電影感科普短片 · 統一製作規範 v1
來源:《人類簡史 · 宇宙的自畫像》(4K / 4'58" / 14 場)與《向下 · DESCENT》(2K / 1'30" / 90 秒垂直剖面)。 兩部片子的規格、工作流、風格、踩過的坑,全部收在這裡。新片先讀第 0、1 節,再讀與本次相關的章節。
0. 鐵律(違反任何一條都會返工)
- 先定聲音,再定畫面。旁白逐句生成 → 量出時長 → 由時長反推每場幀數。絕不先排畫面再配音。
- 旁白與數據必須一致:片中出現的數字、單位、量級,逐條對照事實表;旁白說 98,畫面就不能寫 90。單位錯(如壓力 atm ↔ t/m²)比配錯色嚴重十倍。
- 一顆鏡頭一個資訊:每場只允許一個主命題 + 最多 3 個讀數;多出來的資訊交給旁白。
- 文字永遠可讀:任何文字下方必須有底襯或壓暗;層名 ≥ 30px、讀數 ≥ 13px;小字透明度不低於 0.6。
- 不許硬切:場與場之間用疊化 / 黑場呼吸 / 連續運動;同一部片只能用一種轉場語言。
- 靜音渲染:Remotion 裡
<Audio>一律{false && ...}關掉,音訊由 ffmpeg 外部合入(長 WAV 會讓渲染卡在 audio preprocessing)。 - 渲染前必須
npx tsc --noEmit乾淨,否則會渲出一堆壞幀再重來。 - 交付前三件事:全長校驗、首尾幀校驗、關鍵轉場逐幀校驗(每條 3–6 幀)。
1. 標準流水線(按順序,不可跳)
script.json ──► VO 生成 ──► VO 後處理 ──► 時長表 ──► 時間軸
│
└──► 配樂(numpy)──► 混音 ──► master.m4a
畫面(Remotion)──► 靜音渲染 ──► ffmpeg mux ──► 交付
1.1 劇本
- 每條一個 file:
script.json,欄位id / act / text / caption。 - 中文旁白 ≈ 4.2 字/秒;60 秒片 ≈ 200–230 字,90 秒 ≈ 300–340 字。
- 數字寫成中文讀法(「三千六百八十八」),否則 TTS 會讀錯;畫面裡再用阿拉伯數字。
1.2 旁白(Qwen3-TTS VoiceDesign,男聲紀實)
INSTRUCT = ("A deep, calm, authoritative male documentary narrator. Slow, deliberate, cinematic. "
"Low register, warm, intimate, restrained emotion, close-mic. Consistent, even pacing. Mandarin Chinese.")
generate_audio(text=..., model=model, lang_code="zh", instruct=INSTRUCT,
temperature=0.65, top_p=0.9, repetition_penalty=1.05,
output_path="vo_raw", file_prefix=id)
- 模型
mlx-community/Qwen3-TTS-12Hz-1.7B-VoiceDesign-bf16,mx.random.seed(11)固定。 - 每條生成後立刻
ffprobe驗時長:若某條 > 30 秒或出現整段重複,就是 TTS 退化了,刪掉重生(換 seed 或把repetition_penalty提到 1.12)。 - ASR 複檢:
mlx_whisper轉一遍,核對數字/生僻字(氫→清、矽→龜、鐵→體 這類)。
1.3 聲音後處理(統一鏈,不許各條不同)
highpass=f=70,
asetrate=24000*0.912341, aresample=48000, atempo=1.096081, atempo=1.055,
equalizer=f=190:t=q:w=1.0:g=1.4, equalizer=f=3300:t=q:w=1.4:g=-1.8, equalizer=f=7200:t=q:w=1.8:g=-1.0,
acompressor=threshold=0.14:ratio=2.2:attack=10:release=200,
loudnorm=I=-20:TP=-3:LRA=7
再按 20ms 能量包絡裁掉首尾靜音、把超過 0.34 s 的停頓壓到 0.34 s,兩端 12ms/50ms 淡入淡出。
1.4 時間軸
frames = round(seconds * 24);旁白偏移 = 場起點 + lead(一般 18–24 幀)。- 每場:
lead + vo + tail,tail 16–90 幀(結尾卡給足)。 - 生成
timeline.ts(自動生成,別手改),欄位{ id, from, dur, voAt, voDur }。
1.5 配樂(純程式碼合成,numpy)
- 要有結構,不要鋪滿:按時間碼寫「事件」,而不是一條 pad 到底。
- 和聲:每 12–18 秒換一次,交界處交叉淡化;低音只做 55 Hz 以上的持續音。
- 不要低頻轟鳴:觀眾會形容為「轟轟聲」「太吵」。低音截止 85–100 Hz,長音用純正弦,不加八度諧波。
- 安靜優先:音樂電平 ≈ 旁白的 −20 ~ −27 dB;旁白出現時再壓 40–70%(側鏈閃避)。
- 終混響度:紀實片 −18 ~ −24 LUFS(不是 −14,那是串流媒體流行樂)。
- 教程式的「音效設計」(入水悶響、聲納、金屬吱呀)只在客戶明確要時加;被否過一次,預設不用。
1.6 畫面(Remotion)
見第 2 節。
1.7 渲染與合入
npx tsc --noEmit
npx remotion render Film4K out/silent.mp4 --codec=h264 --crf=18 --concurrency=7
ffmpeg -i out/silent.mp4 -i public/audio/master.m4a \
-map 0:v -map 1:a -c:v copy -c:a aac -b:a 320k -shortest -movflags +faststart out/final.mp4
- 4K = 1920×1080 佈局 +
transform: scale(2);2K =scale(2560/1920)。只寫一套佈局。 - 局部返工:只重渲該段幀區間 →
ffmpegtrim/concat三段拼接 →-c:v copy只換音軌;要換畫面就三段重編碼拼接(約 5–10 分鐘)。
2. 視覺系統
2.1 底板
- 畫布 1920×1080,24 fps;
AbsoluteFill背景近黑(#01050A/#010407),永遠不要純黑 #000。 - 三層結構:背景漸層 → 體積光/粒子 → 資訊層(文字、深度尺、讀數)。
- 收尾統一:
Vignette+ 靜態Grain(0.04,必須animate={false},動態顆粒會讓細線閃)。
2.2 字型
- 標題/詩句:
Songti SC(serif),字距 0.4–0.6em,大字型(90–250px)。 - 數據/讀數:
SF Mono,8–14px,字距 0.16–0.36em。 - 說明:
PingFang SC,14–19px,透明度 0.55–0.7。
2.3 調色(兩部片各自的「世界觀色」)
| 片種 | 頂部亮 | 中段 | 底 | 強調色 |
|---|---|---|---|---|
| 宇宙 / 時間 | #050506 底 | 奶油 #F3E7D0 | — | 琥珀 #E8B06A |
| 海洋 / 深度 | #1E7C93 水面 | #07232E | #01050A | 青 #4FE0C0 |
規則:同一部片只用一個強調色;生物發光/熱液這類例外最多兩種,且各自綁定一種物理量。
2.4 粒子引擎(Canvas 2D)
- 確定性隨機(hash),同一幀永遠同一結果;雲類型:
ball / filament / disk / globe-surface / sphere-shell / figure / city / helix / neuron / glyph / single / text / timeline。 - 兩遍繪製:先大半徑低透明度做輝光,再小半徑高透明度畫核心;
globalCompositeOperation = 'lighter'。 - 點雲邊界必須在畫面外:
makeCloud('text', n)是 3×1.2 的盒子,投影後會出現矩形邊(最常被觀眾指出的 bug)。用expand(cloud, kx, ky, kz)放 2.4–3.2 倍。
2.5 生物與地形(SVG)
- 一律側視、頭朝運動方向;眼睛、鰭、嘴線、喉褶、藤壺等解剖細節至少 4 處,否則像貼圖。
- 剪影 + 邊緣光(0.2–0.35 透明度);不要用
feTurbulence疊在身體上(會變成花崗岩)。 - 地形:多段折線 + 岩層線 + 岩屑 + 沉積,不要三角形;山體不要畫基線(會變成圖表)。
- 生物出現視窗按「深度/時間」綁定,別同時出現三種以上。
2.6 資訊層(HUD)
- 層帶銘牌:深色漸層底(0.72→0)+ 左側 2px 強調色豎條 + 中文 30–35px 純白。
- 讀數:每層 2–3 組,
LABEL8.5px /VALUE13–14.5px。 - 刻度尺:刻線 + 當前值加粗;當前值必須即時計算,不能寫死(寫死會與指標矛盾)。
- 所有數字帶單位;單位用空格分隔(
1,093 atm)。
2.7 轉場
- 首選連續運動(一鏡到底):深度/時間是一個連續量,內容隨它進出畫面。
- 次選短疊化(4–6 幀,只有新鏡頭淡入、舊鏡頭保持不透明被覆蓋)——亮度不塌、HUD 不疊字。
- 禁用:斜向光掃、長交叉溶解、垂直推鏡(會露出暗邊)、黑場後硬切(除非是「入水」這類物理動機)。
3. 事實與數據
- 建一張
facts.md:每條數字 / 單位 / 來源範圍 / 片中怎麼寫。 - 三處最容易錯:① 單位換算(1 atm ≈ 10.3 t/m² ≈ 1.03 kgf/cm²);② 「平均」與「極值」混用(平均 3,688 m vs 最深 10,935 m);③ 簡化說法(90 vs 98 種元素)。
- 全片統一一種精確版本;旁白與畫面必須同源。
4. 交付物清單
deliverables/
片名-4K-旁白版.mp4 # 主版本
片名-4K-純音樂版.mp4 # 如需要
海報-4K.png / 預覽-4K.png # 關鍵幀合成
封面/ # 1920 PNG + 4K PNG + 1146×717 JPG
導演闡述.md # 結構、聲音、修改記錄
發布文案-B站.md # 標題/簡介/標籤/置頂評論/封面建議
事實表.md
發布包必帶:AI 生成聲明、製作分工(模型做了什麼、人做了什麼)、一版「容易看錯的數字」置頂評論。
5. 踩坑記錄(按出現頻率排序)
| 現象 | 根因 | 修法 |
|---|---|---|
| 渲染卡在 audio preprocessing | 長 WAV + <Audio> | 靜音渲染,外部 mux |
| 文字在粒子上一片糊 | 無底襯 + 透明度 0.4–0.5 | 底襯 + 純白 + 加大字型 |
| 畫面出現規則矩形(觀眾最愛問) | 點雲盒子邊界進畫 | expand() 放大 2.4–3.2× |
| 細線/山體閃爍 | 動態 film grain | Grain animate={false} |
| 鯨/魚「倒著游」 | 頭和尾畫反、眼在尾端 | 側視重構:頭在 +x |
| 山體像圖表 | 路徑用 L ... Z 收了水平基線 | 底邊沉到畫面外 |
| 轉場打斷視線 | 光掃/長溶解 | 短疊化或連續運動 |
| 配樂「轟轟」 | 27–80 Hz 持續低音 | 高通 85–100 Hz,去掉 sub drone |
| 音畫不同步 | 畫面節拍與旁白內容不對應 | 深度/時間曲線按旁白內容重排 |
| TTS 單條 600 s | 模型退化循環 | 刪掉重生,repetition_penalty 1.12 |
| 4K 返工太慢 | 全片重渲 | 只渲改動幀區間 + concat |
6. 兩部參考片的位置
- 《人類簡史 · 宇宙的自畫像》:
~/dsh-video-remotion/film/src/scenes/*,14 場,4K,4'58"。 - 《向下 · DESCENT》:
~/dsh-video-remotion/film/src/ocean/*,6 層帶,2K,1'30";旁白與配樂在~/dsh-video-remotion/ocean/。 - 兩者共用
src/engine/particles.tsx(粒子)、src/engine/atmos.tsx(Vignette/Grain)、src/theme.ts(字型/調色/緩動)。