video-talkcraft — 口播影片技能
三大來源合體:管線(配音→字級時間戳→Remotion)+ 詞彙(108 張動效配方卡,全配可播 demo + 自包含 tsx)+ 鏡頭(七層模型反 PPT 系統)+ 視覺語言(Apple 範式預設版)。
核心範式:解說詞驅動畫面,每句都要有活的畫面響應(相機極緩推拉/已有元素的變化), 但新元素只在語義拍邊界進場,禁止機械的「一句一個新元素」(一句一元素是堆積型凌亂的制度根源; 分鏡按語義段落切,排版預算見 cinematography.md §4.5); 一個節拍只有一個主角,說完就讓位;字幕句邊界 = 全片時間錨點。
流程
① 文案 → ② 配音輸入+時間戳(本機CPU) → ③ 素材 → ④ SHOTBOOK 層矩陣 → ⑤ 實現(全局系統 → 首鏡先做先確認 → 其餘鏡頭)
→ ⑥ 渲染 → ⑦ 三重驗收(機器閘全過 + 1 輪審片修 P0/P1)→ ⑧ 交付(可選續審 ≤3 輪)
⓪ 開工體檢:統一依賴 + 畫幅與視覺語言
依賴只有一份:所有口播工程的 remotion/node_modules 與 workbench/node_modules 都是指向 <skill根>/runtime/node_modules 的軟鏈,版本只在
runtime/package.json 裡釘(@remotion/* 全家同號)。新片開工第一件事(用戶 2026-09-15 定版:每次新做影片都要檢查更新):
bash <skill根>/runtime/check-runtime.sh --upgrade # 裝好共享依賴 + 共享無頭瀏覽器 + 鏈好 workbench;Remotion 有新版就全家升級並冒煙渲 1 幀,不過自動回滾
末行 [runtime] OK 才往下走;升了級要把 runtime/package.json / package-lock.json 的改動提交。製作中途不升級(母版段快取不認依賴版本,混版本渲出的段不一致)。
工程目錄裡永遠不跑 npm install(會寫進共享目錄);要加套件 → 加進 runtime/package.json,npm ci,再提交。
畫幅與視覺語言(開工先定,全流程引用)
- 畫幅預設橫屏 1920×1080(用戶偏好);明確要發抖音/豎屏渠道才用 1080×1920
- 視覺語言:用戶明確點了風格就按用戶的來(整套 token 替換);沒點時先從口播稿判定領域、派生本片風格檔
(
references/design-language.md§0:讀全稿答「講什麼 / 對誰講 / 什麼口吻」→ 領域 → 風格檔表給底色策略 / accent / 字體氣質 / 材質與卡造型 / 圖表語言 / 素材氣質 / 能量檔, 寫進 SHOTBOOK §0G0 風格檔),骨架仍是 Apple 範式(一個強調色/一個投影/底色交替分幕/兩檔字重/ 預設幕底:淺pastel-mesh-flow/ 深mesh-flow-dark——12 款幕底見 §1.1,程式碼template/motion-systems/backdrop.tsx), 派生本片 token 落成theme.ts。對任何風格都成立的只有一條:禁止逐場景隨手取色。 卡是中性 UI,進片必須蒙皮:動效卡的 demo / tsx 是無風格的中性呈現,複製進工程後按風格檔改皮(顏色 / 字體 / 圓角 / 材質 / 圖表座標軸與標記 / 佔位圖形)、 不改運動命門(時序 / 緩動 / 幾何比例 / 層級),契約與反例見 design-language §0.4;SHOTBOOK 每鏡寫蒙皮行
① 口播稿
- 每句一個資訊點,鉤子在第一句(數字/衝突);13 句 ≈ 95s
- 數字一律漢字(時間戳按文本逐字錨定,
197747無法與「十九萬七千」的讀音對位);英文品牌詞直接寫(中英混合對齊已驗證) - 先調研核實事實,列「事實紅線清單」(不可說錯的數字/未驗證數據不引用)
② 配音輸入 → 預剪 → 字級時間戳(預設本機 CPU;可選 Fish Audio)
預設使用成品配音:真人錄音或任何 TTS 皆可,輸入 = 一條完整配音(wav/mp3)+ 與之逐字一致的口播稿。 沒有錄音且用戶選擇合成時,可使用下面方案 B;它不會替換已有配音或預設的本機 CPU 流程。
②-0 配音預剪(真人錄音必做;TTS 只會壓氣口,可跳過)——剪掉口語詞(嗯 / 呃 / 那個…)、結巴重說、過長停頓, 在做時間戳之前跑(時間戳做完再動音訊 = timing / beats 全體錯位;預剪 → 時間戳 → 一切後續,順序不可換):
python3 scripts/voice_trim.py audio/raw.wav script.json --dry-run --words-out audio/asr_words.json # 先只出報告:逐條 [filler / repeat / pause] 起止 + 共剪多少;ASR 結果落盤
python3 scripts/voice_trim.py audio/raw.wav script.json --words audio/asr_words.json --out audio/full.wav \
[--video dh/host_raw.mp4 --video-out dh/host.mp4] # 用戶認可後落盤(吃回上一步的詞表,不再跑一次 ASR);同一條錄音的人物影片用同一 EDL 剪(音畫逐幀同長)
- 稿子是真值,寧漏勿錯:只剪 ASR 裡稿子沒有的插入段——全由口語詞表拼成的(filler)、等於緊鄰稿文的結巴 / 重說(repeat);
ASR 聽錯稿子裡的字永不剪(剪它就剪掉了那個字的真實發音);稿外改了措辭的重說只報告,
--cut-unmatched才剪。 詞表來源缺省跑 FireRed(與下面時間戳同一後端),也吃剪映等導出的逐字 SRT(--srt)或詞級 JSON(--words); 句級 SRT 定位不到口語詞,腳本會警告。無稿時只剪整 token 文字恰為保守詞表(嗯 / 呃 / 額 / um…)的口語詞——按規範化文字精確比對、不認同音(五≠唔、餓≠呃); 緊鄰重複的短詞無稿只報告不剪(逐字 token 下分不清疊詞與結巴)。剪同錄的透明 webm 時會解一幀核 alpha,幀數對但透明丟了也算 FAIL。 - 停頓:≥0.7s 的靜音壓到 0.35s(留段內最安靜的一窗真實房間音,不補數字零),首尾留白 0.25 / 0.5s;
切點先找能量谷、再吸附 30fps 幀網格;
cuts.json是 EDL(含源 → 新時間軸映射表,剪人物影片與後續任何對帳都吃它)。 - dry-run 報告必須給用戶過目再落盤:標了「切點未落在靜音裡,聽一下」的條目讓用戶聽那一處;腳本只刪不合成,不改語速不改音高。
剪完人物影片後跑 ③ 的
preflight.py --media-only核時長——同一 EDL 只對同一條錄音成立。
字級時間戳(對預剪後的 audio/full.wav):
# 方案 A(已有錄音,本機 CPU 對齊):
pip install zhconv pypinyin sherpa-onnx soundfile numpy # 預設後端 FireRedASR2-CTC int8 的全部依賴
# 首次:下載模型 767MB(model.int8.onnx + tokens.txt)放 ~/.cache/koubo/<模型名>/,位址見腳本頭註釋
python3 scripts/timestamps_cpu.py audio/full.wav script.json audio/timestamps.json
# 備選(免手動下模型):pip install faster-whisper 後加 --backend whisper(首跑自動下載 460MB)
python3 scripts/make_timing.py audio/timestamps.json remotion/src/timing.json
# 方案 B(可選生成配音 + 時間戳,預設請求 s2.1-pro-free;可用性以 Fish Audio 為準):
pip install requests python-dotenv # 還需 ffmpeg,生成前會檢查
# 在 .env 配置 FISH_AUDIO_API_KEY=xxx 及可選 FISH_AUDIO_REFERENCE_ID=xxx(見 .env.example)
python3 scripts/tts_fishaudio.py script.json audio/full.wav audio/timestamps.json --timing-out remotion/src/timing.json
- tts_fishaudio.py:預設
--mode sentence每句一次請求,插入--pause-sec指定的真實靜音(預設 0.25 秒);--mode stream整稿一次請求、保留自然停頓。兩者均接收 UTF-8 SSE,生成結束才寫檔案,不提供串流播放。先解碼 PCM 再拼接,偏移按採樣數計算。空音訊、缺失/無效對齊或文本不匹配時報錯;只忽略標點、大小寫與字元寬度,不自動轉換數字讀法。中文用介面字級錨點,英文詞內插值;match/ok僅確認文字映射,仍需試聽。合成後若再預剪,須重新執行 CPU 對齊。 - timestamps_cpu.py:ASR 詞級時間戳 → 與口播稿字元級對齊(CJK 是可靠錨點,
匹配鍵=繁簡歸一+無聲調拼音,同音字不算錯;拉丁詞各家 ASR 都常拼錯,在錨點間插值)→
每句 match 質檢,<0.90 標出人工聽核。預設後端 FireRedASR2-CTC(尾部最穩、零誤報;整段餵入 ~200s 崩、記憶體平方漲,腳本預設按靜音切 ≤75s 段再加回偏移,
--chunk-sec可調),備選 faster-whisper; 各後端橫評數據與模型下載位址見腳本頭註釋。 - timestamps.json schema:
{sr, total, sentences:[{i,text,start,end,match,ok,words:[{text,start,end}]}]}——words 為 CJK 逐字 + 拉丁整段 token(標點跳過);滿足此 schema 的任何對齊工具都可替換。 - make_timing.py:轉成 timing.json(chars 與文本逐字元 1:1,標點零時長),供
tSay/msSay錨點查詢 - 配音自查(耳聽):無爆音/截斷/誤讀;句間留 ~0.3s 氣口,時間錨點更穩
②-1 語義標註(2026-09-22 起必做,正主 references/semantic-annotation.md)
口播稿逐句標「這句在做什麼」,落成工程根 semantics.json——這是選卡的需求側產物,沒有它,選卡只剩輸入類型一道過濾、剩下幾十張卡靠印象挑(2026-09-21 那支片的「我是萬里」就這樣拿到了全庫能量最低的文字卡,庫裡 P0 的人名條沒人查到)。
python3 <skill根>/scripts/semantic_annotate.py --init # 從 timestamps.json 出骨架(帶詞法提示 hint)
# 逐句填 sem(26 詞封閉詞表,見 taxonomy.md「語義索引」)/ weight(main 主句 = 允許進新元素、sub 陪襯句)/ entities / need
python3 <skill根>/scripts/semantic_annotate.py --stats # 校驗:與時間戳逐字一致 · 詞表封閉 · 詞法硬規(我是X→自我介紹、點讚訂閱→號召、數量詞→數據)· 每鏡至少一個 main
標註是派生物:預剪 → 時間戳 → 標註 → 其後一切;改稿或重剪後 text 對不上就是標註失效,重新 --init。
②-1 早於分鏡,所以 shot 欄位此時是空的(SHOTBOOK 還沒寫):④ 寫完後必須回填一次,否則下游的鏡頭級覆蓋核不到任何東西——
python3 <skill根>/scripts/semantic_annotate.py --sync-shots # ④ 之後:按 SHOTBOOK 標題的起止秒(或 shots.json)回填 shot,只動 shot,標註不丟
③ 素材
- 素材清單從 ②-1 的語義標註生成,不靠拍腦袋:
need是證據的句去截真頁 / 找出處,身份要頭像與帳號資訊,量化要圖表或數據源,entities裡的人名 / 品牌 / 地點 / URL 就是檢索詞。 - 先給每個鏡頭標素材模式(多選,可組合):
B-roll(實拍影片)/圖片(照片 / 海報 / 插圖)/截圖(網頁 / 介面證據畫面)/純動效——如「B-roll 打底 + 截圖證據卡」。新聞/資訊類話題證據優先:Playwright 即時截圖比泛用 B-roll 更有資訊量。 四檔對應 taxonomy.md 輸入類型代號 V / 圖 / 截圖 / 文,SHOTBOOK 每鏡寫一行素材:V(路徑)· 圖(路徑)· 文(格式見 ④) - 實拍素材是必需項,不是可選項(2026-09-06 硬規):全片零 B-roll / 圖片 = 只有動效 + 口播人物 = 觀眾看到的是「講 PPT」。
preflight.py對帳 SHOTBOOK:零 V / 圖 鏡頭直接 FAIL,V / 圖 鏡頭佔比 < 1/3 WARN(要在 SHOTBOOK 給依據,如證據類題材以截圖為主)。 「本片不做 B-roll」不允許寫成設計決定;影片源搜不到就降級圖片(Pexels photos 原圖 → Pixabay),圖片也沒有才進「未完成 / 未採集清單」。 圖片與影片同源同 key,採集規格(解析度下限、落盤目錄、登記)見references/broll-sources.md「配圖採集」 - 真圖硬規:話題存在可截的真實頁面(產品官網/GitHub/文件/畫廊)時,
成片中的瀏覽器/頁面類鏡頭禁止用程式碼 mock 冒充截圖——卡片 demo 裡的灰條假 UI 是佔位物,
成片必須按卡片「復用指引」整塊換成
<img>真圖;mock 只允許表現無真實對應物的示意 UI, 且 SHOTBOOK 逐鏡標註「為何無真圖」。引申:口播講「這樣的成片/效果」時, 示例畫面必須是真成片片段(<OffthreadVideo>內嵌已有成片/真機內錄裁切,muted); 講「長頁面/看板/參數頁」時用 Playwright 全頁長截圖(放大鏡/巡航類動效直接吃真圖座標)。 真圖上的標註座標一律機器實測,禁目測:頁面元素用 DOMgetBoundingClientRect、成圖用逐像素量測 (目測偏 ±30px 就會把環框到別的元素上);會滾動/移動的真圖,標註(環/框/pill)必須釘在內容座標繫上隨內容動, 釘畫面固定位就是錯位根源 - 單影片鏡頭要有主題邊框(2026-09-07 用戶定版):鏡頭裡唯一主體是一段影片(錄屏 / 單條 B-roll / 引用別人的成片或採訪)時,
禁止裸貼滿幅、禁止裸放白卡、也不裝假播放器(進度條 / 播放鍵 / 時間碼一律不要——不是真播放器就是在說謊),影片區必須包一層
template/components/theme-frame.tsx的<ThemeFrame kind>:八式(復古瀏覽器視窗 / 雜誌相框 / 35mm 膠片 / 拍立得 / 工程圖紙 / 筆記本 / 郵票齒邊 / 雙髮絲線), 按片子調性選一式、一片只用一式,寫進 SHOTBOOK 蒙皮行;多影片的卡(bed-echo-blur 前景 / split-60-40-story 左格 / gallery-wall-dolly)的影片區也包同一式。 框只管造型與自己的裝飾接力,整體入場 / 退場 / 極緩推歸鏡頭層;框裡的畫面零處理(不濾鏡 / 不縮放 / 不淡入淡出)。 例外只有兩種:影片當底床不當主體(bed-echo-blur / §1.2 實拍底床),以及產品介面卡(chat-gpt / claude-code 類,皮即內容)。 靜圖不進框(框說「這是錄像」,畫面不動一眼假;圖用 media-pop-in / slow-push-in)。規則與八式表:design-language §1.3 - 網頁拍攝不貼圖:找資料/找素材時判定可用的網頁,成片裡禁止以靜態截圖貼屏,
必須像手持鏡頭一樣「拍」它——滾(
evidence-scroll-tour◆:勻速上滾 ≈10% 頁高/s,講到關鍵條提前減速停 1~2s)/ 巡(stage-keyframe-tour◇:長頁躺臺上不動,相機挨個停靠興趣點)/ 放大(magnifier-detail圓形放大鏡 看一眼就撤,pip-zoom-box◈拎出來長期掛著)/ 劃(highlighter-sweep掃整句、ink-underline◇劃一個詞、scribble-annotation圈注箭頭、corner-bracket-frame◈框區域);一屏裝完的頁面至少走slow-push-in底噪。 一鏡一主式:滾動/巡遊段內不彈放大鏡、不現場劃線,順序是「滾到 → 停 → 劃/放大 → 再滾」; 拍法選型表見 shot-design.md §2④「網頁拍攝」。素材按 broll-sources.md「網頁拍攝素材採集」規格落盤: Playwright 全頁 2× 長截圖 + 同一會話 DOM 實測的目標座標 JSON(放大鏡/劃線/停點全吃這份座標,接上一條「禁目測」)。 拍攝一律由 Remotion 在長截圖上完成(seek-safe、可對詞錨),不用瀏覽器錄屏(幀率不穩、懶載入與粘性頭穿幫、 對不上字級時間戳)。唯一放行:一屏裝得下且只當配角(media-pop-in 多張堆疊裡的一張)的小截圖可靜態入卡, 但仍帶 Ken Burns,不得是該拍主體 - 標了 B-roll 的鏡頭列 2–3 個英文視覺概念詞跑 Pexels + Pixabay API 雙源並行,候選落
assets/broll/; 源分層與授權紅線(只用免署名源)見references/broll-sources.md - 調研記帳:承載關鍵事實的來源頁逐一截圖存檔,
sources.md裡連結與本地截圖一一對應 (禁止只存連結不留證據);成片引用時優先使用存檔截圖當畫面證據 + micro 階來源行 - 有 B-roll/截圖 + 對應口播的人物素材(錄播/數位人成品)時,人物一律降級成角標常駐——
圓形頭像章(
host-shrink-to-chip◆)或摳人貼角,落左下 / 右下角;不許切走人、不許人物佔滿畫幅。 兩路選型與全部硬約束以references/host-footage.md§5 為準,鏡頭預設見 shot-design.md §2⑦ - Manim 圖表:
--transparent --format=mov後必轉 VP9 webm(-c:v libvpx-vp9 -pix_fmt yuva420p) - 全部落盤 public/,禁止渲染時拉遠端
- ③ 收尾必跑素材體檢(把 host-footage / broll-sources 裡的入場硬規變成斷言;答案早就寫在 reference 裡、但沒人在正確時刻去查, 是 2026-09-06 覆盤裡兩個最大的坑的共同失效模式——所以不再補文件,改成開工前必跑):
python3 scripts/preflight.py --media-only --host remotion/public/dh/host.webm --fps 30 --voice audio/full.wav
# 查:人物素材 r/avg 幀率一致(VFR)· 源片無重複幀簽名 · 素材 fps = 成片 fps(不等→成片改成素材 fps,禁 -r 直轉)·
# 時長與配音逐幀對齊 · 真實寬高比 · 素材盤點(實拍/圖片/網頁長圖數)· sources.md 在冊。任一 FAIL 不進 ④
④ SHOTBOOK(必產出,實現前評審)
先用 references/shot-design.md 給每個鏡頭填三面分層工作單(背景面/主體面/文字面 + 各面動效
- 七種鏡頭類型預設),再按
references/cinematography.md§4 展開成層矩陣,範例references/shotbook-example.md。 每場景:一句意圖 + 主體接力線 + 逐節拍層矩陣(節拍錨定字級時間戳;每行動作必須答得出「配合誰」)。 每鏡必寫「素材:」行(機器可讀,preflight 逐個 stat 檔案):- 素材:V(public/broll/gpu.mp4)· 圖(public/stills/a.jpg, public/stills/b.jpg)· 截圖(public/pages/gh/page.png)· 文—— V / 圖 / 截圖 必須括號給路徑,寫「待採」= FAIL;純動效鏡也要寫素材:文。 必填「## 未完成 / 未採集清單」節:任何「本片不做 X」二選一——歸入 §0 的設計決定(+依據),或歸入本節(+阻塞原因 + 兜底源是否試過); 允許寫「無」,不允許缺節。這一節專門攔「未完成被包裝成設計原則、進而變成不再被質疑的前提」(2026-09-06 覆盤的真正失效模式)。 G0 寫一行「樣板鏡:sNN」(⑤-1 首鏡先做先確認用):預設 s01;s01 是章節卡 / 空鏡等不帶主體動效的鏡頭時,選第一個有卡、有字幕、有人物或素材的鏡頭。 節拍必須機器可驗:每條畫面重音落成remotion/beats.json({t, anchor, sentence, what},t 一律由 timing.json/atChar()查得,禁止手敲近似秒數—— 手敲的誤差靜幀 QA 看不出來),SHOTBOOK 節拍表與 beats.json 一致, 機器閘用scripts/beat_lint.py對 timestamps.json 校驗 |Δ|≤0.1s。 未到拍不顯形:詞錨未到的數字/圖形必須完全不可見(opacity 0), 禁止壓暗/灰顯「預告」;行內數字要連同其後繼字元一起 gate(「就 __ 類」的空洞掛著同樣是缺陷)。 開鏡不空台:鏡頭開場到第一個動效錨點 >1.5s 的空窗必須有承載畫面 (真實 b-roll / 上一鏡元素延續 / 真素材牆),不許空畫布乾等詞錨。 鏡尾保護帶:詞錨動效落點距鏡頭出點 <0.7s 的,要麼提前、要麼挪進下一鏡——落點會被轉場吞掉;beat_lint.py --shots shots.json機器查 ≥0.5s 硬底線。 幕級轉場事件同樣入 beats.json:shape wipe/換幕的遮擋峰值時刻也由詞錨生成入表—— 手敲絕對秒的轉場事件表游離在機器可驗體系外,靜幀 QA 與 beat_lint 都看不見。 排版預算(全表 cinematography.md §4.5):分鏡按語義段落切、每鏡一個 primary visual job; 純文鏡必配陪襯圖形(2026-09-07 用戶回饋「只有文字動效往上堆太單一」):素材行只有「文」的鏡頭(章節卡除外),層矩陣必須多一行 「G5 線稿示意圖 ← 講 X 所以畫 Y」(references/schematic.md,程式碼template/motion-systems/schematic.tsx),preflight 對缺行的純文鏡 WARN; 樞軸句(「但這次不是X」式轉折/設問)的動效歸它開啟的下一鏡;任一時刻同屏主體組 ≤3(降權留守計入)、 每鏡至少留一個空象限;hero 造型一屏一個。 排版規範(全表references/layout.md):預算管「放多少」,規範管「放哪、多大、怎麼對齊」—— SHOTBOOK 每鏡寫版式行(欄跨度 + 組包圍盒 + 對齊基準 + 字階),定妝幀開debugOverlay核九項,任一失敗 = P1; 獨句 hero 居中但不得覆蓋人臉(含 B-roll 裡的人臉,縱向改取人臉之外的三分線)。 版式輪換(2026-09-21 用戶:成片「人物在左下角、素材在中間方塊、右邊放文字,過於固定」;全表 cinematography.md §4.5 第 9 條):寫逐鏡矩陣之前先在 G0 寫「版式節奏表」 (| 鏡 | 人物形態·方位 | 素材容器 | 主卡 |,格式 cinematography.md §4)——同一張呈現卡(素材呈現 / 數據 / 運鏡類)不連用 3 鏡、全片 ≤1/3(≥6 鏡的片);人物形態(半身 / 角標左下 / 角標右下 / 分屏格內 / 摳人貼角 / 短暫離場) 與素材容器(出血全屏 / 裝框 / 分屏格 / 底床 / 多圖編排 / 3D 牆 / 長頁)連續 3 鏡至少換其一;同一條 B-roll 不進相鄰兩鏡。單條 B-roll 按 shot-design.md §2⑦ 七式選、相鄰鏡不同式, 多素材按 §2④′ 關係表;preflight 按節奏表 + 蒙皮行核(連用 / 佔比 FAIL)。輪換是換構圖不是加運動——每式內部仍只有相機極緩推拉。 每鏡必寫「選卡行」(②-1 的語義 → 卡;候選由機器給):
python3 <skill根>/scripts/card_match.py --out qa/card-candidates.md # 語義 × 素材行 × 卡索引 → 每鏡每個主句語義的可行候選 + 排序理由 + 落選理由
跑之前先 semantic_annotate.py --sync-shots 回填 shot(②-1 時還沒有分鏡)。候選表除按語義列候選,還會給宣告了素材的鏡單獨列一行
素材承接候選——宣告了 V / 圖 / 截圖 卻沒有呈現 / 運鏡類卡承接 = 素材裸貼,preflight 判 FAIL。
SHOTBOOK 每鏡寫 - 選卡行:<語義> → <卡>、<語義> → <卡>(選卡行裡的卡要真的落進蒙皮行,preflight 對帳);
選候選之外的卡要在該鏡寫一行 - 語義偏離:自我介紹 ← 開場已報身份,s11 不再重複(理由 ≥4 字,preflight 認這行放行)。
層矩陣的節拍行加一列語義(值取自 semantics.json,不另造詞),這樣「這一拍在做什麼」在分鏡裡就是機器可讀的。
選卡必讀卡經驗:每張選中的卡,把 references/cards/<slug>.md 的「已知坑」與「落位自檢」逐條抄進該鏡層矩陣的自檢列,
實現後按條核(例:取景框 / 圈注 / 底線類卡必核標註是否套住目標;gooey-morph 只用於圖不用於字且無人物時居中;chapter-title-card 每章一套主題色 + 一個與本章內容相關的線稿 motif,SHOTBOOK 寫章節主題行——四張同色同紋樣的章節卡是「又來了」不是「翻頁」)——
卡經驗不進 SHOTBOOK 就等於沒讀。
動效詞彙從 108 張配方卡 裡選,兩道過濾都查 references/taxonomy.md 的機器生成索引(源頭是各卡 frontmatter 的「輸入 / 語義 / 素材形態 / 位置 / props」五個欄位,scripts/cards_index.py --write 生成、--check 校驗,手改索引無效):先按這一鏡的輸入過濾(人 / V / 圖 / 截圖 / 文 / 界 / 場——「輸入類型索引」),再按這句口播的語義過濾(自我介紹 / 數據 / 對比 / 列舉 / 引用 / 號召……26 詞封閉詞表——「語義索引」,一張卡只列在它專為之而設的語義下);索引裡帶 ◦ 的卡沒有可換內容的 prop(只暴露資源 / 皮膚類,或什麼都不暴露),改文案 / 數據要動 tsx(各卡復用指引的 props 行寫了改哪裡)。◉◎ 兩批新卡(29 張)md 開頭另有「輸入類型」表 +「常用場景」四條。然後 references/taxonomy.md 分類索引 → references/cards/<slug>.md 參數與坑 → template/cards/<slug>.tsx 自包含 Remotion 源碼(實現以它為準,複製進工程改 CONFIG 即用);demos/<slug>/index.html 是同畫面的 HTML 預覽(open gallery/index.html 一屏瀏覽、demo 滾入即自動播放;帶★實戰卡的生產母本另在 template/motion-systems|components)。
保真鐵律:每張用到的卡在工程裡必須真實存在 src/cards/<slug>.tsx
(自 template 複製改 CONFIG)——只讀 md 就憑卡名手寫「神似」簡化版是最大翻車源
(回彈/拍擊/密度全丟、取景框括號方向畫反、名片變色塊),機器閘用 scripts/card_lint.py
逐 slug 校驗存在性與相似度(≥0.55,改 CONFIG/文案在容忍內)。
蒙皮不是重寫:複製來的卡是中性 UI,必須按 SHOTBOOK §0 風格檔改皮——顏色全換 theme token、字體棧與字重、圓角 / 描邊 / 投影 / 材質、
圖表卡的座標軸 / 網格 / 標記 / 數字字體、卡片類的佔位圖形換真素材或風格化圖形——只改皮層,不改時序 / 緩動 / 幾何比例 / 層級;
每鏡層矩陣旁寫蒙皮行(卡名 → 改了什麼皮),同一片內同類卡共用一套皮;契約、例外(產品介面卡不蒙皮、語義色不換色相)與反例見 design-language §0.4。
card_lint 的 0.55 就是給蒙皮留的餘量:改皮過得了,重寫運動才掉下去。
三段式鐵律:入場 0.20.8s → hold(靜置即可——畫面的活由場景相機極緩推拉負責)→ 出場 0.150.5s;入場永遠比出場用力;同屏重音同一時刻只能有一個。
選了動效就要帶上它的音效:每張卡在 demos/_lib/sfx-map.js 有 cue 表({t, name, vol, rate?, clip?},t 為卡內相對秒)——
SHOTBOOK 選卡時把 cue 抄進該鏡頭的層矩陣(換算成絕對秒;vol 按成片口徑重標 ≤0.35,
demo 庫的 0.65 上限是試聽口徑不是成片口徑)。實現時按 ⑤ 的 sfx 步驟落地。
覆蓋口徑:主要動效入場全覆蓋,對齊 demo 庫密度
(每卡 26 記 ≈ 0.4 記/s,100s 的片約 4050 記)——「少而準」管的是單點不疊雙記、
音量克制(≤0.35)、連續揭示類(緩拉/對焦/逐字升起)與金句純文字卡、logo 落幕留白、
轉場只配蓄勢不配落點、不要收尾叮噹與重砸;不是砍覆蓋面。真採樣(pk-)
④-1 SHOTBOOK 模板與範例
G0 風格檔(產品/品牌/色卡/字體/幕底策略/能量檔) 版式節奏表(鏡號 / 人物形態·方位 / 素材容器 / 主卡)
鏡頭逐層矩陣(格式範例):
| 面層 | 內容 | 動效 | 備註 |
|---|---|---|---|
| G1 背景 | backdrop.tsx | 極緩推 | |
| G2 遠層 | 截圖 evidence.png | scroll-tour 巡,停 @3.2s | |
| G3 主體 | host chip | 已靜置 | |
| G4 文字 | 標題 |