卡通 3D 故事短片(three.js + Remotion)
已驗證範例:The Bridge That Fell for a Song。這是一部原創的 67 秒短片,講述了 1831 年布勞頓橋和 74 名士兵齊步走的故事。
- 程式碼:Remotion 專案的
src/videos/bridge/(合成畫面BridgeShort,1080x1920,30 fps)。 - 腳本、語音和音效:
~/bridge-short/。 - 風格研究:
references/。
風格參考來自私下研究的頻道(references/:STYLE_BIBLE.md、reports/*.md、frames/)。
- 那些影片是私下研究資料。切勿上傳、發布或傳送它們。
- 切勿複製他們的腳本、角色或鏡頭。故事、角色和語音必須是我們自己的。
- 切勿在旁白或描述中說出頻道名稱。
使用者適用的規則:
- 影片中無字幕或標籤。
- 僅限英文。
- 語音:語調平穩統一。
- 笑話必須基於研究過的真實事實。
- 標準混音:音樂 +3 dB,音效 -6 dB,語音不變。
- 最終輸出為 2K 垂直:1440x2560,
--scale 1.3333。 - Opus max 驗證每一步。
- 每一步完成後都要儲存。
- 腳本一經批准,就「直接執行」。
工作流程
- 主題與事實。 挑選一個令人驚訝的真實故事,具有物理上的因果關係(必須是視覺化的),並搭配一個簡單的日常類比來解釋它。
- 在
SCRIPT.md頂部寫下事實及其來源。
- 在
- 腳本(約 3.7 字/秒,55-70 秒)。沿用橋短片的小節公式:
- 鉤子: 一行聳人聽聞的事實(「74 名士兵只是走過一座鐵橋就把它震垮了。」)。
- 設定: 年份、地點、自豪感。
- 行動: 三到四個小節逐步升級,每個小節規模略大。
- 斷裂: 崩塌的瞬間。
- 面無表情的雙行台詞: 「幸運的是……/不幸的是……」。
- 解說: 透過日常類比(盪鞦韆的小孩)解釋一個物理概念。
- 後果: 它創造的規則。
- 呼應轉折: 結局。
- 切勿描述觀眾已經看到的畫面。
- 語音。 錄製或生成
voice.wav,然後製作其字詞時間戳words.json(使用任何能提供字詞時間的語音轉文字服務)。- 將它們放在專案資料夾中,例如
~/bridge-short/voice/。 - 手動修正字詞時間戳。所有內容都根據 words.json 進行時間同步。
- 將它們放在專案資料夾中,例如
- 鏡頭規劃 在
story.ts中:複製templates/bridge/(最終的橋原始碼,與 Remotion 專案的src/videos/bridge/相同)到src/videos/<name>/,在src/Root.tsx中BridgeShort旁邊註冊一個新的合成畫面,並重新命名。SHOTS:id、a/b 影格、白天/金色光線、群眾模式、tau故事時間。XFADE:場景/時間變換處的交叉淡出。FLASH_AT:鉤子之後的白色閃光。CAMS:每個鏡頭的關鍵幀{f, dur?, cut?, s: f => {pos, look, fov, roll}}。KICKS:撞擊時的翻轉震動。DOF/dofAt:每個小節的鏡頭模糊。FOREGROUND:近景取景道具。- 每個視覺反應都落在其對應字詞前 0-3 幀的位置。
- 世界。
lights.ts:燈光加上每個燈光下的 LOOK 天空/河流/雲彩調色盤。shade.ts:雙色調陰影和untone()。build.ts:城鎮、房屋和 Kenney CC0 套件道具,重新著色,並對阻擋任何相機視線的物體進行視線剔除。paint.ts:HD Canvas2D 繪製紋理,接縫處以深色色調繪製。world.ts:天空著色器、霧氣 = 地平線顏色、河流、逐影格姿勢、每個鏡頭凍結的太陽(相對於相機)。
- 角色。
toon.ts:Canvas2DPen繪圖 API,600x1000 設計畫布,腳底在 y = 975,豆形頭部,棍狀四肢,李子色可變寬度輪廓,表情庫。cast.ts:面向相機的廣告牌、群眾、效果卡、眨眼、行走循環。所有廣告牌都放在NOINK圖層上。cardshade.ts:卡片由場景光照亮,無自發光。
- 後期(
Bridge.tsx+ink.ts+lensblur.ts+grade.ts)。- 合成器順序:墨水 → 鏡頭預處理 → 鏡頭主體 → 泛光 → NEUTRAL 色調映射 → 調色(MSAA 4)。
- 每個像素參數都隨輸出高度 / 1920 縮放。
- 音效(
~/bridge-short/audio/:timeline.py、sfx_gen.py、sfx.py、music.py、instruments.py、dsp.py、mix.py)。- 事件表 → 合成的音效加上在語音下方閃避的原創配樂。
- 輸出:mix.wav(48 kHz,精確長度)、分軌和 cues.md。
- 在製作音效之前鎖定畫面的時間常數。任何後續的時間變更都意味著重新執行音效。
- 外觀檢查。 執行
node scripts/bridge-stills.mjs out/<name>/x_ 100,400 0.5。- 設定
BRIDGE_ENTRY=src/sandboxes/<n>/index.tsx以渲染沙盒副本。 - 使用
python scripts/sbs_sheet.py out.jpg --ours ... --ref ...製作與參考影格的並排比較。 - 將它們發送給 Opus max 驗證器:1-3 張圖片,一份 ≤200 字的判定。
- 設定
- 最終渲染。
npx remotion render src/index.ts <Comp> out/<name>/video.mp4 --codec h264 --crf 16 --scale 1.3333- 使用
-map 0:v:0 -map 1:a:0進行混流(Remotion 會寫入一個靜音的音軌)。 - QA:
python scripts/short_qa.py final.mp4 out/<name>/qa shots.json檢查每個影格是否有黑色、白色、凍結和跳幀,以及響度和圖表。 - 修復它發現的任何問題,然後執行一次深入的 Opus 審計。
- 交付。 將最終的 mp4 檔案傳送給使用者(SendUserFile),更新記憶,撰寫筆記。
最終外觀數值(橋短片經過 4 輪驗證後;全部在 templates/bridge/ 中)
每個新短片都從 templates/bridge/ 開始(複製到 src/videos/<name>/):外觀存在於這些數值中,故事存在於 story.ts / build.ts 佈局 / cast.ts 角色中。Opus max 最終得分:白天色彩 7,金色 5-6,光照 5-6,墨水 6,紋理 5-6,角色 7,深度 6-7,構圖 6-7(起始分數為 5/3/4/5/4/7/4/6)。
- 燈光預設(
lights.ts,太陽相對於相機並為每個鏡頭凍結):- 白天:方位角 75 / 仰角 48,光照 [1.58,1.5,1.33],陰影 [.30,.29,.36],提升 [.05,.06,.11](僅在陰影中使用冷色調),天空頂部 #3e7fd2 → 地平線 #b8d0ec,霧氣 = 地平線,25→300 米,uSat 1.08,超過 60 米約有 15% 的藍色霧靄。
- 金色:方位角 6 / 仰角 7(背光低角度太陽),主光朝向 #FFB36B ×1.5,紫藍色陰影(建築物正面 ≈ #444380),天空 #ffc47c → #8a6f8a,僅超過 50 米有桃色霧氣,太陽光碟 #ffcf9e + 泛光,接觸光斑 + 真實卡片陰影。
- 反照率(
paint.ts/build.ts):帶有底座、檐口、窗台、門罩、台階、煙囪和煙囪帽的柔和紅磚/奶油色/赭色/陶土色房屋,高度 7 / 8.4 / 9.8 米;暖灰色/米色石材(來自「故事書」風格的飽和度 -35%);赭色木甲板 C* ~51-58,帶有近黑色接縫;鐵材暗沉且去飽和。切勿使用檸檬色、薰衣草色光照下的臉部。 - 墨水(
ink.ts):#030303,近距離 5.1 像素(6 米)→ 遠距離 3.3 像素(90 米)(在 1080x1920 下),從 35° 開始的摺痕 ×0.8,深度跳躍從 1% 開始,僅遠處霧氣色調 0.3;角色卡片位於NOINK圖層(它們自帶李子色墨水)。 - 鏡頭(
lensblur.ts+story.ts中的dofAt):在 1080 下 cInf 像素:鉤子/河流特寫 15-16,近景 12-14,中景 10-12,公園 7,金色搖擺 5,寬景/鳥瞰 0。對焦在前排角色的眼睛上。 - 後期(
Bridge.tsx):墨水 → 鏡頭預處理 → 鏡頭主體 → 泛光(閾值 1.0,強度 .5,6 層,半徑 .6)→ NEUTRAL 色調映射 → 調色;MSAA 4。存在膠片顆粒但已關閉(參考資料顯示無顆粒;它會使檔案大小增加四倍)。 - 角色(
toon.ts/cast.ts/cardshade.ts):豆形頭部高/寬 .94,李子色墨水 #241726,眼睛間距 .26 W,無腮紅,14 種表情;成年人高度 3.5 個頭部高度;行走上下晃動 5 %,傾斜 1-7°,著地步伐 0.8 米;眨眼 0.5-2.3 秒;白天在腳下緊密接觸陰影 ~.5 + 太陽方向尾部;金色光線僅內緣反光(永遠不是偏移的外部副本)。 - 相機(
story.ts):大幅跳躍時硬切,平滑步進滑行 18-40 幀,每個停頓都有微微移動(無 ≥4 幀的靜止停頓),撞擊時翻轉震動在 7 幀內衰減,4-4.6° 的滾轉,前景道具(FOREGROUND)出現在約 1/3 的鏡頭中。
外觀目標(根據參考資料測量;請參閱 references/reports/)
- 墨水:
- 世界線條:在 1080 寬度下約 3 像素,近黑色 #0b0a0c,隨距離變化不大。僅有輪廓、深度跳躍和法線摺痕。牆壁/地板接縫或地平線處無線條。角色卡片永遠不會被世界墨水勾勒輪廓。
- 角色墨水:深李子色 #201628-#2f1d28,在底部/陰影側較粗。
- 色彩:
- 白天中位亮度 ~.57。非墨水區域的 p5 亮度 ~.23(無暗部細節缺失)。光照區域色度 C* p90 ~55。白天天空頂部 ~#5e93d9,地平線亮度 1.28 倍。
- 金色:桃色地平線 #ffd08a,紫藍色陰影(永遠不是棕色),背光太陽。
- 深度:
- 約 1/3 的螢幕時間有景深效果(特寫、中景、插入鏡頭),在 1080 下 cInf 10-16 像素,焦點在眼睛上。定場和廣角鏡頭保持清晰。
- 霧氣 = 地平線顏色,白天 25→420 米,金色 20→360 米。
- 泛光僅作用於 HDR 自發光物體:閾值 1.0。
- 相機:
- 大幅跳躍時硬切。其他所有移動都是 18-40 幀的平滑步進滑行,在 720p 下峰值 ≤ 25 像素/幀。
- 每個停頓都向前推進 0.15-0.35%/幀,關鍵字詞上為 0.6%/幀。
- 滾轉 4-5°。
- 無手持晃動。撞擊震動每幀翻轉符號並在 7 幀內衰減。
- 角色:
- 約 3.5 個頭部高度,腿長 1.4 個頭部高度。
- 棍狀四肢約為頭部寬度的 0.055,墨水點狀手。
- 豆形頭部(高/寬 ~0.93,較窄的下巴,較尖的頭頂)。
- 無腮紅或眼睛高光。臉部亮度約 ~.93。
- 行走上下晃動 3-7%,傾斜 1-7°,腳步著地。
- 每 0.5-2.3 秒眨眼一次,持續 4 幀。
外觀匹配循環(橋短片外觀的達成方式;可用於任何「讓它看起來像 X」的後續處理)
- 首先測量參考資料。 每個主題(運動、深度、紋理、角色、光照、輪廓、調色)由一個分析代理負責,為
references/reports/<topic>.md撰寫數字,而非形容詞。共享簡報:compare/CONTEXT.md。報告是所有後續代理的真相來源。 - 沙盒,每個檔案一個所有者。 將專案資料夾複製到
src/videos/<name>_{cam,world,mat,char,post},並在src/sandboxes/<n>/index.tsx中設定入口點(與主index.tsx相同,僅更改導入路徑)。橋短片的所有權分配:- cam:story.ts(相機關鍵幀、切換、震動、景深表、前景道具)
- world:world.ts、lights.ts、shade.ts、grade.ts(太陽、天空、霧氣、河流、色彩、調色)
- mat:paint.ts、build.ts(繪製紋理、建築物、道具)
- char:toon.ts、cast.ts、cardshade.ts(角色繪製、姿勢設定、卡片光照、效果卡)
- post:ink.ts、Bridge.tsx、lensblur.ts(輪廓處理、合成器、鏡頭模糊、泛光)
代理僅在自己的沙盒中編輯自己的檔案,並使用
BRIDGE_ENTRY=src/sandboxes/<n>/index.tsx node scripts/bridge-stills.mjs out/<name>/<n>/x_ <frames> 0.5渲染靜止畫面。
- 合併 使用
python scripts/bridge_merge.py [cam,world,mat,char,post](將主程式備份到backup/bridge_<time>/,僅複製所屬檔案)。然後執行npx tsc --noEmit(過濾到專案資料夾),然後在下一輪之前從主程式重新同步每個沙盒(cp -f src/videos/<name>/* src/videos/<name>_<n>/)。 - 驗證 使用一個新的 Opus max 代理:並排比較圖表(
python scripts/sbs_sheet.py out.jpg --ours a b --ref r1 r2),為每個領域評分(滿分 10 分)(白天/金色色彩、光照、墨水、紋理、角色、深度、構圖),並附帶一個包含影格編號的編號修復清單。將每個修復對應到檔案所有者,並使用 SendMessage 恢復該所有者的代理(保留其上下文)。橋短片得分:第 1 輪 5/3/4/5/4/7/4/6 → 第 2 輪 5/4/5/6/4/7/6/6 → 第 3 輪請參閱筆記。 - 所有權之間的合約存在於導出的常數中(例如
ink.ts中的NOINK圖層,story.ts中的dofAt/FOREGROUND,lights.ts中的LIGHTS/LOOK)。更改合約意味著要告知所有讀取它的所有者。
注意事項
- Kenney 自然套件材質是藍綠色的:在 build.ts 中按材質名稱重新著色。
- 相機最後會進入房屋內部:build.ts/world.ts 中的視線剔除器會移除任何阻擋相機光線的物體。
- 如果將墨水與景深放在同一個合併效果處理中,墨水會被覆蓋。墨水必須在模糊處理之前獨立進行一次處理。
- 像素級別的後期參數必須隨解析度縮放:靜止畫面為 0.5,最終為 1.333。R3F 將 dpr 限制為 ≥ 1,因此
--scale 0.5的靜止畫面仍會渲染 1080x1920 的緩衝區。 - 磁碟: 每個 Remotion 捆綁包都會將
public/(~1.3 GB)複製到臨時資料夾\remotion-webpack-bundle-*中,並且永不刪除。橋短片處理過程中,60+ GB 的資料填滿了系統磁碟,導致渲染因 ENOSPC 錯誤而失敗。始終使用export TEMP='<大磁碟>/remotion-tmp' TMP='<大磁碟>/remotion-tmp'進行渲染(bridge-stills.mjs 會自行設定),並在使用者刪除共享臨時資料夾中的舊捆綁包資料夾之前詢問使用者(自動模式會阻止清理)。<大磁碟>/remotion-tmp 也會被填滿(橋短片 4 輪後約有 500 個資料夾 / 110 GB):當一個專案完成且沒有正在渲染的任務時,刪除其中的remotion-webpack-bundle-*和puppeteer_dev_chrome_profile-*資料夾。 - 在 JS 字串中,請使用
"<大磁碟>/remotion-tmp",切勿使用"<大磁碟>\remotion-tmp"(\r會變成回車符)。 - Remotion 會寫入一個靜音的音軌:使用
-map 0:v:0 -map 1:a:0進行混流。 - 子代理無法在此工具環境中寫入報告檔案:要求它們提供一份 ≤150 字的最終訊息,然後您自行將其儲存到
out/<name>/<n>/REPORT.md。 out/內部的臨時.ts檔案會破壞tsc:請將它們命名為.txt。- 2K 渲染速度約為 4 fps(67 秒約需 10 分鐘)。0.5 比例下的靜止畫面在約 40 秒的捆綁後,每個需要 3-8 秒。
- 2.5% 的膠片顆粒會使 2K 檔案從約 250 MB 變成 910 MB,並且在 YouTube 上會變得模糊;參考資料中沒有顆粒。請保持關閉。
驗證器發現的可讀性陷阱(檢查每個新道具/鏡頭是否存在這些問題)
- 一個鞦韆如果畫成一根繩子消失在小孩身後,看起來會像上吊。 一定要用兩根繩子連接到一塊寬木板,小孩在中間(
toon.ts中的swingKid),並且使用一個其腿部能避開弧線的框架(兩端各一個 A 形框架)。 - 距離鏡頭小於約 2 米的道具或漂浮物會變成巨大且被切斷的模糊色塊。當相機移動時,請重新檢查其新位置附近的每個道具(河流相機移入了漂浮的帽子中)。
- 被畫面邊緣切斷的前景灌木叢看起來像一個「綠色球體」;前景道具必須是可識別的,否則就不要放。
- 旗幟:紅色 + 黃色星星/菱形看起來像越南的旗幟。請使用符合時代背景的旗幟(1831 年的英格蘭使用聖喬治十字旗)。
- Pain
…
[為翻譯而截斷]