Morph Edit (動態 B-roll) 是做什麼的?
你為創作者影片製作動態圖形片段。每個片段都是一個永不剪切的形狀:它會變形其大小、圓角和顏色,同時內容以短暫模糊效果切換。游標以真實的點擊和拖曳驅動變化,且每次變化都精準落在一個說出的詞語上。
輸出是一組片段,創作者可直接拖入其剪輯軟體。你也會提供他們一份已插入這些片段的預覽渲染影片,以及兩個 HTML 頁面:一個用於逐步檢視片段,另一個用於比較原始與預覽版本。
你需要的所有檔案都在此技能資料夾中:
engine/:動畫引擎 (motion.js)、頁面外殼 (base.css)、build.py(將片段轉為自包含 HTML)、render.js(含動態模糊的逐格渲染)、beats.js(靜態畫格聯絡表)、字型 (Geist, OFL)。scripts/:setup.sh、inspect_video.py、words.py、composite.py、make_pages.py。reference/engine-api.md:如何撰寫片段的說明。在撰寫第一個片段前務必閱讀。examples/opus-aoe2/:針對一段 54 秒真實影片完成的六個片段,請以此作為品質標竿與起點。
以下 $SKILL 代表此技能資料夾的路徑。請在使用者的專案資料夾中,於 motion/ 目錄下工作。
1. 設定(僅首次執行)
bash $SKILL/scripts/setup.sh ./motion
此指令會檢查 Node、Python 3 與 ffmpeg,並將 Playwright + Chromium 安裝至 motion/node_modules。執行所有引擎腳本時,請加上 NODE_PATH=./motion/node_modules。
2. 訪談
使用 AskUserQuestion 工具,儘量控制在一輪內。你需要:
- 影片。 一個路徑。將其複製或引用為
motion/work/source.*。 - 逐字稿。 可選。如果沒有(或只有純文字),請使用
scripts/transcribe.py轉錄音訊(見步驟 3)。這會提供真實的詞語時間戳記,比 SRT 估計更準確。 - 密度:
- 輕:每分鐘 2–4 個片段,僅在最強烈的時刻。
- 中(預設):每分鐘 4–7 個。
- 重:覆蓋大部分台詞,僅留短暫的臉部畫面空白。
- 外觀:
- 預設色板:暖灰色背景、黑與白元件、一個橘色強調色。
- 或使用他們的品牌色,並可選字體。請他們將 Logo、截圖或品牌色放入
motion/inputs/,並讀取這些檔案。
- 任何應避免或包含的內容。 應該保留在臉部畫面的台詞、要顯示的實際數字或名稱、要重現的產品截圖。
跳過使用者已回答的任何問題。
3. 檢查影片素材
python3 $SKILL/scripts/inspect_video.py motion/work/source.mp4 motion/work
python3 $SKILL/scripts/words.py transcript.srt > motion/work/words.txt
# 若無逐字稿(或你要精確詞語時間):改為轉錄音訊
motion/.venv/bin/python $SKILL/scripts/transcribe.py motion/work/source.mp4 motion/work
transcribe.py 會寫出 words.txt 與 transcript.srt。向使用者顯示逐字稿,以便他們在規劃前修正聽錯的名稱或術語。
你自己檢視 motion/work/contact.png。video.json 提供解析度、fps 以及佈局章節:
- full: 說話者填滿畫面。
- pip: 說話者在一個框內,其餘區域空白。包含框的位置,以及若框的尺寸或位置改變時的警告。
片段必須符合影片的解析度與 fps。來自 SRT 的詞語時間是估計值(±0.2 秒);請據此處理。
4. 規劃,並在編碼前取得批准
顯示一個表格,每個片段一行:
| # | 進點–出點 | 涵蓋的台詞 | 形狀在哪些詞語上做什麼 | 處理方式 | 原因 |
創意方向:決定每個片段佔據畫面的多少比例。 這是最重要的決定;請為每個片段單獨做出決定並說明理由。
- 全螢幕插播。 畫面全是說話者,且台詞描述某個可視的內容:產品、流程、比較、數字、章節轉換。
- 在該想法持續期間(3–10秒)切換出去,然後再回到臉部。
- 不要在鉤子出現的第一秒、或是個人、情感或意見型台詞時切換出去。
- 每次插播之間至少保留約 2 秒的臉部畫面。
- 空白區域中的面板。 剪輯已經留下空間:PiP 框、分割畫面、一個純色區域。
- 渲染一個透明片段(
bg:null),置中於空白區域,其大小在每一刻都保持與說話者框的距離。 - 它可以持續很長時間(15秒以上)作為連續的變形,因為說話者始終在畫面上。
- 如果
inspect_video.py報告框正在變動,詢問該變動是否為預期,然後為最大的框設定大小,或在變動點分割面板。
- 渲染一個透明片段(
- 無。 台詞是關於說話者本人的,或者與另一個片段太接近。
內容規則:
- 顯示主題的真實物件:資料夾、終端機、檔案、產品、結果。從詞語中提取。將每個想法映射到
reference/engine-api.md詞彙表中的互動(藥丸+點擊、進度、勾選、狀態島、附拖曳的卡片、滑桿、切換開關、分頁、圖表+工具提示、搜尋/篩選、檔案拖放、終端打字、並排比較、章節卡片)。 - 絕不發明數字、引言、價格或結果。 使用相對條形圖、骨架文字行或取自逐字稿的標籤,並列出哪些是示意性的。僅在使用者提供實際數字時才放入。
- 一個片段一個想法。連續的片段(整個 PiP 章節)可作為一個帶有多個狀態的長片段。
- 節奏配合說話速度,而非音樂:每個說話拍子一次變化,間隔約 0.4–1.2 秒。
等待使用者批准或編輯規劃。
5. 建構
根據 reference/engine-api.md 與範例,在 motion/clips/NN-名稱.html 中為每個片段撰寫一個 fragment。然後建構:
python3 $SKILL/engine/build.py motion/dist motion/clips/*.html
將每個狀態變化對齊到對應的詞語:片段本地時間 = 詞語時間 − 片段進點時間。
6. 在關鍵詞語上檢查靜態畫格
NODE_PATH=./motion/node_modules node $SKILL/engine/beats.js motion/dist/NN-名稱.html motion/work/NN.png 0.4 1.2 2.1 …
選取每個狀態穩定後的時間點,以及少數中間變形時刻。逐一檢視每個聯絡表。修復任何擁擠、裁切、無法閱讀或詞語對不準的問題,或游標跑出畫面的情況。然後再次檢查。面板片段在聯絡表中會渲染在黑色背景上,方便你判斷。
7. 渲染
NODE_PATH=./motion/node_modules node $SKILL/engine/render.js motion/dist/NN-名稱.html motion/out/NN-名稱_0m32s40.mp4 30000/1001
- 使用影片的 fps。
- 面板片段(
bg:null)必須輸出為.mov,這會產生帶 Alpha 的 ProRes 4444 格式。 - 根據時間軸進點命名每個檔案(
0m32s40= 0:32.40)。 - 渲染時每個影格會處理 4 個子影格,因此比即時播放慢。在多核心機器上可同時執行兩個片段。
8. 交付
寫入 motion/plan.json(結構見 reference/engine-api.md)。為 UI 音效,為每個片段提供 "sfx": [[片段本地時間, 種類], …] 列表,取自其提示:click 和 toggle 用於游標點擊,pickup/drop 用於拖曳開始/釋放,whoosh 用於形狀變形,pop 用於介紹和徽章,rise/fall 用於條形圖,type 用於打字,tick 用於項目出現,shutter 用於截圖,success 用於勾選。然後:
python3 $SKILL/scripts/composite.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/sfx.py motion/plan.json motion/out/preview.mp4 # UI 音效,如果使用者想要的話
python3 $SKILL/scripts/make_pages.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/make_gallery.py motion/plan.json motion/out/preview.mp4
使用者會收到,全部在 motion/out/ 底下:
- 片段
TIMING.md:檔案、進點、出點、涵蓋的台詞、處理方式,以及哪些是示意性的preview.mp4:插入片段後的影片,使用硬剪輯、原始音訊(以及啟用時的音效)sfx/:每個片段的音效獨立 WAV 檔,方便在剪輯軟體中混合index.html:所有片段同時在一個網格中播放,包含完整預覽與其他頁面的連結(請先開啟此頁)viewer.html:逐步檢視片段compare.html:原始影片 vs 預覽,同步顯示,可選並排、堆疊或擦拭
明確說明預覽僅供審閱:最終剪輯時,使用者應將片段放入自己的剪輯軟體,在那裡他們可以調整時機、加入轉場和混合音訊。
訂閱卡片(可選)
詢問創作者是否希望在他們的呼籲行動台詞上放置一個訂閱結尾卡,以及一兩個簡短的提醒卡。模板位於 $SKILL/templates/subscribe/ 中的片段 fragment(end-card.html、reminder.html)。將一個複製到 motion/clips/,然後:
- 替換
__CHANNEL__、__HANDLE__與__AVATAR__(創作者的 Logo 或照片,作為 data URI;若無圖片,則在圓圈中使用一個字母)。請向創作者索取這些資訊;切勿猜測名稱或代號。 - 重新調整
<script>頂部的常數時間(IN、點擊時間、T)以配合創作者自己的詞語。結尾卡會在創作者說出 Share、Subscribe、Bell、Like 和 Comment 時點擊;提醒卡則點擊 Subscribe 和 Bell。 - 像其他片段一樣建構、檢查靜態畫格、渲染並加入
plan.json。將卡片渲染為透明.mov面板,使其疊在影片之上。
字幕(可選)
製作一份口語語言的 SRT 與一份英文 SRT,以作為隱藏式字幕上傳(非燒錄)。在 motion/work/cap/ 中工作:
motion/.venv/bin/python $SKILL/scripts/captions/find_gaps.py motion/work/words.txt "<video>":Whisper 在長影片上可能會漏掉整段語音。它會印出缺口;使用retx.py "<video>" "<缺口列表>" motion/work/gapwords.json [語言]重新轉錄這些缺口。python3 $SKILL/scripts/captions/make_cues.py motion/work/words.txt motion/work/gapwords.json motion/work/cap會寫入 cue 與四個區塊。- 使用
templates/caption_brief.md平行翻譯四個區塊(四個子代理,每個區塊一個)。每個區塊寫出out1..4.json,包含每個 cue 的{"i","orig","en"}。 - 修正被標記的 cue,然後執行
python3 $SKILL/scripts/captions/build_srt.py motion/work/cap motion/out/captions寫出captions_original.srt和captions_english.srt(每行兩個平衡行,最多 42 個字元)。 - 告知創作者在發佈前,先在 VLC 或非公開上傳中測試 SRT。
樣式預設值
使用者的品牌會覆蓋這些設定。
- 顏色: 畫布
#E9E7E2、墨水#0B0B0B、白色元件、一個強調色#FF5A1F。在暗色影片上的面板片段使用淺色形狀(#F4F2EE)。 - 字體與圖示: Geist 用於 UI 文字,Geist Mono 用於程式碼、檔案名稱和終端機。一個圖示集,一種筆畫粗細(
M.icon)。 - 動態: 彈簧,最多只有極小的過衝。前緣和後緣使用不同的彈簧,使指示器有拉伸感。鏡頭會縮放,使每個狀態填滿畫面。
- 禁用: 彈性緩動、粒子、光暈、UI 鍍鉻上的漸層、混合圖示粗細、空閒時間、任何看起來像模板的東西、偽造數據。
注意事項
- 絕對不要在鏡頭縮放的任何元素上設定
will-change;文字會渲染模糊。 - 在變形容器內更換文字需要自己獨立的進出時機(
M.visdin/lin/lout),否則新舊文字會重疊。 mix-blend-mode: difference標籤必須位於具有該混合模式本身的圖層中。使用濾鏡的父層會隔離它們。- 需要滑入反白下方的項目需使用
M.FAST彈簧,否則反排行會短暫空白。 - 在每個鏡頭縮放期間(包括變形中),保持游標在畫面內。
- 來自 SRT 的詞語估計在同一個 cue 內會漂移;盡可能將重要變化放在某個 cue 的第一個或最後一個詞語。
- 片段以保持其最後一個狀態結束;合成器會在該片段時槽較長時保持最後一個影格。