Motion explainer(影片加強版)— 動畫講原理、照片當證據、AI 影片帶情緒
這個技能把「上網查資料 → 寫腳本 → 中文旁白 → 一格一格做動畫 → 字幕 → 配色 → 找授權照片、生成示意圖 → 生成 AI 影片 → 自我審查 → 輸出 MP4」串成一條固定流程。和基本版 motion-explainer 相比,多了第 7.5 節的圖片層、第 7.6 節的 AI 影片層,還有第 4 節的修正唸錯的字;其他步驟完全相同。影片素材以 AI 生成為主:新聞、宣傳片、圖庫影片幾乎都有版權,不剪進教學片。它站在三個東西的肩膀上:
- HyperFrames(HeyGen 開源,HTML + GSAP 輸出 MP4)與它的官方 skills,特別是
/hyperframes入口和/faceless-explainer工作流。做法以官方為準。 - 本 repo 的
motion-design(品味規則:緩動、節奏、停留、中文排版)與review-loop(contact sheet 自我審查)。好不好看以這兩個為準。 - 本資料夾
scripts/的工具:把官方流程沒處理好的中文旁白、字幕、字型一致性和三色主題補起來。
references/lessons.md 是實戰踩過的坑,動工前必讀,每一條都在第一支片裡真的發生過。
0. 環境檢查(第一次用時)
- 先跑
python scripts/hw_check.py --project <專案>:它會偵測 CPU、記憶體、GPU 和硬碟,並建議要用哪個旁白引擎、--workers設多少、sub-agent 要不要分批派。照references/hardware.md的說明告訴使用者;那些建議都是推估,不是跑分。 - Node.js 22+、ffmpeg/ffprobe、Python 3 + Pillow + fonttools(
pip install fonttools;裝了brotli字型會輸出成 woff2,沒裝就輸出 ttf)。 - HyperFrames CLI:
npm install -g hyperframes,再跑hyperframes doctor(Docker、Whisper、Kokoro、MusicGen 都是選配)。 - 官方 skills:
hyperframes skills update,做這類片還要hyperframes skills update faceless-explainer。 - 匿名使用統計預設開啟,問使用者要不要
hyperframes telemetry disable。 - TTS(擇一,問使用者):
- edge-tts(預設):
pip install edge-tts,不需要 GPU,產生時要連網。台灣口音有zh-TW-HsiaoChenNeural(女)、zh-TW-HsiaoYuNeural(女)、zh-TW-YunJheNeural(男)。 - Breeze TTS 2(進階):本機 NVIDIA GPU(約 7.7 GB VRAM,建議 12 GB 以上;模型檔約 7 GB),可以用文字描述來設計聲音,再做聲音複製,口音和情緒的控制最細。
- 其他引擎也可以:只要能為每一句輸出
assets/voice/raw/NN.wav。英文片可以用 HyperFrames 內建的 Kokoro/HeyGen。
- edge-tts(預設):
1. 研究(有網路搜尋時)
- 搜尋主題的最新資料,至少兩個獨立來源。數字對不上的地方要寫下來,取來源一致的那個。
- 每個數字分成三類,之後畫面上都要標:官方宣稱/實測或報導/自己的估算。
- 自己做簡單物理或數學估算,讓觀眾「算得出來」,那是教學片最有價值的部分。估算一定要拿現實比對(例如:「一般車最多 1.2 g」被市售車 1.8 秒破百推翻,要改成 1.5 g)。
- 不用品牌照片和 logo;主角用自己畫的示意圖,標「示意圖」。
- 研究的同時就記下圖片線索:有沒有「先例」、「老前輩」、「實驗照片」可以當證據(例如 NASA 的歷史照片、已經存在的同類產品),這些就是第 7.5 節要找的真實照片。
2. 需求訪談(照 /hyperframes 的 intent layer,一次問完)
一定要確認:播放平台(決定比例:上課/YouTube → 16:9)、長度(建議 60–90 秒,旁白長度會決定實際片長)、要不要旁白(推薦要)、要不要先審分鏡、自動化還是一起邊做邊調。
再加問三個顏色(本技能新增),像簡報版型:
- 背景色、主色(文字與線稿)、強調色(只給答案、結論、關鍵數字、章節卡)。
- 沒有偏好就推薦:黑底
#121212、白字#F2F0EA、橘色強調#FF7A1A。 - 字型:全片統一用一種字型。預設是源石黑體 粗體(GenSeki Gothic Bold,OFL 授權,中文、英文、數字、字幕都用它)。使用者有指定字型就換,但要確認那個字型可以自由使用。
- 顏色和字型都寫進專案的
theme.json(格式見templates/theme.example.json的bg/fg/accent/font)。
彙整成需求摘要,分「使用者回答」和「我推斷的」兩區,使用者確認後才開工。
3. 建專案與分鏡
hyperframes init videos/<kebab-name> --non-interactive --example=blank --skill=faceless-explainer,接著寫BRIEF.md,然後照/faceless-explainer的 Step 0–2 做(capture/extracted/、選一個 frame preset 產生frame.md)。- 選 preset 時優先選線稿清楚的(例如
cobalt-grid)。它只是「來源配色」,最後會被theme.py換成使用者的三色。 - 在
frame.md加上 繁體中文覆寫(字型、字重、字距、行高、投影機最小字級),內容照motion-design第 5 節。 - 跑
bash scripts/fetch_fonts.sh <project>,把源石黑體粗體(從官方 GitHub release 下載)、frame worker 製作時用的 Latin 字型和 Noto TC,全部放進assets/fonts/,不要依賴 Google Fonts 線上載入。 - 寫
STORYBOARD.md和SCRIPT.md(格式照官方 storyboard-format / script-format)。旁白要照「子句」切,每個逗號就是一個畫面揭示的時間點;數字寫成國字(「零點八一秒」),TTS 才不會唸錯。
4. 旁白
- 產生
assets/voice/raw/NN.wav(每句一個檔,NN 是分鏡格號):- edge-tts:
python scripts/edge_tts_voice.py --project <p> --voice zh-TW-HsiaoChenNeural [--rate -5%]。全片用同一個 voice,聲音天然一致;--list zh-TW可以列出所有聲音。 - Breeze TTS 2:
python scripts/breeze_voice.py --project <p> --breeze-repo … --model … --voice "<聲音描述>" --only-ref,先設計一個參考聲音讓使用者聽,確認後再拿掉--only-ref產生全部句子(每一句都複製這個參考聲音)。如果有批次 runner,改用scripts/tts_jobs.py產生工作清單。 - 使用者還沒裝、或不確定要選哪一個:照
references/tts-setup.md給建議,一步一步確認,不要擅自安裝。
- edge-tts:
- 先讓使用者試聽前一兩句,口音與情緒由使用者用耳朵決定,不拿分數代替。不滿意就換一個 voice 或改語速,刪掉舊的 WAV 再重新產生。
- 整支片做完才發現某個字唸錯(例如英文品牌名、破音字):不要整句重錄,不然那一格的動畫時間會全部跑掉。改成:同一個聲音、同一句話產生 4–6 個候選,可以換 seed,也可以換拼法,例如
Road-ster或同音同調的字,字幕仍然用原文;放到assets/voice/fix/cand/NN_X.wav。然後跑python scripts/fix_voice.py --project . audition --line N --clauses <那個詞所在的子句>,把關鍵片段串成一個試聽檔給使用者用耳朵選。選好之後跑apply --line N --take NN_X,它會把新句子整句等比伸縮回原本的長度,音量對齊原本那一句,再重算那一句的字幕時間,每一格的長度不變。接著重建字幕 →patch_captions.py→ 刪掉.hyperframes/pre-theme/compositions/captions.html(不然theme.py會換回舊字幕)→theme.py→place_media.py→ 重新輸出。不要把重錄的句子照停頓切成子句再對時間:重錄的停頓位置不一樣,切點會落在字中間,結果漏字或重複(實測發生過)。ASR 只能用來篩掉明顯錯的;聲調對不對,ASR 聽不出來(實例:「輪胎」ASR 判對,使用者聽起來是錯的)。
- 整支片做完才發現某個字唸錯(例如英文品牌名、破音字):不要整句重錄,不然那一格的動畫時間會全部跑掉。改成:同一個聲音、同一句話產生 4–6 個候選,可以換 seed,也可以換拼法,例如
python scripts/voice_meta.py --project <p>:去頭尾靜音、量出每個子句的時間、寫audio_meta.json。node <faceless-explainer>/scripts/audio.mjs sync-durations --audio-meta ./audio_meta.json --storyboard ./STORYBOARD.md- 響度:最後成片要約 −14 LUFS、true peak ≤ −1 dBFS。旁白太小聲就統一加同樣的增益加 limiter,保留各句之間的相對音量。
5. 鏡頭設計(Step 4)
- 在
shots.json(見templates/shots.example.json)裡,每格用「第幾個子句 → 畫面上出現什麼」來寫,跑python scripts/apply_shots.py --project <p>換算成真實秒數,寫回STORYBOARD.md。 blueprint欄位只能是<id> (Adapt)、<id> (Reproduce)或compose,說明另外放在note。- 先用
hyperframes catalog --query找現成元件,找不到再自己畫。 - 會在多格重複出現的主角(車、人、儀器)先畫成一個共用 SVG,固定各部件的座標,所有 worker 都必須照抄。不這樣做,每格的主角都會長得不一樣。
6. 平行做每一格
node <faceless-explainer>/scripts/frame-packets.mjs --project <p> --storyboard <p>/STORYBOARD.md- 從
templates/dispatch_context.md複製一份到.hyperframes/frame-packets/_dispatch_context.md,把專案的值填進去:Video direction、共用素材、時間規則、字型。 - 每一格派一個 sub-agent,全部平行。prompt 依序讀:
_role.md→_dispatch_context.md→ 該格 packet →frame.md→ 共用素材。 - 相鄰格要接續同一個畫面時(例如同一條刻度尺),先做完的那一格回報的精確幾何,要立刻轉給還在做的那一格。
- 全部回來以後:
python scripts/unify_frames.py --project <p>,統一字型和髮絲線位置。
7. 組裝、字幕、配色
node <fe>/scripts/assemble-index.mjs --storyboard ./STORYBOARD.md --hyperframes .
node <fe>/scripts/captions.mjs build --storyboard ./STORYBOARD.md --audio-meta ./audio_meta.json --hyperframes . --out ./caption_groups.json
python scripts/patch_captions.py --project . # 中文字幕字型與粗細(預設粗體 700)
python scripts/theme.py --project . # 套用 theme.json 的三色與字型(index、每一格、字幕)
node <fe>/scripts/transitions.mjs inject --storyboard ./STORYBOARD.md --hyperframes .
node <fe>/scripts/transitions.mjs verify --storyboard ./STORYBOARD.md --index ./index.html
hyperframes lint && hyperframes check
(<fe> = 已安裝的 faceless-explainer skill 資料夾。)字幕每次重建後,都要重跑 patch_captions.py 再跑 theme.py。theme.json 的 accents 指定每一格裡哪些元素用強調色(block/fill/text);font 會把每一格和字幕的所有文字都換成同一個字型和字重,覆蓋 worker 原本寫的字型設定。換字型後字變寬了,要重跑 hyperframes check 看有沒有溢出或重疊。
最後一步才瘦身字型:python scripts/subset_fonts.py --project .。它會只留下片中用到的中文字(CJK 字型從 12–17 MB 降到幾百 KB),並把每一格的 @font-face 改指向瘦身後的檔案。任何改動文字、字幕或配色的動作之後都要重跑:theme.py 每次都從配色前的原始檔重新套色,原始檔指向的是完整字型,新加的字如果不在瘦身檔裡,就會退回系統字型。
7.5 圖片層(本技能新增)
完整規則見 references/images.md。重點:
- 規劃:每支片 3–5 張。真實照片當證據卡(「真的有人做過」),Codex 生成圖當開場、收尾的氣氛背景。動畫是主體,圖片不能搶走線稿講的原理。
- 找照片:
python scripts/find_images.py search "<關鍵字>"→get "File:…" --name <短名> --project .。只接受公有領域、CC0、CC BY、CC BY-SA,來源會自動寫進assets/images/web/CREDITS.md。下載後要親眼看一次,路人、其他品牌的 logo、浮水印要裁掉。 - 生成示意圖:把 prompt 寫進
gen_prompts.json(見templates/gen_prompts.example.json),跑python scripts/codex_images.py --project .。需要本機已登入的 Codex CLI,使用內建的 image_gen,不需要 API key。生成後要親眼檢查有沒有冒出文字或 logo。沒有 Codex 的話,告訴使用者可以改用其他生圖工具,把 PNG 放進assets/images/gen/。 - 套色:在
media.json寫好每張圖的裁切、尺寸和模式(照片用duotone,生成圖用keep),跑python scripts/treat_images.py --project .。 - 擺放:先看每一格落定後的 contact sheet,找真的空著的區域,在
media.json的placements寫好frame、mode(card/background)、box、at、label、credit。要把原本的線稿換成照片,就用hide。然後在theme.py之後跑python scripts/place_media.py --project .。 - 畫面標示:照片寫「Photo: 作者 · 授權 · 來源」,生成圖寫「AI 生成示意圖」。
- 跑
hyperframes check(照片上的文字對比度、重疊),最後才跑subset_fonts.py,因為圖說和來源也有字。
7.6 AI 影片層(本技能新增)
完整規則見 references/ai-video.md。重點:
- 規劃:每支片 2–4 段。用在開場的鉤子、一個拍不到但正好對上旁白的動作(例如「只能跳一下」→ 車子落地)、收尾的情緒。需要精確數字或受力方向的畫面仍然交給線稿。
- 第一格用 Codex 靜態圖:先照 7.5 節生成符合主題配色的圖,H3 再從這張圖開始動,影片和片子的風格才會一致。
- 寫 spec:
assets/videos/gen/specs/<name>.json(範例在templates/video-specs/)。每段 4–15 秒,主體寫「沒有品牌、沒有文字」,動作寫成一句清楚的事件,再加上相機運動和聲音描述。 - 生成:
python scripts/ai_video.py prompt --project .(官方六段格式)→run(需要video_config.json的 runner,見templates/video_config.example.json)。沒有 runner 的話,給使用者prompt.txt和第一格,請他用 ComfyUI 的官方 MiniMax H3 R2V 模板生成,存成assets/videos/gen/<name>/clip.mp4。 - 檢查:
python scripts/ai_video.py check --project .,每一張check-1.png都要親眼看:有沒有變形、多出零件、文字或 logo、動作時間點對不對得上旁白。不合格就換 seed 重跑。 - 擺放:在
media.json的placements用"video": "assets/videos/gen/<name>/clip.mp4",加上duration,必要時加out(影片結束前把卡片淡出)。在theme.py之後跑place_media.py,然後hyperframes lint(video 一定要有 id、不能放在有計時的元素裡)和hyperframes check。 - 畫面標示「AI 生成影片(H3)」;影片一律靜音,聲音只用旁白。
8. 審查(review-loop)
- 先
hyperframes check,再用 draft 品質輸出整片(hyperframes render --quality draft --workers <hw_check 建議值>;審查階段一律用 draft),在每個子句結束前 0.15 秒截一格(取落定的狀態),用review-loop/scripts/sheet.py --video … --at …拼成 contact sheet,每一張都要親眼看。 - 對照
references/lessons.md的檢查表逐項看,修完重新輸出、重新看,直到一輪都沒有問題。 - 看完才輸出最終版:
hyperframes render --skill=faceless-explainer --quality high --output renders/video.mp4,再量一次響度。
9. 交付
交出 MP4 路徑、片長、一張總覽 contact sheet,並列出:用了哪些來源、哪些數字是宣稱、哪些是估算、哪些地方和需求不一樣(例如片長超出)、哪些沒做(例如沒有配樂)。