video-flow:程式碼渲染的通用講解影片工作流程
一句話:先想清楚「教會什麼」,再把這件事變成一條可計算的時間軸,最後讓瀏覽器逐幀畫出來。 成片 = Canvas/HTML 的
render(t)+ headless Chrome 逐幀截圖 + FFmpeg + 可選 TTS/配樂/字幕。
本 Skill 把「一條影片」拆成 8 個可檢查的階段。每個階段都有產物和驗收點;任何一步不合格,不要進入下一步。
0. 什麼時候用 / 不用
用:
- 把一份 PDF / PPT / DOCX / 文章 / 網頁 / 影片 / 一個主題,做成 1–5 分鐘講解影片;
- 需要「文字清晰、數據準確、可改一幀、可重現」的影片(程式碼渲染相對於影片生成模型的結構性優勢);
- 要直式/方形/橫式多版本,或多語言版本;
- 需要旁白、字幕、配樂,且希望整套流程可重複。
不用:
- 需要真人/實拍/寫實鏡頭 → 用影片生成模型或實拍,本 Skill 只負責「程式碼這一層」;
- 只是剪已有素材 → 用剪輯工具/Agent;
- 只想生成一段 MP4 卻不願意定分鏡和文案 → 成片會像模板,建議先做第 1–2 步。
1. 硬規則(違反任何一條,返工)
- 畫面是時間的純函數:頁面暴露
window.render(t);給定t,畫面唯一確定。- 禁止
Date.now()、無種子隨機、requestAnimationFrame驅動的狀態、CSStransition/animation、跨幀快取。 - 累積型動畫(粒子/水面)用固定步長從 0 推到
t,或改解析公式。
- 禁止
- 時間軸是唯一事實來源:分鏡、旁白、配樂、音效、字幕都從同一張
timeline.json派生。 - 先分鏡後程式碼:沒有
storyboard.md和script.json,不要寫場景程式碼。 - 原文事實不編造:數字、年份、人名、公式必須來自源材料;不確定的標
[待核實]並在交付時單列。 - 預設不帶任何品牌/浮水印:除非用戶提供 logo/品牌名;預設頁腳只寫課程/主題資訊。
- 一次編碼:音訊在 WAV 階段完成混音與響度,最終只做一次 AAC 編碼;不要反覆轉碼。
- 交付前必須過 QA:抽幀、黑幀、響度、時長、字幕、音畫同步,見第 8 步。
2. 輸入與產物
輸入(任選,可混合)
| 類型 | 處理方式 |
|---|---|
scripts/ingest.py 抽文字;掃描件/亂碼時自動柵格化為 PNG,讓模型「看頁」 | |
| PPTX | 逐頁抽標題、正文、備註;可選把關鍵頁匯出為圖片 |
| DOCX / Markdown / TXT | 直接抽取為 source/source.md |
| 網頁 URL | 抓正文;保留來源連結 |
| 影片 | ffprobe 元資料 + 定點抽幀;無 ASR 時由人補充內容 |
| 純主題 | 使用者給的一句話/大綱;先讓使用者確認「必須出現的事實」 |
每個專案的目錄契約
<project>/
project.json # 元資訊:標題/受眾/目標/畫幅/風格/聲音/音樂/品牌
source/ # 源材料(source.md、pages/*.png、meta.json)
storyboard.md # 分鏡表:每鏡講什麼、畫面、時長、旁白、考點
script.json # 機器可讀:scenes[](type/文案/視覺/vo/時長)
build/ # index.html + lib.js + theme.js + scenes.js + timeline.js
audio/ # vo/*.wav、bgm、mix.wav
frames/ # 逐幀 JPEG
out/ # final.mp4 / final.srt / poster.png
qa/ # report.md + contact sheets + 抽幀
用 scripts/init_project.py 一次生成骨架。
3. 工作流程(8 步)
第 0 步:環境檢查
python scripts/check_env.py
必須:Python 3.10+、FFmpeg/ffprobe、一個 Chromium 核心瀏覽器、numpy/scipy。
建議:edge-tts(線上神經語音)、pypdf、python-pptx、python-docx、Pillow。
缺什麼按輸出的提示裝;裝不了就降級(無旁白 / 系統語音 / 手寫音訊)。
第 1 步:讀源材料,提煉「教學結構」
先回答 5 個問題(寫進 project.json 的 brief):
- 受眾是誰?他們已經會什麼?
- 看完後要能說出/做出什麼?(1–3 條可檢驗目標)
- 最容易誤解/最難的 1 個點是什麼?
- 必須出現的事實/公式/資料有哪些?來源分別是什麼?
- 時長與畫幅?平台(課堂/手機/社媒)?
不要直接按原文頁序講。用 references/storytelling.md 裡的 4 種結構之一重組:
- 因果鏈(推薦給理科/工程);
- 問題→解法→驗證;
- 誤區→糾正→遷移;
- 時間線/流程。
第 2 步:定風格與畫幅
按 references/styles.md 選 1 套(silicon / paper / blueprint / neon / swiss),按 references/formats.md 定畫幅。
規則:
- 內容偏「晶片/工程/資料」→ silicon / blueprint;
- 偏「人文/生物/歷史」→ paper;
- 偏「發布/行銷/年輕化」→ neon / swiss;
- 一屏只講一件事;豎屏必須重新排版,不要把橫屏裁成豎屏。
第 3 步:寫分鏡與腳本
產出 storyboard.md(人看)和 script.json(機器用)。每個鏡頭必須寫:
type(title/concept/process/compare/formula/bars/quote/recap/custom)kicker(小標題)、headline(一句話結論)、points(≤3 條)vo(旁白,1–2 句;沒有配音就留空)visual(圖/表/流程/公式的具體資料)duration(可空,由旁白時長自動定)
寫文案的 5 條硬約束:
- 螢幕字 ≠ 旁白稿:螢幕只留關鍵詞/結論,旁白負責解釋。
- 一屏最多 1 個結論 + 3 個支撐點;標題 ≤ 18 字,正文每行 ≤ 22 字。
- 每 2–4 秒要有變化(元素/鏡頭/強調),但不要粒子爆炸。
- 先寫「禁用清單」:漸變背景+居中大字、所有元素淡入、滿屏小字、無意義光暈。
- 事實句單獨標來源;不確定的加
[待核實]。
第 4 步:生成旁白與時間軸
# 可選:沒有配音就跳過,直接給每個 scene 寫 duration
python scripts/tts.py --project . --voice zh-CN-XiaoxiaoNeural --rate +3%
python scripts/timeline.py --project .
tts.py輸出audio/vo/<id>.wav(48 kHz),自動做輕 EQ/壓縮;支援--from-dir用真人錄音。timeline.py用實測旁白時長生成build/timeline.js與timeline.json:scene.duration = head + voDuration + tail,沒有旁白的鏡頭用顯式duration。- 之後只改 script.json 再重跑這兩步,不要手改 timeline。
第 5 步:搭建頁面與實現鏡頭
用模板:
python scripts/init_project.py --dir my-video --title "..." --format 16:9 --style silicon
# 編輯 build/content 由 timeline.py 生成;通用鏡頭已實現,直接改 script.json
- 通用鏡頭(8 類)在
build/scenes.js,讀CONTENT渲染;大多數講解片足夠。 - 需要專業圖(晶片/電路/解剖/地圖/分子)時,寫
build/custom.js:在window.CUSTOM['s3'] = function(u, D, sc, ctx){ /* 用 lib.js 的 helpers 畫 */ };script.json裡把該鏡type設為custom。 - 每次只做一個鏡頭:先渲染 3 張靜幀(
scripts/render.py --still 1.2,2.4,3.6),檢查文字溢出/重疊/主體大小,再繼續。
第 6 步:渲染
python scripts/render.py --project . --fps 30
# 只渲染某段:--start 8 --duration 4
# 複用已有 Chrome:--cdp http://127.0.0.1:9333
# 讓腳本自己起 Chrome:--launch-chrome
輸出 frames/f00000.jpg...,可斷點續渲(已存在且 >2KB 的幀跳過)。
無頭 Chrome 與 sandbox:如果運行環境禁止 Chrome 的 IPC/管道,需在允許的環境運行,或用
--cdp連接一個已啟動的 Chrome。
第 7 步:配樂、音效、混音、字幕
python scripts/audio.py --project . # 合成 BGM + 放旁白 + duck + 母帶
python scripts/srt.py --project . # 生成 out/final.srt
- 沒有旁白:
audio.py --no-bgm或只用使用者提供的音樂。 - 使用者提供音樂:放到
audio/music.*,audio.py會自動循環/裁切並 duck。 - 目標響度預設 −14.2 LUFS、真峰值 ≤ −1.5 dBFS;音訊只編碼一次。
第 8 步:編碼 + QA + 交付
python scripts/encode.py --project . # frames+mix+srt → out/final.mp4
python scripts/qa.py --project . # qa/report.md + 抽幀拼圖
QA 必須全部通過(見 references/qa.md):
- 時長/畫幅/幀率/音軌/字幕流正確;
- 無 ≥0.25 s 黑幀;抽幀無空白、無疊字、無溢出;
- 響度在目標 ±1 LU,真峰值 ≤ −1.5 dBFS;
- 首幀不是純黑;最後一個鏡頭有收束;
- 事實清單與源材料一致;
[待核實]已單列。
交付:out/final.mp4、out/final.srt、poster.png、storyboard.md、script.json、qa/report.md、渲染用時與已知不足。
4. 通用鏡頭類型(模板已實現)
| type | 用途 | 關鍵欄位 |
|---|---|---|
title | 開場/章節 | title/subtitle/kicker |
concept | 一個概念 + 3 個要點 | headline/points/visual |
process | 流程/步驟(3–5 步) | steps[] |
compare | 兩方對比 | left/right |
formula | 公式 + 解釋 | formula/notes[] |
bars | 資料對比 | items[{label,value}] |
quote | 金句/結論 | quote/author |
recap | 總結地圖 | nodes[]/takeaway |
custom | 專業圖 | 自己寫 custom.js |
需要新型別時:在 scenes.js 裡加一個 window.SCENES_IMPL['type'],並在 references/pipeline.md 記錄資料契約。
5. 畫幅與安全區
| 畫幅 | 尺寸 | 安全區 | 標題字號 | 正文字號 |
|---|---|---|---|---|
| 16:9 | 1920×1080 | 左右 96 / 上下 64 | 72–120 | 28–40 |
| 9:16 | 1080×1920 | 左右 64 / 上下 160 | 64–96 | 32–44 |
| 1:1 | 1080×1080 | 四周 72 | 56–88 | 28–40 |
| 4:5 | 1080×1350 | 四周 80 | 60–92 | 30–42 |
豎屏要重新排版:標題在上、圖在中、結論在下;不要橫向壓縮。模板用 layout() 根據畫幅切換,參考 references/formats.md。
6. 常見失敗 → 修法
| 現象 | 根因 | 修法 |
|---|---|---|
| 黑屏/白屏 | JS 報錯、render 未定義、canvas 尺寸 0 | render.py --still,看控制台;顯式給 canvas 寬高 |
| 字體不對/首幀回退字體 | 字體未載入 | 等 document.fonts.ready 再置 READY=true;CJK 用系統兜底串 |
| 同一 t 兩次不一樣 / 並行閃 | 用了 rAF/計時器/隨機/跨幀狀態 | 改純函數;hash(seed);閉式彈簧 |
| 文字重疊/溢出 | 沒有逐鏡靜幀檢查 | 每鏡 3 張靜幀 + 豎屏 360px 寬抽幀 |
| 音畫不同步 | 音訊從 0 開始 vs 影片從 start;TTS 逐句拼 | 同一 timeline;整段 TTS;-ss 放 -i 前 |
| 響度忽大忽小 | 多次 loudnorm/轉碼 | 只在 WAV 階段靜態增益;一次 AAC |
| 渲染太慢 | 4K/子幀/筆刷/WebGL | 先 960×540 小樣;子幀只給快動作;並行 worker |
| Chrome 起不來 | sandbox 限制 IPC/管道 | 在允許環境運行,或 --cdp 連已啟動 Chrome |
7. 擴展點
- 新風格:複製
templates/styles/*.json,改色板/字體/背景類型;在styles.md補一格。 - 新鏡頭:
build/scenes.js註冊;或build/custom.js寫專業圖。 - 真人配音:把錄音按
<scene-id>.wav放進audio/vo_human/,tts.py --from-dir只做重新取樣/輕處理。 - 多語言:一個
script.<lang>.json+ 對應 TTS 聲線;時間軸可複用同一套畫面(注意文字長度差異)。 - 多畫幅:同一
script.json用不同project.format重新 init/render;佈局由layout()適配。 - 品牌:
project.json.brand提供 logo 文字/顏色/頁腳;預設關閉。
8. 參考文件
references/pipeline.md:完整技術管線、render(t)契約、CDP 渲染、FFmpeg 參數、時間軸資料模型。references/inputs.md:PDF/PPT/DOCX/URL/影片的抽取與 OCR 兜底。references/storytelling.md:4 種教學結構、節奏表、文案規則。references/styles.md:5 套風格的色板/字體/動效/適用題材。references/formats.md:畫幅、安全區、豎屏重新排版規則。references/audio.md:TTS 選項、真人錄音、配樂合成、ducking、響度、單次編碼。references/qa.md:驗收清單與自動檢查命令。