程式化影片生成技能
一個確定性、零模板的工作流程,適用於 AI 編碼代理,可直接從單一 HTML5 Canvas/SVG 檔案、Python 程序化音頻腳本以及無頭 Playwright → FFmpeg 管道,設計、視覺 QA、評分和渲染 60fps 1080p MP4 動畫影片。
路徑。 ${CLAUDE_SKILL_DIR} 是包含此 SKILL.md 的目錄。在 Claude Code 中它會自動展開;在 Cursor、Codex、OpenCode 或其他代理中,請將 ${CLAUDE_SKILL_DIR} 替換為 skills/programmatic-video/ 的解析路徑。
為什麼需要確定性逐幀渲染?
永遠不要使用即時瀏覽器螢幕錄製(MediaRecorder、requestAnimationFrame 掛鐘時間捕獲,或 CSS 轉場以即時時間運行)來製作影片:
- 掛鐘時間捕獲會丟幀,只要 CPU 負載飆升,就會導致音視頻不同步和卡頓。
- CSS 動畫以掛鐘時間運行,使得無法直接跳轉到
t = 14.20s進行即時視覺 QA。 - 盲目渲染浪費時間:在檢查標題是否超出卡片邊界之前就渲染 5,000 幀,保證浪費工作。
相反,使用此技能構建的每個影片都遵守三個規則:
- 規則 1 — 幀索引的純函數: 整個場景由
window.__setFrame(frameIndex, timeSeconds, fps)驅動,其中t = frameIndex / fps。每個位置、透明度、計數器和粒子都是t的確定性數學函數(使用種子 PRNG,如mulberry32,絕不使用Math.random())。 - 規則 2 — 完整渲染前的多模態聯繫表 QA: 在對完整的 60fps MP4 進行編碼之前,捕獲 8–12 個關鍵時間戳(
render.mjs --timestamps ...),將它們拼接成一個contact-sheet.png(contact-sheet.py),然後使用你的多模態閱讀/查看工具檢查該圖像,以修復文字裁剪、重疊或對比度低的問題。 - 規則 3 — 樣本精確音頻 + 零磁碟膨脹 FFmpeg 管道: 生成多段立體聲 WAV 音軌 + 時間戳音效提示(
synth-audio.py),然後將 Playwright 的 PNG 緩衝區直接透過管道輸入ffmpeg -f image2pipe(render.mjs)。
端到端代理工作流程(6 個步驟)
步驟 1:故事板與場景預算
在編寫程式碼之前設計一個具體的時間線表。將影片分組為 4–8 秒的場景,並帶有 scene.html 和 synth-audio.py 共享的明確轉換時間戳 (T_cut):
| 場景 | 時間 (t) | 幀數 (60fps) | 視覺重點 | 音頻 / 音效提示 |
|---|---|---|---|---|
| 01 — 鉤子/警報 | 0.0s – 7.0s | 0 – 420 | CRT 終端啟動、打字機日誌、2.7s 處的 CTA 按鈕點擊 | 子音脈衝 + UI 點擊/解鎖提示在 2.7s,漸強音進入 3.4s |
| 02 — 英雄指標 | 7.0s – 15.0s | 420 – 900 | 3D 透視合成波網格 + 3 個彈簧物理計數器卡片 | 在 7.0s 處完整的 124 BPM 合成波貝斯 + 立體聲琶音器落點 |
| 03 — 深度遙測 | 15.0s – 23.0s | 900 – 1380 | 分割畫面進度條 + 動畫半圓形儀表 | 濾波器掃掠 + 高帽子鼓,在 15.0s 處的子音衝擊 |
| 04 — 點名與結局 | 23.0s – 30.0s | 1380 – 1800 | 貢獻者卡片的 Bento 網格 + "JOB'S DONE!" 橫幅與五彩紙屑 | 在 25.2s 處的最後和弦 + 語音/音效提示,主輸出淡出 28.5–30.0s |
步驟 2:使用 window.__setFrame(f, t, fps) 編寫 scene.html
編寫一個自包含的 1920x1080 HTML 檔案,使用 HTML5 <canvas>(和/或內聯 <svg> + DOM 覆蓋層),並公開:
window.__setFrame = function(frameIndex, timeSeconds, fps = 60) {
if (window.__rafId) {
cancelAnimationFrame(window.__rafId);
window.__rafId = null;
}
const t = typeof timeSeconds === 'number' ? timeSeconds : frameIndex / fps;
renderSceneAtTime(frameIndex, t);
};
- 始終包含一個種子 PRNG(
mulberry32(seed))用於星星、粒子、五彩紙屑或雜訊,以便幀f在多次運行中完全相同。 - 等待
document.fonts.ready(由render.mjs自動處理)。 - 請參閱 references/visual-patterns.md 以獲取可複製的配方(3D 透視網格、彈簧計數器、CRT 終端、儀表、Bento 卡片、五彩紙屑物理)。
步驟 3:執行快速時間戳快照並構建 contact-sheet.png
永遠不要先執行完整的 60fps 渲染。每個場景採樣 1–2 個時間戳(加上轉換中點)並構建一個聯繫表:
# 1. 在約 3 秒內捕獲 9 個關鍵幀 PNG
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
--html ./scene.html \
--timestamps 1.8,3.0,5.2,8.5,12.5,16.5,20.5,24.5,28.0 \
--out-dir ./qa-frames
# 2. 將它們拼接成一個帶標籤的網格圖像
python3 "${CLAUDE_SKILL_DIR}/scripts/contact-sheet.py" \
--dir ./qa-frames \
--cols 3 \
--thumb-width 560 \
--title "VISUAL QA CONTACT SHEET" \
--out ./contact-sheet.png
步驟 4:多模態自我審查循環(必做!)
在你的 ./contact-sheet.png(以及任何看起來密集的 ./qa-frames/t-*.png)上調用你的圖像「閱讀」/「查看」工具。根據 references/visual-qa-loop.md 中的清單檢查每個圖塊:
- 是否有任何文字溢出或與卡片邊框、徽章或進度條碰撞?
- 所有數字、標籤和 HUD 標題在 1080p 解析度下是否高對比度且清晰可讀?
- 每個場景轉換是否乾淨落地,沒有出現意外的空白/黑色幀?
如果你在 contact-sheet.png 中發現任何問題,請修正 scene.html 並在繼續之前重新執行步驟 3。
步驟 5:合成程序化音軌並混合 WAV 音效提示
生成一個立體聲 44.1 kHz WAV 音軌,其轉換漸強音和音效提示與 scene.html 中的確切時間戳匹配:
python3 "${CLAUDE_SKILL_DIR}/scripts/synth-audio.py" \
--duration 30.0 \
--bpm 124 \
--style synthwave \
--transitions 3.4,7.0,15.0,23.0,25.2 \
--cue "25.2:./sfx/jobs-done.wav:+1.5" \
--out ./soundtrack.wav
對於自定義多段合成或整合主題音樂包(例如 jblxo/claude-code-sound-packs),請閱讀 references/audio-synthesis.md。
步驟 6:通過 FFmpeg 管道渲染最終 60fps H.264 MP4
一旦視覺 QA 和音頻合成通過,以完整管道模式執行 render.mjs:
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
--html ./scene.html \
--duration 30 \
--fps 60 \
--audio ./soundtrack.wav \
--crf 18 \
--out ./final-video.mp4
使用 ffprobe 驗證輸出容器:
ffprobe -v error -show_entries format=duration,size:stream=codec_name,width,height,r_frame_rate -of default=noprint_wrappers=1 ./final-video.mp4
參考手冊(按需載入)
| 主題 | 參考文件 |
|---|---|
| Canvas/SVG 視覺基本元素、緩動函數、種子 PRNG、3D 合成波網格、儀表、Bento 卡片 | references/visual-patterns.md |
| 多模態聯繫表 QA 循環、常見佈局缺陷、時間戳選擇策略 | references/visual-qa-loop.md |
| 程序化 Python/NumPy 音頻合成、和弦進行、漸強音、閃避、WAV 音效提示混合 | references/audio-synthesis.md |