p
開源專案 · 程式碼生成影像 / 音訊視覺化

程式碼渲染音樂影片與離線算圖管線

pdoom-video 是以 TypeScript 與 Three.js 建構的程式碼渲染音樂影片引擎。畫面每一幀皆為歌曲時間的確定性函數,保證瀏覽器即時預覽與 1080p60 / 4K60 離線匯出精確一致。專案包含音訊歌詞強制對齊工具、動態排版系統以及基於 Headless Chrome 的次影格動態模糊算圖管線。

984
GitHub Stars
17
場景模組
324×
最高次影格取樣
MIT
開源程式碼授權
01
架構概觀

確定性時間函數與生成式排版

pdoom-video 將整首歌曲的時間軸轉化為純數學函數,將視覺畫面定義為時間點 t 的確定性輸出。專案為歌曲《I'm Upping My P(doom)》製作,全程由 Claude(Opus 5.5)於 Claude Code 環境協同生成,涵蓋視覺概念、音訊對齊分析、引擎核心與 17 個場景模組。

架構分為兩個獨立層級:Python 音訊分析管線(使用 uv 管理 Demucs 音軌分離與 CTC 強制對齊),以及前端渲染引擎(Bun、Vite 與 Three.js)。渲染核心在瀏覽器內提供 60 fps 即時預覽,並透過 Headless Chrome 驅動離線算圖管線。

字型排版整合 Archivo、IBM Plex Mono、Cormorant Garamond 與單線繪圖字型(Single-stroke fonts)。歌詞依照字詞起訖時間逐字高亮,字體寬度(width 62–125)與字重(weight 300–900)隨樂句張力動態形變。

音訊分析至影音輸出生命週期
音訊分離→ 歌詞對齊→ 時序標記→ 場景渲染→ 次影格採樣→ 影像編碼
「Every frame is a deterministic function of song time, so the live preview in the browser and the offline 1080p60 (or 4K60) export are identical.」
— mexicat/pdoom-video 官方 README
02
環境需求與啟動

本機預覽與依賴安裝

執行渲染引擎需要 Bun、Google Chrome(離線算圖透過 playwright-core 驅動)以及支援 libx264 的 FFmpeg。複製儲存庫後進入 app 目錄安裝依賴並啟動 Vite 開發伺服器:

cd app bun install bunx vite

在瀏覽器開啟 http://localhost:5173 即可檢視即時畫面。網址加入 ?t=23 可直接跳轉至指定時間點(秒)。預覽介面支援以下鍵盤快捷鍵:

快捷鍵 控制操作
Space 播放/暫停(Play / Pause)
← / → 跳轉 ±1 秒(按住 Shift 跳轉 ±5 秒)
, / . 單影格逐格前進/後退
[ / ] 切換至上一個/下一個場景
l 循環播放當前場景(Loop scene)
h 隱藏/顯示除錯 HUD 介面

音訊分析管線(選用)

若需自訂歌詞或重新分析音訊特徵,進入 analysis 目錄透過 uv 執行對齊工具:

