程式化向量卡通影片製作套件 (Procedural Cartoon Video Kit)
本技能提供一套純程式碼驅動、無外部素材依賴(零失真純向量)的卡通教學與導覽解說短影片製作管線。結合 Python Pycairo 繪圖引擎、Google Gemini 3.8 Flash TTS 語音配音、自動字數時長對齊、智慧標點斷句字幕 與 FFmpeg 音畫合成,可在數分鐘內自動化算繪出 1280×720 (30 fps) 高清 MP4 影片。
系統環境需求 (Prerequisites)
以 macOS 為標準執行環境:
# 1. 系統依賴與字型(必要:Noto Sans CJK TC 繁體中文黑體)
brew install ffmpeg cairo pkg-config
brew install --cask font-noto-sans-cjk-tc
# 2. Python 依賴庫
pip3 install pycairo numpy pillow
# 3. OpenRouter API 金鑰(用於 Gemini 3.8 Flash TTS 語音生成)
# 將 API 金鑰寫入 ~/.openrouter_key,確保不含換行符
echo "YOUR_OPENROUTER_API_KEY" > ~/.openrouter_key
chmod 600 ~/.openrouter_key
驗證環境:執行 python3 example_ds2.py auto,若能正常產生 example_ds2/grid.png 即表示環境配置完成。
專案標準目錄結構
my_video_project/
├── engine.py # 核心引擎:畫布底層、字幕生成、BGM 合成、Episode 類別、FFmpeg 管道
├── dc.py # 共用視覺模板庫(開場、路線圖、問答、重點整理…)
├── atian.py (或 xd.py / aj.py) # 主持人角色定義(覆寫 dc.doctor 實現全局換角)
├── ep1.py # 當集畫面代碼(各場景繪製函式 s0, s1, s2...)
├── ep1/ # 當集資產目錄
│ ├── script.json # 旁白文字腳本(字串陣列)
│ ├── c1.pcm ~ cN.pcm # 經 1.1x 加速處理後之各段語音檔(24kHz s16le PCM)
│ └── grid.png # 自動產生的全片縮圖預覽表(每場景 2 格)
└── tools/
├── make_payloads.py # script.json -> OpenRouter TTS 請求 JSON
├── tts.sh # 呼叫 OpenRouter 批次生成 24kHz PCM 語音
├── f0.py # 音高質檢腳本(中位數 Hz,檢出並重抽音高漂移段落)
└── prep.sh # 語音 1.1x 加速並重命名為 c1.pcm ~ cN.pcm
標準六階段製作流程 (SOP)
製作任何新的一集,嚴格遵循下列六個階段:
階段 1:腳本撰寫與場景劃分 (script.json)
- 於
ep1/script.json建立 JSON 字串陣列,一個字串即對應一個獨立場景 (Scene)。 - 單段旁白字數建議在 30 ~ 80 字之間(朗讀約 6 ~ 15 秒),節奏最為舒適。
- 標點符號請使用標準全形標點(
,、。、!、?、:、;),引擎會自動依標點智慧斷句上字幕。
階段 2:TTS 語音生成、音高質檢與 1.1x 語速優化
- 生成 TTS 請求檔:
注意:風格提示詞(如道地台灣國語、活潑青年導遊)必須填入python3 tools/make_payloads.py ep1instructions欄位,嚴禁填入input否則會被唸出來。 - 批次請求語音:
bash tools/tts.sh ep1 - 音高質檢 (F0 Pitch Check):
python3 tools/f0.py tts_ep1/*.pcm- 男聲
Puck正常中位數為 120 Hz ~ 160 Hz。 - 音高嚴格守則:若檢測發現任何一段 超過 165 Hz(代表 Gemini 誤漂移成女聲),必須單獨重新請求該段直至音高正常。詳見 audio-tts-pipeline.md。
- 男聲
- 語速加速與格式化:
將檔案以bash tools/prep.sh ep1atempo=1.1加速輸出至ep1/c1.pcm~ep1/cN.pcm。
階段 3:主持人角色綁定與特色繪製
- 角色模組必須符合標準函式介面:
def my_host(ctx, x, y, s, t, mouth=0.0, wave=False, point=False, sweat=False, happy=True, look=0.0): - 透過在模組底端執行
dc.doctor = my_host,全局一鍵替換所有模板的主持人。 - 完整繪製手法(眨眼計算、橡皮管手臂、音量 RMS 驅動嘴型開合)請參考 character-design.md 與 character_template.py。
階段 4:Pycairo 視覺場景代碼撰寫 (ep1.py)
- 為每個場景撰寫對應函式
def s0(ep, ctx, u, T, m):u: 本場景內的經過秒數。T: 全片絕對秒數。m: 即時語音振幅 (0.0 ~ 1.0)。
- 使用
ep.kw(sc, "精確關鍵字")獲取旁白唸到該關鍵字的精確秒數,驅動圖卡浮現。 - 關鍵函式與佈局 API 詳見 engine-api.md。
階段 5:快速縮圖預覽與視覺質檢 (Preview & QA)
python3 ep1.py auto
- 引擎會在 2 秒內快速抽樣全片每場景 2 格,拼合成
ep1/grid.png。 - 重點查驗:
- 文字是否有豆腐方塊(缺字)。
- 內容是否超出畫布邊界或字串重疊。
- 底部圖卡是否侵入字幕區(不得低於 y=610)。
- 右側圖卡是否與常駐主持人碰撞重疊。
階段 6:完整影片算繪與 FFmpeg 解碼驗證
- 正式算繪 MP4:
引擎自動合成 1280×720 H.264 影像、壓製字幕、混音 BGM(自動壓低)並封裝 AAC 音訊。python3 ep1.py - 完整性無損校驗:
終端機無任何報錯即代表影音同步、封裝完美無缺。ffmpeg -v error -i 輸出檔名.mp4 -f null -
核心 API 速查表
| 功能 | 語法 | 說明 |
|---|---|---|
| 進度計算 | prog(u, t0, d=0.5) | 自 t0 秒開始,經歷 d 秒由 0 變為 1 |
| 彈跳縮放 | pop(ctx, cx, cy, p) | 圍繞中心點彈跳出場(帶 back 曲線) |
| 關鍵字對齊 | ep.kw(sc, "文字", nth=0) | 精確推算該字詞被唸到的時間(已自動提前 0.25 秒) |
| 圓角矩形 | rrect(ctx, x, y, w, h, r) | 定義圓角路徑 |
| 填色描邊 | fillstroke(ctx, fill, stroke, lw=5) | 同時填色並深色描邊 |
| 單行文字 | text(ctx, s, x, y, size, col, align='c') | 繪製文字,可選靠左 'l'、置中 'c'、靠右 'r' |
| 膠囊標籤 | chip(ctx, "標籤", x, y, p, col, size=30) | 彈出式膠囊圖卡 |
| 彈出面板 | if panel(ctx, x, y, w, h, p): ... ctx.restore() | 內容白底面板(需與 restore 成對) |
| 右下主持人 | corner(ctx, T, m) | 於右下角繪製微縮版常駐主持人 |
| 章節大標卡 | station_card(ctx, u, 站號, "站名") | 章節開頭置中浮現大字卡(前 1.9 秒) |
| 重點整理結尾 | outro_doc(ep, ctx, u, T, m, sc, 標題, 副標, rows) | 天女散花紙屑、重點條列與下集預告結尾場景 |
踩坑避雷三大守則 (Crucial Guardrails)
- 字幕安全界線:
- 底部
y = 648 ~ 702為自動字幕專用區。 - 所有資訊面板、資料卡片、按鈕下緣嚴格禁止超過 y = 610!
- 底部
- 特殊符號與 Emoji 禁令:
- Pycairo 在
Noto Sans CJK TC字型下無法渲染 Emoji(如 ✨、📜、🌱)與特殊 Unicode 箭頭(➔、➜),會變成難看的豆腐方塊。 - 替代方案:箭頭用
->或調用arrow()函式;星星用star()函式;打叉用純英數符號×或mark(ctx, x, y, False, p)。
- Pycairo 在
- 關鍵字精確度:
ep.kw(sc, phrase)中的phrase必須是script.json該段文字中的精確子字串,不可多字、漏字或添加標點符號,否則會造成程序中斷。
參考文檔與範例資源
- 引擎架構與所有內建幾何元件:references/engine-api.md
- 向量角色設計與呼吸/眨眼/語音嘴型實作:references/character-design.md
- TTS 請求規格、F0 音高演算法與音訊處理:references/audio-tts-pipeline.md
- 畫布安全區、缺字防範與避坑清單:references/layout-and-pitfalls.md
- 角色範本代碼:examples/character_template.py
- 完整集數極簡範本:examples/minimal_episode.py