Communitygithub.com

dmtrKovalenko/fframes

使用程式碼建立、動畫化、預覽和渲染影片,搭配 fframes(Rust、SVG 場景、ffmpeg 編碼、Skia GPU 渲染)。每當使用者需要影片、動畫、動態圖形、解說、宣傳、社交短片、標題卡、播客視覺、歌詞/字幕影片或任何以程式製作的 .mp4/.webm,或要求更改、修正、加速或檢查 fframes 影片時使用。涵蓋安裝 fframes、建立專案、設計美觀動畫、3D 鏡頭(`fframes::three_d`,three.js 風格場景)、音效(音樂、語音、音效、音量)、在即時預覽視窗中觀看,以及無需觀看即可檢查結果:PNG 影格與聯絡表、自動問題偵測、音量數值、快速草稿與範圍渲染。

fframes 是什麼?

fframes 是一個 Rust 函式庫,可讓開發者以程式碼驅動的方式建立影片,從簡單的動畫到複雜的動態圖形和 3D 場景皆可處理。其核心概念是將影片定義為一個 Rust 結構體,並實作 `render_frame` 方法,為每個影格回傳一個 SVG 樹狀結構,利用 `svgr!` 巨集來建立標記。場景可分割時間軸,`timeline!` 和彈簧(spring)負責動畫數值,音訊地圖(audio map)則處理聲音的擺放,最終由 ffmpeg 編碼輸出。 這個技能提供完整的 CLI 工具,用於渲染、預覽、偵錯和導出影片。開發者可以使用 `preview` 命令進行即時 GPU 加速預覽,使用 `strip` 和 `onion` 命令檢查影格序列和動畫軌跡,以及使用 `inspect` 命令自動偵測常見問題,例如缺失的字型或超出畫面的文字。它也支援音訊分析(LUFS、真實峰值)和 3D 場景(`fframes::three_d`)。 fframes 的主要優勢在於其效能和靈活性。預設的 Skia GPU 後端渲染速度比 CPU 後端快約 10 倍,並支援即時預覽視窗。專案產生器可建立單一場景或多場景模板,支援多種格式(橫向、直向、方形、UHD)。開發者可以在 `cargo-fframes` 工具產生的標準專案結構中工作,並使用一個一致的指令集來處理所有影片製作流程。 這個技能還強調謹慎的設計規劃,要求開發者在編寫程式碼之前先確定目標、受眾、音效和動畫設計。它強烈反對「模板化」或「通用」的結果,鼓勵針對每個專案設計獨特的動畫和視覺風格。對於需要調整時間點或查看特定影格細節的情況,它提供了精確的指定方式(時間碼、場景名稱、百分比),以及用於詳細檢查的影格裁切和縮放功能。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/dmtrKovalenko/fframes/tree/HEAD/skills/fframes-video

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

使用 fframes 製作影片

fframes 是一個 Rust 函式庫,可從程式碼渲染影片。影片是一個 Rust 結構體,帶有 render_frame(frame) -> Svgr 方法:對於每個影格,它回傳一個 SVG 樹,使用 svgr! 巨集(帶有 {rust 表達式} 的 SVG 標記)建構。場景分割時間軸,timeline! 和彈簧(spring)負責動畫數值,音訊地圖放置聲音,而 ffmpeg 則進行編碼。

每個專案都有一個命令列(來自 fframes::cli)。用它來處理所有事情:渲染影片、開啟即時預覽視窗,以及以檔案形式檢視影格、聯絡表和音量數值。在設計之前請閱讀 references/design.md,在編寫程式碼時請閱讀 references/api.md,音效相關請閱讀 references/audio.md,3D 鏡頭(fframes::three_d)請閱讀 references/3d.md。

當比對提供的影片時,請先遵循 references/design.md 中的參考分析指南。其剪輯、節奏和動作優先於下方設計預設值;快速的剪輯和故意的黑畫面可能是所要求結果的一部分。

在開始任何其他事情之前的兩條規則

在編寫程式碼之前先規劃