cd analysis uv run python align.py # 產出 data/lyrics.json uv run python analyze.py # 產出 data/audio.json
已提交之時序資料可直接使用。儲存庫已內建 data/*.json 完整對齊資料。僅執行即時預覽與影片渲染無需安裝 Python 與 uv。
03
算圖模式與管線工具

離線渲染器功能清單

專案透過 bun scripts/render.ts 驅動無頭 Chrome 與 FFmpeg,提供五種離線算圖、檢查與效能診斷模式。算圖腳本以 WebSocket 接收無損 raw RGBA 像素流,以 pipe 方式直接輸入 FFmpeg 編碼,避免磁碟暫存影格圖檔。

Render · 01
render.ts video
全片影音匯出
輸出完整 mp4 檔案,整合動態模糊、時間抗鋸齒與 AAC 音軌合成。
Render · 02
render.ts video --scale 2
真實 4K 母帶
以 3840×2160 物理解析度直接渲染所有著色器與髮絲線條,非放大升頻。
Inspect · 03
render.ts stills
精確時間點截圖
在指定秒數陣列擷取無損 PNG 影格,支援以 --only 隔離單一場景模組。
Inspect · 04
render.ts sheet
分鏡聯絡簿
以網格陣列排列多個時間點縮圖,支援 --cuts 自動抓取所有場景切換邊界。
Montage · 05
render.ts plates
場景代表圖集
為各場景產出代表性 JPEG 存入 public/plates/,供應片尾回溯蒙太奇。
Benchmark · 06
render.ts perf
影格耗時診斷
量測指定區間每影格平均耗時,包含 GPU 同步與像素讀回時間。
Engine · 07
AdaptiveSampling
自適應動態模糊
依畫面運動量自動選擇 12、36、108 或 324 次影格,誤差達標即停止取樣。
Pipeline · 08
analysis/align.py
音訊強制對齊
Demucs 分離人聲,搭配 CTC 聲學特徵與 Whisper 產出精確至字詞的起訖時間。

任務情境與指令參數決策表

任務情境 執行指令與模式 關鍵參數與說明
本機即時預覽與動效微調 bunx vite 網址帶入 ?t=<秒數>,按鍵 l 循環當前場景
輕量草稿匯出(快速確認分鏡) bun scripts/render.ts video --samples 4 --crf 20
標準 1080p60 交付版本 bun scripts/render.ts video --samples auto --shutter 0.2 --crf 16
4K60 極致解析度母帶匯出 bun scripts/render.ts video --scale 2 --samples auto --shutter 0.2 --x264 aq-mode=3:rc-lookahead=30
場景切換接點與銜接驗收 bun scripts/render.ts sheet --cuts --cols 4 --out ../out/cuts.png
單一場景著色器效能評估 bun scripts/render.ts perf --only shoggoth --from 30 --to 35
04
引擎架構與渲染原則

動態模糊與渲染管線規則

專案於 docs/ENGINE.md 制定了嚴格的無狀態與時間軸契約。為支援離線多影格動態模糊與 4K 超取樣,場景模組必須遵守以下核心設計原則。

RULE 01

純函數時間軸契約

場景輸出必須僅相依於歌曲時間 f.t。引擎嚴格禁止場景維護跨影格狀態或計數 render() 調用,確保自適應取樣器能以任意順序且無副作用地插補次影格。

來源 · 官方 docs/ENGINE.md
RULE 02

自適應次影格收斂階梯

--samples auto 依序按 4、12、36、108、324 階梯插補次影格。每次在現有採樣點兩側插入新點,當新舊均值最大差異低於 --tol(預設 3/255)即提前終止。

來源 · 官方 docs/ENGINE.md
RULE 03

60 fps 抖動與 frameIdx

影格等級的隨機抖動與閃爍必須使用 frameIdx(t) 作為種子,禁止使用 Math.floor(t * 60)。後者在快門區間內會因時間截斷產生雙重曝光偽影。

來源 · 官方 docs/ENGINE.md
RULE 04

4K 邏輯像素與物理解析度

--scale 2 分配 3840×2160 實體緩衝區,但場景座標一律以 1920×1080 邏輯像素計算。著色器需使用 FRAG_PX 與 pxLine() 確保髮絲線在 4K 下保持銳利。

來源 · 官方 docs/ENGINE.md
RULE 05

旋轉網格超取樣(RGSS)分工

內嵌 4 點 RGSS 的著色器在離線匯出時,每次影格僅分配一個取樣點,利用快門時間的多次影格自動平滑,著色器計算負擔降低 75%。

來源 · 官方 docs/ENGINE.md
RULE 06

字詞分段上色與 Kerning 保留

動態逐字高亮必須透過 glyphX() 取得絕對字元起點,禁止使用 measure(slice) 累加。後者會遺失字元對之間的 Kerning 數據導致字距崩壞。

來源 · 官方 docs/ENGINE.md
RULE 07

動態發射器與粒子時序

粒子發射率若隨時間改變,必須將發射率以 birth time 函數傳入(含 rateMax)。以當前 t 讀取發射率會導致粒子在不同次影格中被錯誤重置時序。

來源 · 官方 docs/ENGINE.md
RULE 08

多通道並行管線與無損拼接

4K 渲染耗時甚鉅。官方建議以 --from 與 --to 拆分時間區段在多個管線並行渲染,最後透過 FFmpeg 的 concat demuxer 進行無損合併。

來源 · 官方 README · 4K 算圖說明
05
終端機操作實例

從即時預覽到自適應 4K 算圖

以下演示如何在本地端啟動預覽伺服器、跳轉至特定時間點除錯、以聯絡簿模式檢查所有場景邊界,並執行具備自適應次影格動態模糊的 4K 母帶匯出。

~/pdoom-video/app · zsh · bun v1.2+
user@workstation ~/pdoom-video/app › bunx vite
[vite] dev server running at: [vite] > Local: http://localhost:5173/?t=0 [ready] three.js canvas initialized (1920x1080 logical) · audio loaded
user@workstation ~/pdoom-video/app › bun scripts/render.ts sheet --cuts --cols 4 --out ../out/cuts.png
[headless] chrome launched with --use-angle=metal [cuts] scanning 17 scene transitions in src/timeline.ts 0.00s open · 11.20s loss · 22.40s prompt · 31.80s hook · 42.10s room... [sheet] rendered 17 boundary frames to ../out/cuts.png ✓
user@workstation ~/pdoom-video/app › bun scripts/render.ts perf --only shoggoth --from 30 --to 35
[perf] benchmarking scene "shoggoth" (30.00s..35.00s, 300 frames) avg frame time: 38.4ms | gpu-sync: 11.2ms | pixel readback: 8.6ms [perf] target 60 fps headroom: PASS ✓
user@workstation ~/pdoom-video/app › bun scripts/render.ts video --scale 2 --samples auto --shutter 0.2 --x264 aq-mode=3:rc-lookahead=30 --out ../out/pdoom-4k.mp4
[ws] pipeline server listening on ws://localhost:57218 [render] scale=2 (3840x2160 physical) · target=60fps · crf=16 t=00.00s (open): 12 sub-frames (converged tol=3) t=32.40s (shoggoth zoom): 108 sub-frames (converged tol=3) t=64.12s (leftturn whip): 324 sub-frames (converged tol=3) [ffmpeg] encoded 9,400 frames · avg bitrate: 672.4 Mbit/s [export] render completed in 2h 28m → ../out/pdoom-4k.mp4 ✓
「The current code picks up to 324 sub-frames per frame where the motion needs them.」
— mexicat/pdoom-video 官方 README

離線確定性算圖的工程價值

傳統瀏覽器 WebGL 動畫受限於硬體垂直同步與每秒 60 影格的即時算力,無法直接輸出無瑕疵的高動態模糊與膠卷級顆粒。pdoom-video 將時間軸解耦為離線純函數,由無頭瀏覽器逐影格計算並透過 WebSocket 串流 RGBA 原始緩衝區至 FFmpeg,使 Web 技術能產出媲美專業後製軟體規格的 4K 母帶。

06
先看清楚這些

硬體負擔與授權邊界

  • GPU 與記憶體高強度消耗。4K 匯出時無頭 Chrome 與 FFmpeg 管線各自佔用約 4–5 GB 記憶體。光線步進(Ray-marched)場景在 108–324 次影格下單格耗時可達 10 秒以上,全片渲染在 Apple M5 Pro 晶片上耗時約 2.5 小時。
  • 膠卷顆粒編碼率激增。影片底片顆粒(Film grain)於 4K 物理像素等級著色,預設 CRF 16 編碼位元率達 670 Mbit/s(全曲檔案約 13 GB)。如需控制體積,需手動設定 --crf 18(約 450 Mbit/s)或 --crf 20(約 230 Mbit/s)。
  • 音訊與歌詞不屬 MIT 授權。專案程式碼依 MIT 授權釋出,但音軌(audio/pdoom.mp3)、歌詞原始檔(lyrics/)與字型(SIL OFL)保有各自版權,非 MIT 範圍,商業衍生需另行取得授權。
  • 無狀態時間軸限制。所有場景模組嚴禁維護累加變數或計數 render() 調用次數。若破壞純函數約定,自適應次影格取樣器將拋出異常並拒絕匯出。
  • 分析模型快取磁碟佔用。若執行 analysis/ 目錄下的 CTC 與 Demucs 音訊分離工具,PyTorch 權重將下載約 4 GB 至 analysis/.cache/,處理完成後建議手動清理。
  • Windows 環境編碼管線相容性。離線算圖腳本依賴 Bun 與 Playwright 導向 Chrome,並透過 WebSocket 與管道串接 FFmpeg。在非 macOS/Linux 環境建議於 WSL2 執行以避免管道中斷。
07
進階路徑

自訂場景與延伸探索

pdoom-video 的場景與時間軸採模組化架構,所有場景皆為 src/scenes/ 目錄下的獨立 TypeScript 模組。開發者可透過擴充自訂著色器、更換音軌與重新對齊歌詞,建構專屬的程式碼生成式影音專案。

進階開發地圖

1. 自訂場景模組。在 src/scenes/ 建立新檔案並實作 Scene 介面,於 src/timeline.ts 註冊其時間區段,即可接入時間軸排程。

2. 替換音軌與自訂歌詞。將新音訊放入 audio/,編寫初始歌詞後透過 analysis/align.py 與 analysis/analyze.py 重新計算字詞級時間戳記與節拍網格。

3. 自訂單線繪圖字型。在 src/engine/stroke.ts 中載入新的單筆畫 SVG 字型,支援透過光標筆尖動態繪製書法或工程製圖風格文本。

4. 光線步進著色器調優。參考 src/scenes/paperclips-glsl.ts 與 src/scenes/ilya-glsl.ts,實作客製化距離場(SDF)與 4 點 RGSS 旋轉取樣著色器。

5. 多管線並行算圖加速。長篇專案可使用 --from 與 --to 參數啟動多個無頭 Chrome 處理程序,最後使用 FFmpeg 串接無損 mp4 片段。

核心技術文檔閱讀清單

① docs/TREATMENT.md — 視覺概念書、17 個分鏡場景設計規範與卡拉 OK 排版準則。
② docs/ENGINE.md — 渲染引擎核心、字型系統、GLSL 著色器與自適應次影格取樣演算法規格。
③ app/scripts/render.ts — 離線無頭 Chrome 驅動、WebSocket 原始像素串流與 FFmpeg 管道實作。

「The words are part of the image, not subtitles on top.」
— mexicat/pdoom-video 官方 docs/TREATMENT.md · Karaoke rules