動畫配音廣告
核心原理
聽到什麼 = 看到什麼。 配音決定時間點。先錄音,Whisper 給出每個字的時間戳記,然後所有文字、場景、通知和效果都精準落在對應的字詞上。程式碼中沒有影格編號:使用 at: '客戶',時間會從 public/words.json 自動抓取。新的錄音 = 執行 npm run vo,影片會自動重新對齊。
螢幕上沒有任何一秒是靜止的。一秒沒有動態 = 觀眾會滑走。
鐵則
- 你聽不到。 業主是唯一的聽眾。你所有對音訊的檢查都必須是數值化的(
silencedetect、ffprobe、重新轉錄)。嚴禁未引用輸出就寫「音訊正常」。 - 先清除靜音,再進行轉錄。 Whisper 在靜音附近容易搞錯時間。
prep-vo.sh會以正確順序完成這兩項工作。 - 音訊變更後必須重新執行
npm run vo。 否則所有同步都會偏移。 - 影片在配音結束時結束 + 8 個影格(
time.ts中的DURATION)。render-all.sh會列印每個檔案的長度與配音長度進行比對。如果不同,代表有東西被裁切了。 - 文字僅限於 y=260 到 y=1570 之間。 上下區域會被 Instagram 覆蓋。
validate()會在文字超出此區域或寬度超過 1000px 時停止渲染並附上說明。 - 效果音量低於人聲。 在
Ad.tsx中設定為常數:配音 1.15,音樂 0.22,每個效果乘以SFX = 0.38。「效果太大聲」= 調整這個數字。 - 先檢查 stills 再輸出 mp4。
npm run check會渲染 10 個影格到out/stills。在完整渲染之前,必須查看所有 PNG 檔案。 - 只使用真實內容。 數字、付款和客戶訊息:必須是真實發生的。可以隱藏姓名,但禁止虛構結果。這既是為了遵守 Meta 政策,也因為觀眾能識破虛假內容。
- 希伯來文: 字型(Rubik、Heebo,可變字型,OFL)已包含在範本中,並透過
delayRender載入。根目錄設定為direction: rtl。標籤內的數字會設定為direction: ltr。
專案初始設定
cp -R ~/.claude/skills/animated-voiceover-ad/template ~/ads/<廣告名稱>
cd ~/ads/<廣告名稱>
npm install
npm run setup # 從 Mixkit 下載效果和音樂
需要:Node 18+、ffmpeg、whisper-cli(brew install ffmpeg whisper-cpp)以及位於 ~/.whisper/models/ggml-large-v3-turbo.bin 的 Whisper 模型(如果缺少,words.mjs 會輸出下載指令)。
工作流程
| 步驟 | 說明 |
|---|---|
| 1. 腳本 | 根據 references/script-formula.md。每個句子預先對應到一個場景。在業主錄音前先讓他過目。 |
| 2. 錄音 | 使用手機或 QuickTime,單一檔案。說錯話?暫停一秒,然後從該句子開頭重新開始。之後刪除錯誤的片段(請參閱 references/audio.md)。 |
| 3. 清理與轉錄 | npm run vo -- recording.m4a。列出所有單字及其時間戳記。將轉錄結果展示給業主,並直接在 public/words.json 中修正 Whisper 聽錯的單字(僅修正 w 欄位)。 |
| 4. 導演 | 僅編輯 src/Ad.tsx:KTS(動態文字)、通知、SCENES。所有時間點都指向單字,例如 ['更多', 2] 表示該單字第二次出現。元件詳細說明請參閱 references/scenes.md。 |
| 5. 檢查 | npm run check(TypeScript 檢查 + stills 渲染)。檢查所有 still 檔案。 |
| 6. 渲染 | npm run render。MUSICS(Root.tsx)中的每首音樂 = out/ 目錄下的一個單獨檔案,便於 A/B 測試。 |
| 7. 修改 | 業主的每個意見 = 一個固定的修改:在 at 中改用其他單字、調整音量、修改 until。不要重寫整個場景。 |
廣告變體
- 音樂: 內建,3 個合成。
- 不同開頭: 前 3 秒決定成敗。錄製 2-3 個不同的鉤子作為獨立檔案,使用
ffmpeg concat將每個鉤子與主體連接,對每個連接檔案執行npm run vo,並渲染到單獨的目錄。只要主體部分的單字相同,Ad.tsx就保持不變。 - 完整字幕: 在
Ad.tsx中設定CAPTIONS = true。單行顯示,根據標點符號斷行。這很有用,因為大多數贊助廣告是在沒有聲音的情況下被觀看的。
常見問題
| 問題 | 解決方案 |
|---|---|
在配音中找不到單字 "X" | 錯誤訊息會建議相近的單字。Whisper 處理希伯來文時,可能會合併或拆分前綴(和/介系詞/所有格/介係詞)。請使用 words.json 中實際存在的單字。 |
| 渲染顯示舊程式碼 | $TMPDIR/remotion-webpack-bundle-* 中存在舊的 bundle。render-all.sh 會刪除它。 |
| 安裝了 TypeScript 7 | Remotion 需要 [email protected]。 |
delayRender 卡住 | 加上 --timeout=180000(render-all.sh 中已包含)。 |
| 印章在落地前縮小 | 其 spring 動畫設定 overshootClamping: true(已內建)。 |
| 清除靜音後單字黏在一起 | 將 prep-vo.sh 中的 stop_duration 提高到 0.35。 |
| 「無聊」的某秒 | 在該秒的單字上增加一行動態文字、通知或效果。確保每秒都有事件發生。 |
範本中的示範
範本附帶一個示範配音(TTS 語音,public/vo.wav + public/words.json)以及與之同步的 Ad.tsx,以便在錄音前可以測試所有功能是否正常:npm install && npm run setup && npm run check。對於真實廣告:執行 npm run vo -- recording.m4a 會覆蓋這兩個檔案,然後根據腳本重新編寫 Ad.tsx。