不要直接開啟模板並開始製作動畫。首先:

  1. 確定簡報內容:誰在看它以及在哪個平台觀看(平台決定格式和長度)、觀看者必須記住的一件事、調性,以及現有的素材(標誌、產品鏡頭、影片片段、音樂、旁白)。向使用者詢問缺少且重要的部分。切勿編造產品事實、數字或引言。
  2. 當影片配合音樂或語音剪輯時,請先選擇音效。其節奏、拍子和樂句決定了所有其他元素的時間安排。
  3. 首先規劃動態設計,將動態設計與聲音峰值同步,以形成一個獨特的流程:元素將從何處出現,它們將如何轉換。嘗試為每個場景創建一個獨特的動態設計,使其看起來獨特且精緻。影片不應該看起來像幻燈片。
  4. 嘗試推理觀看最終影片的人的觀感,並相應地調整您所做的每個設計元素:流程、節奏、拍子、動態和顏色。

不要有「模板痕跡」(Slop)

模板痕跡是一種由預設選擇組成的影片:它可能只更改了文字就能套用在任何產品上,而觀眾在一秒鐘內就能認出它。除非使用者要求,否則請勿提供:

  • 模板遺留物:起始版面配置、顏色、字體或裝飾、佔位文字、假標誌、虛構數字。
  • 節拍轟炸:整個影格在每一個拍子上縮放、搖晃或閃爍。將小東西(一條線條、一個單詞、一個火花)同步到節奏上,並且只在少數剪輯點才改變整個影格。
  • 萬用動畫:每個元素都以相同的緩動曲線和持續時間向上淡入 40 像素。
  • 靜態場景:一個東西出現,保持不動,然後淡出,而其他所有東西都不動。
  • 通用文案:「推出」、「釋放」、「無縫」、「次世代」、三個詞的標語(「快速。簡單。強大。」)。用一般人會說的方式來撰寫螢幕上的文字。
  • 一般性的文字:文字數量應有限且精準。

相反地,為每個元素賦予一個與主題相關的理由,並移除那些沒有理由的元素。將精力花在細節和動畫上,而不是文字上:次要動畫、交錯入場、繪製的線條、彼此反應的物體、跨剪輯攜帶的元素。在向使用者展示任何東西之前,先查看一個序列並問問自己,如果只更改文字,這個影片是否仍能套用在不同的產品上。如果可以,那就改變想法,而不是改變顏色。

1. 安裝

從 https://rustup.rs 安裝 Rust,然後安裝建構 ffmpeg 所需的系統函式庫:

# macOS
brew install pkg-config ffmpeg x264 x265 opus nasm ninja
# Debian / Ubuntu
sudo apt-get install -y yasm nasm ffmpeg libx264-dev libx265-dev libopus-dev libclang-dev clang ninja-build libvpx-dev libasound2-dev
# Arch
sudo pacman -S ninja yasm nasm ffmpeg x264 x265 opus clang

Windows 會連結預先建置的 FFmpeg 9 共享建置版本(設定 FFMPEG_DIR 指向從 BtbN/FFmpeg-Builds 解壓縮的 ffmpeg-n9.0-latest-win64-gpl-shared 建置版本,將其 bin 資料夾加入 PATH,使用 winget install LLVM.LLVM 安裝 LLVM,並設定 LIBCLANG_PATH)。詳細資訊請參閱 fframes README。

2. 建立專案

curl -fsSL https://raw.githubusercontent.com/dmtrKovalenko/fframes/main/scripts/new-video.sh | bash -s -- my-video --yes
# 或一次性安裝產生器並直接使用:
cargo install --locked cargo-fframes
cargo fframes new my-video --format landscape --fps 30 --yes

選項:--template single-scene|multi-scene、--format landscape|portrait|square|uhd、--fps、--title、--backend、--dir。此專案依賴於與已安裝 cargo-fframes 匹配的 fframes 版本;使用 --git 則會改用儲存庫的 main 分支。務必傳遞 --yes 以避免等待輸入。

模板:

  • single-scene(預設):單一場景。它適用於所有格式;從這裡開始製作單鏡頭短片、標題卡和直式影片。
  • multi-scene:兩個場景。從這裡開始製作包含多個場景的任何內容;它只接受 landscape 和 uhd 格式。

模板內容是展示 API 的佔位程式碼。請將其版面配置、顏色、字體和裝飾替換為針對使用者要求影片所設計的內容。

使用 Skia GPU 後端(預設)。 cargo fframes new 會選擇 Metal(macOS)或 Vulkan(Linux、Windows)上的 Skia。其渲染速度比 CPU 後端快約 10 倍,並提供即時的 preview 視窗。在 macOS 和 Linux 上,首次建置會下載預先建置的 Skia 和 ffmpeg,並且只編譯 Rust 依賴項(約一分鐘;其他目標,或同時使用 metal 和 vulkan,則會從原始碼編譯 Skia,大約需要 20 分鐘)。立即啟動它並在建置過程中撰寫影片:

cd my-video && cargo build --release        # 在背景執行,首次建置是最慢的

--backend cpu 不需要 Skia,但沒有預覽視窗;僅在沒有 GPU 時才選擇它。

專案渲染為產生的結構:

my-video/
  src/lib.rs        # 影片(來自模板)
  src/main.rs       # 命令列
  media/            # 編譯進二進位檔的字型、圖片和音訊(一個起始字型)
  README.md         # 下方的命令

下方的每個命令都是 cargo run --release -- <command>。定義一個簡短的 shell 函式(變數如 R="cargo run --release --" 在 zsh(macOS shell)中無法正確分割單詞):

R() { cargo run --release -- "$@"; }

3. 開發迴圈

使用此技能時完全不要撰寫測試。 不要建立單元測試、整合測試、快照測試或視覺回歸測試、測試模組或測試框架。使用 inspect、渲染的影格、聯絡表、音訊檢查和原生預覽來驗證影片。

預覽,不要渲染。 如果影片使用 GPU 渲染後端且此機器上有 GPU,請執行原生預覽(或向使用者顯示命令),而不是在每次更改後再次渲染影片。一旦變更準備好審查:

  1. 在可複製的 shell 程式碼區塊中顯示完整的命令,使用實際的專案路徑和套件名稱;不要要求使用者定義 $R 輔助函式。例如:cd /absolute/path/to/fframes && cargo run --release -p my-video -- preview 0s。
  2. 明確提供為使用者執行該預覽的選項。如果他們已授權開啟或重新整理預覽,則顯示命令並在該授權範圍內繼續。

在請求的變更之後,將命令的開始時間設定為變更區段當下或之前的特定秒數,並提供足夠的引導時間以查看其入場或轉換。例如,preview 8.5s 讓使用者無需重播開頭即可審查大約 9 秒處的變更。說明他們將看到哪個區段。當使用者請求最終匯出時,渲染完整影片;如果該請求已經明確,則不需要再確認。

在每次變更之後:

  1. $R timeline 列出場景及其影格和秒數範圍,以及每個音軌。在此先檢查結構和節奏,然後再檢查像素。
  2. $R inspect 每 0.25 秒檢查一個影格,加上每個場景的第一個和最後一個影格。它會回報缺失的圖片、字型或字形、被畫布邊緣截斷的文字、無效的 SVG(零尺寸的矩形、錯誤的半徑)、損壞的變換和中斷(panic),每個都帶有其時間和場景。遇到錯誤時會以代碼 2 退出。修正它回報的所有問題。僅出現在場景前幾個影格的警告通常是入場動畫;使用 strip 檢查它。
  3. $R strip <scene or range> -n 12 寫入一個聯絡表(strip.png):在一個帶有標籤的圖片中均勻間隔的影格。使用您的圖片工具開啟它。這是判斷版面配置、節奏和動作最快的方式。$R strip 2s,5s,9s 將選定的時間並排放置。
  4. $R frame Intro@end,Outro@50% 將全尺寸 PNG 寫入 frames/ 以進行細節檢查(排版、對齊、對比度),並列印在這些影格中發現的問題。在銳利的縮放裁切上判斷小細節(元素之間的接觸、邊緣、小形狀),切勿在縮小的影格上判斷:$R frame 3s --crop 1100,520,240,120(影片像素,放大到大約 960 像素寬)。--ids 會勾勒出每個具有 id 的元素並標示其名稱,以找出哪個形狀是哪個。
  5. $R onion "[email protected]@1s" -n 6 將影格混合成一張圖片(onion.png)以顯示動作的路徑和間距:緩動、超調、交錯。
  6. $R preview Intro 為使用者開啟一個帶有聲音的即時視窗(空白鍵播放/暫停、h/l 前後快進一秒、j/k 前後跳一個影格、q 離開)。它會阻塞直到關閉,因此在為使用者執行時請在背景啟動它。如上所述顯示命令並提供啟動它的選項;在編輯後,使用接近變更處的特定秒數。

當需要編碼樣本時,$R render Intro --draft 會以一半解析度編碼一個場景。$R render 會為請求的最終匯出寫入完整影片。

在展示完成的影片之前,執行 $R inspect --pops:它會以小尺寸渲染每個影格,並警告關於突然出現(pop)的部分,即畫面中在兩個靜止影格之間於一個影格內變化的部分,例如一個元素出現、消失或跳到另一個元素前面,而不是移動到那裡。每個警告都會給出 frame ... --crop ... 命令來查看它;相同區域的重複(計數器、閃爍的燈光)會被分組為一個警告。

