Reel 動態圖形剪輯
將原始直式影片轉換為完成的動態圖形剪輯:
設定 → 分析 → 詢問:風格(風格看板)+ 前置選項 → 節奏表 → plan.json
→ 檢查 + 預覽迴圈 → 渲染疊加層 → 合成 → 驗證 → 提供:字幕 + 附加功能
疊加層是使用 HTML/GSAP 逐幀渲染,並具有透明背景(assets/engine.html),因此波斯文字形、字型和漸層都能達到像素完美。你永遠不需要手寫動畫程式碼:你只需撰寫一個 plan.json,列出元件及其時間點。引擎會根據所選的 風格預設 來製作動畫,風格預設會決定外觀、動作、轉場和聲音調色盤,並為每個元件提供預設的音效。
使用使用者的語言(通常是波斯語)與他們交談。保持進度更新簡短。
為何剪輯要感覺「恰到好處」——而不是千篇一律
觀眾會注意到圖形或音效慢了半秒,或者與正在說的話毫無關聯。這就是讓剪輯看起來像業餘的原因。早期的剪輯正是因為這一點而受到批評:裝飾性徽章出現在說話者的臉上,卻與他所說的內容不符。後來,使用者還說剪輯開始看起來 重複。以下四個想法可以解決這兩個問題,而工具強制執行了大部分:
- 錨定在文字上。 任何與語音呼應的文字都使用文字錨點(
"t": "w:رایگان"),使其在音節上彈出,而不是在附近。手動輸入的秒數僅用於純視覺事件。 - 錨定在畫面上。 點擊、頁面變化和版面縮放來自
motion.json事件("t": "m:m12")以及你自己閱讀的帶時間戳的連續畫面。沒有可見點擊的點擊音效就是噪音。 - 保護臉部。 在
plan.avoid中宣告臉部和子母畫面矩形。render.js check隨後會標記任何遮擋它們的元素。在渲染之前修復每個COVERS警告。 - 讓使用者選擇外觀,然後在其中變化。 在設計前先詢問風格(步驟 2)。然後不要每次都依賴相同的配方:變換開場鉤子格式、哪些元件承載想法、以及轉場。
references/styles.md有每個風格的劇本和開場鉤子格式列表。
步驟 0 — 設定(第一次在機器上執行)
python <skill>/scripts/setup.py
安裝 faster-whisper、puppeteer-core 和 gsap 到 ~/.cache/reel-motion-edit/,合成音效庫,並下載 Whisper 模型(large-v3-turbo,約 1.6 GB;如果 huggingface.co 被封鎖或斷線,它會斷點續傳並回退到 hf-mirror.com)。這是「下載你需要的東西」的步驟,所以直接執行,無需詢問。用一句話告訴使用者正在下載什麼。在背景執行:在慢速連線下,模型可能需要一段時間。同時,你可以使用 analyze.py --no-transcript 進行視覺分析,之後再重新執行以獲取文字稿。在更新技能後重新執行 scripts/sfx.py ~/.cache/reel-motion-edit/sfx,以便新的風格聲音存在。
如果你找到有用的額外素材(字型、圖示集、免版稅音效或音樂曲目),將其下載到工作目錄。在 <workdir>/CREDITS.txt 中註明其授權。偏好 OFL/CC0 來源(Google Fonts、Pixabay/Freesound CC0)。內建字型:Vazirmatn(內文)、Lalezar(顯示用)、Changa(科技)、Lemonada(俏皮)、Noto Kufi Arabic(正式)。使用者本地安裝的字型(例如 Morabba、IRANSansX、Yekan Bakh)可以透過 plan.fonts 添加,而且通常是最符合品牌形象的選擇。請查看 %LOCALAPPDATA%\Microsoft\Windows\Fonts 和 C:\Windows\Fonts。
品牌套件。 如果 ~/.config/reel-motion-edit/brand.json 存在,render.js 會自動應用它:style、theme(品牌顏色)、fonts、handle(@用戶名浮水印)、handleCorner、logo。plan 可以覆蓋它;"brand": false 會對單支影片忽略它。當使用者告訴你一個持久的偏好(他們的用戶名、他們總是想要的風格、品牌顏色),主動提議將其儲存在那裡。
步驟 1 — 分析
在影片旁邊建立一個工作目錄(<video dir>/<video name>_edit/)並執行:
python <skill>/scripts/analyze.py "<video>" "<workdir>" --lang fa
然後閱讀 analysis/transcript.txt 和每一張 analysis/sheets/sheet_*.jpg(每張 10 秒,每格 0.5 秒,帶時間戳)。腳本列印出的動作事件(m0 … mN、cut/change)是候選項。對照連續畫面確認每一個,因為捲動也會顯示為「change」。
Whisper 有時會拼錯波斯語或英語產品名稱。記錄修正(它們對字幕和文字錨點很重要:錨定在 Whisper 拼寫的字詞上)。
步驟 2 — 詢問使用者:風格 + 前置選項(在設計任何東西之前)
不同的影片和觀眾想要不同的外觀,而使用者想要選擇。建立一個風格看板:他們的影片一個代表性影格,以全部 7 種預設風格渲染,包含標題、步驟晶片、貼紙和字幕行。首先撰寫一個最小的 plan(影片 + 一個標題 + 一個關鍵字 + 如果影片有步驟則加上步驟),然後執行:
node <skill>/scripts/render.js "<workdir>/plan.json" styleboard <T> # → build/styleboard.jpg
選擇影格 T 為典型影格(不是轉場)。將圖片發送給使用者(SendUserFile,顯示渲染),然後使用 AskUserQuestion 詢問。如果品牌套件已經有 style,則跳過風格問題,除非使用者要求不同的東西。
- Q1 — 風格(最多 4 個選項:首先推薦最適合此內容的風格,附上一行理由,再加上三個對比的替代方案;說其他選項可以透過輸入「其他」來選擇)。預設:
gradient現代漸層、bold流行/Hormozi、neon科技/賽博、minimal簡約 Apple 風格、doodle手繪、retro復古 VHS、news新聞播報。說明在assets/styles.json中(label、feel)。 - Q2 — 前置選項(多選),僅限適用的選項:
- 修剪暫停(跳接):
tighten.py移除長於約 0.45 秒的靜音。最適合 talking-head 影片。在螢幕錄影上,警告說沉默的片段可能是點擊發生的地方。它會改變時間軸,所以它在分析之前執行:對修剪後的檔案重新執行分析。 - 語音清理:
"voice": "enhance"(降噪、低頻切除、臨場感、溫和壓縮)。建議用於手機或房間音訊。 - @用戶名浮水印:如果品牌套件中沒有,則詢問用戶名。
- 背景音樂:僅當使用者有曲目或希望你找一個 CC0 的。它會自動在語音下方進行側鏈壓縮。
- 修剪暫停(跳接):
如果使用者只想要剪輯而不在乎,為他們挑選,告訴他們你選擇了哪種風格以及原因,然後繼續。
步驟 3 — 節奏表(在設計之前思考)
撰寫 <workdir>/beats.md:每拍一行,包含時間範圍、說了什麼、顯示了什麼,以及佈局(全臉 / 螢幕 + 左下角子母畫面 / 手持螢幕 / …)。標記:
- 開場鉤子(前 1–3 秒):從
references/styles.md中選擇一個鉤子格式,如果你知道上次用過的話,選擇一個不同的 - 講者解釋的每個步驟 / 想法
- 回報時刻(顯示結果:「已連線」、「完成」、數字)
- 結尾的行動呼籲
- 佈局變化(相機與螢幕間的縮放):轉場點
- 每個佈局的安全區域:疊加層可以放置而不遮擋臉部、遊標或被示範物件的區域
閱讀 references/styles.md(所選風格的劇本)和 references/creative-direction.md(節奏、放置、音效規則)。它們很短,而且是「雜亂」與「專業」之間的差異。
步驟 4 — plan.json
撰寫 <workdir>/plan.json。所有元件、它們的屬性和預設音效都在 references/components.md 中。在撰寫 plan 之前先閱讀它。最小形狀:
{
"video": "D:/videos/vpn firefox.mp4",
"size": [1080, 1920], "fps": 30,
"style": "neon",
"voice": "enhance",
"handle": {"text": "@your_handle", "corner": "tl"},
"avoid": [{"name": "face", "from": 0, "to": 14.6, "rect": [200, 420, 680, 900]},
{"name": "pip", "from": 15, "to": 29.1, "rect": [0, 1300, 510, 620]}],
"elements": [
{"type": "title", "t": 0, "d": 3.8, "y": 90, "kicker": "آموزش ۶۰ ثانیهای", "lines": ["`VPN` *رایگان*"], "sub": "با سرورهای فایرفاکس"},
{"type": "transition", "t": "m:m3-0.1"},
{"type": "steps", "items": [{"t": "w:گوگل", "label": "جستجو در گوگل", "sub": "`vpn firefox github`"}], "hide": [[29.0, 34.1]]},
{"type": "keyword", "t": "w:رایگان", "x": 540, "y": 1640, "text": "رایگان", "emoji": "🎁"},
{"type": "success", "t": "w:وصل", "x": 405, "y": 678, "title": "وصل شدی!"},
{"type": "cta", "t": 57.4, "items": [{"text": "سیو کن", "icon": "save"}, {"text": "فالو کن", "icon": "follow"}]}
],
"camera": [{"t": "w:رایگان", "d": 1.2, "type": "punch", "scale": 1.12, "cx": 540, "cy": 700}],
"sfx": [{"t": 16.2, "name": "typing", "db": -8}],
"cover": {"lines": ["`VPN` *رایگان*"], "sub": "آموزش ۶۰ ثانیهای"}
}
讓風格決定外觀。 保持視覺屬性(theme 顏色、keyword style/rotate/from、transition kind、title anim、字幕樣式)未設定,除非你有語義上的原因(錯誤用紅色、品牌顏色)。預設會填入它們,而這正是讓風格感覺不同的原因。沒有 kind 的轉場會循環使用該風格的轉場。plan 中的 theme 僅覆蓋預設(例如產品的品牌顏色)。
文字語法:*word* 或 *two words* = 強調,`latin` = 隔離的從左至右(LTR)執行(防止「VPN」/URL 在從右至左(RTL)文字中翻轉)。
步驟 5 — 檢查、預覽、修正(迴圈)
node <skill>/scripts/render.js "<workdir>/plan.json" check
node <skill>/scripts/render.js "<workdir>/plan.json" preview 1 5.5 15.8 21.1 27.4 54
check 會列印解析後的時間軸並檢查:
COVERS:元件覆蓋了受保護區域OFFFRAMECLUTTER:同時有超過 3 個疊加層SFXPILE:音效堆疊在 0.35 秒內ORDER:文字錨點點擊了更早的出現,所以使用w:word#2
修復每個問題。然後查看 build/preview.jpg:為每個重要元件選擇動畫中間的時間點,並檢查標註和漣漪是否精確位於它們的目標上。從全解析度影格讀取座標(ffmpeg -ss T -i video -frames:v 1 f.png),而不是從縮圖猜測。迭代直到正確為止。預覽成本低,完整渲染則不然。
步驟 6 — 渲染和合成
node <skill>/scripts/render.js "<workdir>/plan.json" full # build/overlay.mov(≈ 每分鐘影片 3–6 分鐘)
python <skill>/scripts/compose.py "<workdir>/plan.json" --out "<video dir>/<name> - edit.mp4"
node <skill>/scripts/render.js "<workdir>/plan.json" cover <T> # build/cover.jpg — 貼文封面(模糊影格 T + 標題)
在背景執行完整渲染。compose.py 執行以下操作:
- 僅對影片應用相機移動
- 疊加圖形
- 如果設定了
voice清理則應用 - 在語音下方混合音效床,如果設定了音樂則加上側鏈壓縮:
"music": {"file": "...", "db": -20} - 歸一化至 -14 LUFS
永遠不要覆蓋原始影片。寫入一個新檔案,並在重新渲染時加上版本後綴(- edit v2)。
步驟 7 — 驗證
為輸出製作一個連續畫面(ffmpeg -i out.mp4 -vf "fps=1/2,scale=216:-1,tile=10x3" sheet.jpg)並查看它。檢查持續時間是否匹配以及音訊是否存在。誠實報告你檢查了什麼(影格)以及你不能檢查什麼(你無法聆聽;音效時序是根據事件列表驗證的,不是透過耳朵)。
步驟 8 — 提供字幕和附加功能(始終在最後)
一旦剪輯交付,使用 AskUserQuestion(在適用時使用多選)詢問。僅提供尚未完成的選項:
- 字幕:來自
references/caption-styles.md的 3–4 種樣式,首先推薦所選風格的預設(styles.json 中的captions),並根據這個影片說明理由。 - 封面圖片用於貼文(
render.js cover)。 - Instagram 說明文字:從文字稿撰寫
<workdir>/post.txt:一個鉤子行、2–4 行簡短的價值內容、行動呼籲、講者提到的連結或評論關鍵字,以及 8–15 個相關的波斯語 + 英語主題標籤。 - 儲存到品牌套件:所選的風格、用戶名和顏色,以便下一支影片從那裡開始。
- 另一個風格版本:使用不同的
style重新渲染同一個 plan,用於 A/B 測試(僅疊加層改變)。
對於字幕:
python <skill>/scripts/captions.py "<workdir>" --style karaoke --zones "0-14.6:1400,29.4-33.8:1400" --default-y 1170 --keywords "رایگان,VPN" --fix "غلط=درست,وی پی این=VPN"
校對列印的區塊。使用 --fix 修正 Whisper 拼寫;多字來源會合併標記。將 "captions": {"file": "captions.json"} 添加到 plan(樣式預設為預設的;設定 "style" 以覆蓋),執行 check(字幕也不能遮擋臉部或貼紙),然後作為新版本再次渲染和合成。
常見陷阱
- 螢幕座標中的元件(點擊、強調、標註箭頭)如果相機移動縮放同一部分,會對不準。僅在 talking-head 部分使用相機移動。
- Camtasia 風格的臉部與螢幕間動態縮放大約持續 0.5 秒。將轉場元件放在縮放的開始處,並且不要在那個視窗中將文字放在螢幕上。
steps.hide在全臉部分隱藏步驟晶片,並在之後重新顯示。- Whisper 單字時間戳在暫停後的第一個字可能有大約 0.1 秒的延遲。對於強烈的衝擊(標題猛擊),使用
-0.05微調。 - 不是 1080×1920 的來源(例如 608×1080 的手機匯出)會由 compose 和 preview 縮放/裁剪到 plan 的大小。Plan 座標始終以 plan 大小的像素為單位,因此將從來源影格讀取的座標乘以
1080 / source_width。 - 手持手機拍攝顯示器畫面:螢幕會漂移,因此固定在螢幕上的元件(點擊、強調、箭頭)無法保持在目標上。改用結構(步驟)、邊緣的單字錨定貼紙,以及全影格轉場。
- 標題預設會有一個深色頂部遮罩(設定
"scrim": false以移除)。它可以使標題在明亮螢幕上保持可讀。 - 保持講者自己的語音不變(除了響度歸一化之外,沒有 EQ/壓縮)。