規則:

  • 在說任何東西看起來不錯之前,請先查看 PNG 圖片。
  • 優先使用 strip 而不是多次 frame 呼叫;當只需要構圖時,加上 --scale 0.5。
  • 在解析輸出時加上 --json:結果會輸出到標準輸出(stdout),進度則輸出到標準錯誤(stderr)。
  • 保持使用 --release:偵錯建置版本的渲染速度會慢很多倍。

指定時間

120(影格)、3.2s、500ms、1:05.5、50%、start、end;按結構體名稱指定場景,Intro(也會匹配 IntroScene,不區分大小寫)、#3(場景索引)、Intro[1](該類型場景的第二個);在場景內部 [email protected]、Intro@12、Intro@50%、Intro@end。範圍:a..b(結尾不包含)、a..、..b、all,或使用場景名稱代表整個場景。用逗號分隔多個時間點。

所有命令

命令用途
timeline查看場景、持續時間、音軌及其混音設定
inspect [RANGE] [--every 0.1s | --all-frames] [--fail-on warning] [--pops]在不渲染像素的情況下發現問題;--pops 也找出突然出現或消失的元素
strip [RANGE | TIMES] -n N [--columns 4] [--width 480] [--crop x,y,w,h]在一張圖片中審查流程和動作
frame TIMES [-o dir] [--svg] [--crop x,y,w,h] [--zoom N] [--ids]選定影格的全尺寸 PNG(以及佈局後的 SVG)、銳利裁切、標籤元素
onion RANGE -n N查看動作的軌跡和緩動曲線
svg TIME將給定影格的最終 SVG 以文字形式讀取(位置、文字、顏色)
preview [TIME] [--paused] [--mute]為使用者提供帶有聲音的即時視窗
render [RANGE] [-o out.mp4] [--draft]編碼影片或其一部分(音訊也相應裁剪)
audio analyze [RANGE] [--waveform w.png]音量(LUFS)、真實峰值、削波、靜音、按場景顯示
audio at TIMES在特定時刻播放哪些聲音,以及它們在檔案中的位置和音量
audio render [RANGE] -o a.wav將混音輸出為 WAV 檔案

瀏覽器編輯器

fframes 也有一個帶有時間軸和拖曳功能的網路編輯器,當有人想要以互動方式調整影片時非常有用。它執行編譯為 WebAssembly 的影片,需要 Node.js 和 wasm-pack;設定位於 fframes 儲存庫中 hello-world 範例的 editor/ 資料夾(https://github.com/dmtrKovalenko/fframes/tree/main/examples/hello-world)。當使用者要求 GUI 編輯器時提及它。用於觀看請使用 preview,用於您自己的審查請使用 CLI。

4. 撰寫影片

impl Video for MyVideo<'_> {
    const FPS: usize = 30; const WIDTH: usize = 1920; const HEIGHT: usize = 1080;
    fn duration(&self) -> Duration<'_> { Duration::Auto }            // 場景時長總和
    fn audio(&self) -> AudioMap<'_> { AudioMap::none() }              // 參閱 references/audio.md
    fn define_scenes(&self) -> Scenes<'_> { Scenes::from(vec![&self.intro as &dyn Scene, &self.main]) }
    fn render_frame<'a>(&'a self, frame: Frame, ctx: &FFramesContext<'a, '_>) -> Svgr<'a> {
        fframes::svgr!(<svg xmlns="http://www.w3.org/2000/svg" width={Self::WIDTH} height={Self::HEIGHT}>
            <rect width={Self::WIDTH} height={Self::HEIGHT} fill={BACKGROUND} />
            {ctx.render_scenes(&frame)}
        </svg>)
    }
}
  • 每個想法對應一個場景,每個場景 2-6 秒。在場景內部,frame.seconds() 從場景開始計時。
  • 預設情況下,在 svgr! 屬性中直接使用 frame.animate(fframes::timeline!(...)) 來處理具有固定值的動畫。svgr! 將這些動畫提升為快取的靜態變數。在時間軸中內聯定義緩動曲線,包括 Easing::Spring { mass: 1.0, stiffness: 180.0, damping: 20.0 };命名常數是可選的。對於彈簧動畫,請省略其結束時間,以便其自然停止。

…

[內容因長度而被截斷]

相關技能