竖屏實拍口播短視頻剪輯(Windows + Codex + 剪映)
適用場景:手上只有別人拍好的素材(口播 + 空鏡),要剪成 30–50 秒、1080×1920 的豎屏短視頻,最後由剪輯師在剪映裡收尾或直接出片。
硬規則(不可違反)見 references/AGENTS_rules.md,開工前把它放進項目的 AGENTS.md。本文件只講流程。
輸入
- 素材目錄(唯讀,絕不改動原件;先複製一份到工作目錄)。
- 剪輯師本人的風格習慣(若有)。剪輯師本人說過的習慣 = 硬標準;參考片只當招式庫,學手法不學參數,衝突時聽剪輯師。
- 可選:參考片、品牌標識位置、片尾 CTA 文案(不得寫未核實的電話/地址)。
輸出
spec.json(分鏡,唯一剪輯依據)、粗剪成片或成片 mp4、.srt、逐秒 QC 拼圖、QC 報告。- 路線 A 額外交付:剪映草稿;路線 B 額外交付:透明疊加層 ProRes 4444
.mov。
第 0 步:環境自檢(不過不開工)
按 references/windows_env.md 跑自檢:ffmpeg 完整版(帶 zscale、tonemap、prores_ks)、Python 3.10/3.11、faster-whisper + whisperX、Playwright + Chromium + 目標中文字體,可選 demucs / RVM;剪映草稿目錄已填進配置並加入 writable_roots。Codex 沙箱預設斷網,模型和依賴要提前裝好。任何一項失敗,先報告缺什麼,不要硬跑。各步驟的具體命令見 references/windows_commands.md。
第 1 步:素材盤點
- ffprobe 每個檔案:解析度、幀率(是否可變)、旋轉、時長、色彩傳輸(HLG/PQ = HDR)。寫成
inventory.csv。 - 不導出 SDR 中間檔案:每次讀幀時在濾鏡鏈裡現轉。所有素材都加
fps=30;HDR 素材的讀幀濾鏡鏈以 HDR 轉 SDR 開頭,否則畫面發灰,截封面幀也一樣(命令見windows_commands.md第 2 節)。 - 每條素材抽縮圖打標籤(內容、人物、可用時段、遮擋/黑場/起始偏暗、是否他人品牌)。標出不能用的素材和時段。
- 檢查:每條素材都有標籤;傳輸特性為 arib-std-b67 或 smpte2084 的素材,讀幀濾鏡鏈都以 HDR 轉換開頭。
第 2 步:聽寫與校對
- faster-whisper 粗聽:
medium模型、device='cpu'、compute_type='int8'、language='zh'、vad_filter=True、word_timestamps=True,initial_prompt放行業詞表。VAD 會漏句,再跑一遍關 VAD 的,這一遍加condition_on_previous_text=False。 - 先人工對照音頻校對全文:專業詞、數字、同音錯字;Whisper 還會憑空編出沒說過句子,要刪掉。聽不清的詞直接從音頻剪掉,不猜。
- 聽寫前固定先用 ffmpeg 抽 16 kHz 單聲道 WAV 再交給 whisper。再把校對稿送進 whisperX 做強制對齊(結果寫進 spec 的
align欄位),拿逐字起點(誤差 0–3 幀)。whisperX 的字尾時間不可靠,出點用能量檢測。
- 檢查:轉寫裡沒有未校對的專業詞和數字;每句有逐字起點。
第 3 步:敘事重組(先定敘事,再定特效)
- 第 1 秒必須是鉤子:「反差 + 結果」,用原話。片頭不放空鏡和 logo。
- 鉤子可以把兩句不相鄰的原話拼起來,但每半句都帶
src_t,拼完不能改變原意。 - 聲音二選一,寫進 spec:第一句照常開口、大字壓在上面;或把結果句(≤3 秒)提到片頭做冷開場,再回到正常順序。
- 鉤子可以把兩句不相鄰的原話拼起來,但每半句都帶
- 刪掉不推進故事的句子(口號、鋪墊、重複表態),目標 30–50 秒。
- 標出 3–4 個敘事轉折點(開頭鉤子 / 場景轉換 / 高潮結果 / 收束金句),爆點只放在這些位置;高潮力度排第一,開頭次之。兩個爆點至少隔 6 秒;約 30 秒的片子放 3 個,約 50 秒放 4 個。
- 檢查:每條上屏文字都能在轉寫裡找到原話和時間戳,並核對上下文(同一個詞在不同句裡意思可能不同)。
第 4 步:寫分鏡 spec.json,請用戶確認
欄位規範見 references/spec_schema.md,關鍵詞類別示例見 references/kw_class.example.json(示例裡的詞是某個項目的,換項目要重寫)。每段寫清:源素材與入出點、版式、字幕、kw_class、特效預設、B-roll、音效、音樂段落、src_t(原話時間戳)。渲染前把分鏡表發給用戶確認。
第 5 步:剪輯
- 入出點用 10 ms 幀 RMS 能量檢測(不用 Whisper 字尾)。氣口剪乾淨:吸氣聲、廢話一點不留。
- 實際跑通的做法:先按能量裁,閾值 max(第 10 百分位 + 14 dB, −48 dBFS),連續 3 個 10 ms 視窗有聲才算開口,前留 0.10 s、後留 0.14 s,再人工收緊;檢查剪點兩側低於 −42 dBFS 的連續長度合計 ≤90 ms。
- 剪輯師習慣的目標:每個字起音前只留 1–2 幀(≤67 ms),尚未按此標準實測(待驗證)。驗證方法:demucs 分離人聲後,從剪點量到連續 3 個 10 ms 視窗高於 −42 dBFS 的起點;每個剪點 ≤67 ms、首字輔音不被切掉、剪段重跑 ASR 無斷字才算通過,通過後再改成預設。
- 可另出一版句間留 2–3 幀的對比版給剪輯師挑。
- 幀精確導出每段:
-ss放在-i前,-vf含fps=30,用-frames:v nf定長(nf = round((出點 − 入點) × 30)),libx264 -preset veryfast -crf 12,帶 BT.709 三個色彩標記;音頻按採樣點拼接,每段 8 ms 淡入 / 15 ms 淡出防爆音。 - 同機位跳切加 1.08 倍推拉;進出 B-roll 用甩鏡 + 橫向模糊。
- B-roll 只插在原話提到對應內容的地方,不為湊節奏硬插。
第 6 步:字幕特效(兩檔)
常規檔:每 1.5–2 秒一個,最長間隔 ≤3 秒,克制。
- 底部字幕:白字黑描邊,一行 ≤12 字,整句出現(是否給關鍵詞上色做成參數,由剪輯師定)。
- 強調放中層金色大字(關鍵詞 1.75×,數字 2×),逐字入場 115%→100%,6–8 幀;可加手繪底線/圈註、紙紋、柔和投影。
- 可選招式:數字滾動、實物貼圖配對應擬音、累加清單(字號 ≥ 底部字幕 1.2 倍,匯攏後再放大)、豎排對仗金句(出現時隱藏底部同句字幕)、開頭身份標籤(只在開頭用一次,標註「非原話」)。
爆點檔:每條 3–4 個,算進總密度,每一下疊滿:
- 大字占畫寬 75–85%(85% 是上限,安全區優先);4 幀內推近 1.15–1.25;2–3 幀震屏帶運動模糊;背景壓暗 6–30%、適當去飽和(參數,以手機上看人像層次清楚為準),人物層不調色;預混好的複合重擊音效(按 1 個計)。
- 力度分檔:最重的一下推近 1.25、震屏 3 幀;其餘推近 1.15、震屏 2 幀。
- 同一招全片只用一次:字在人後(摳像)/ 文字遮罩轉場 / 全屏數字滾動 + 紅章 / 豎排金句寫出 + 掃光。
- 字在人後:字放肩線以上,避開手和道具;頭要擋住字 25–30%(<15% 手機上看不出);描白邊前先把椅子等誤摳物從蒙版裡擦掉。
- 紅章:全片唯一的紅色,寬 30–40% 畫寬,3 幀內 150%→100% 砸下 + 2 幀震屏。
- 定格:只能放在一句說完後的自然靜音裡(人聲 < −45 dB),選嘴最接近閉合的幀,≤0.4 秒,全片最多一處,重擊音效壓在定格起點。這是「氣口一點不留」的唯一例外。
- 所有入場動畫提前 1 幀開始。
第 7 步:聲音
- 人聲:高通 80 Hz → 降噪 → 輕 EQ → 壓縮。
- 音樂:按章節換曲(剪輯師習慣),交叉淡化 300–600 ms;說話時側鏈閃避。只用確認授權或自行合成的音樂。
- 音效:全片約 0.5 個/秒,均勻分佈,每 4 秒視窗 1–3 個,任意兩個間隔 ≥0.25 秒;電平預設音效 RMS 比人聲有聲段低 14 dB(
db=-14);內容匹配的擬音優先於通用 pop。 - 響度:第一遍
loudnorm=I=-14:TP=-1.5:LRA=11測量;第二遍帶入測量值加linear=true,後面固定接aresample=48000,alimiter=limit=0.7:attack=1:release=30:level=false;最後 ebur128 複測,按 g = min(−14 − I, −2.9 − Peak) 補增益。目標 −14 LUFS,真峰值 ≤ −1 dBTP。
第 8 步:渲染與交付(二選一或組合)
- 路線 A:剪映草稿(剪輯師只用剪映時的預設)。Codex 出粗剪、字幕、音效與音樂時間點,用 pyJianYingDraft 新建草稿,剪輯師打開剪映做包裝和導出。限制和注意事項見
references/jianying_route.md,整條路線待在 Windows 實機驗證。 - 路線 B:疊加層(爆點必須用)。特效層用 HTML/Canvas,Playwright 驅動系統裝的 Chrome 逐幀截透明 PNG:視口 1080×1920、
device_scale_factor=1、啟動參數--font-render-hinting=none,截圖前等window.READY和document.fonts.ready,omit_background=True;所有動畫寫成時間 t 的純函數。PNG 序列以-framerate 30讀入,編 ProRes 4444(-alpha_bits 16),再用 ffmpeg overlay 合成。把疊加層作為影片軌放進剪映草稿:沒跑過,待驗證。ffmpeg drawtext 做不出逐字入場、字在人後。 - 保底交付:粗剪成片 + SRT + 分鏡表,包裝由剪輯師在剪映完成。
- 疊加前對底片做輕微調色
eq=contrast=1.04:saturation=1.07。 - 最終編碼:
libx264 -profile:v high -preset slow -crf 17 -maxrate 16M -bufsize 24M -g 60 -r 30 -pix_fmt yuv420p -color_primaries bt709 -color_trc bt709 -colorspace bt709,AAC 192k,-movflags +faststart。
第 9 步:質檢(全部通過才交付)
逐項按 references/qc_checklist.md。報告只寫自己抽幀、聽音頻核實過的東西,每條帶數字和單位;量不到的寫「沒量到」,不硬報。
封面
- 分工:策劃出文案和候選幀(寫進 spec 的
cover欄位),剪輯出版式和導出(1080×1920 與 3:4)。 - 主標題用原話濃縮,可調語序(如「擰螺絲一個半月」),不加原話裡沒有的事實;≤7 字、最多 2 行。副標籤放結果數字,貼紙 2–3 個。
- 標題和臉都放在中間 1080×1440(y 240–1680)裡,抖音主頁網格按 3:4 裁切。
- 每次至少給 3 個候選幀,附時間戳和理由,示意圖標「非成稿」。
- 逐 0.5 秒掃全段找側身或表情幀;視線方向決定版式(人看左上 → 人放右下、標題放左上);衣服或背景有字時禁止鏡像翻轉。
成功標準
- 時長 30–50 秒,第 1 秒是原話鉤子;上屏文字 100% 可追溯到原話。
- 常規特效最長間隔 ≤3 秒;爆點 3–4 個且力度分檔、招式不重複。
- 音效 ≈0.5 個/秒、無同時疊響;卡點 ≤2 幀;−14 LUFS ±1、真峰值 ≤−1 dBTP。
- 安全區越界 0;無意外黑幀/凍幀;字不壓臉、不壓品牌標識。
- 用戶確認过分鏡表;交付物齊全。
常見坑 → 對策
| 坑 | 對策 |
|---|---|
| HLG 素材發灰 | zscale + tonemap=hable 轉 SDR,gamma 約 1.12 |
| Whisper 字時間偏早、字尾拖進靜音 | 起點用 whisperX 對齊,出點用能量檢測 |
| VAD 漏句 | 再跑一遍關 VAD |
| 上屏字不是原話 / 上下文錯用 | 每條帶 src_t,QC 逐條對照轉寫 |
| 特效力度全一樣,顯得普通 | 分常規檔和爆點檔,爆點疊滿 |
| 字在人後看不出 | 量遮擋比例,頭擋住 25–30% |
| 椅子被摳進人像 | 字放肩線以上;描邊前擦掉 |
| 卡點量錯 | 從「看得清的第一幀」量;入場提前 1 幀 |
| 齒音被當成音效 | demucs 分離人聲後只在伴奏軌上測 |
| 音效扎堆 | 每 4 秒視窗 1–3 個,高潮複合音效按 1 個計 |
| 章或大字進抖音按鈕區 | 右邊界 ≤ x 930 |
| 邊說話邊定格、嘴型對不上 | 定格只放在靜音裡,≤0.4 秒 |
| 動畫滑入時掃過臉或出畫 | 改為原位淡出 + 目標位放大淡入 |
| 查看工具按路徑快取舊圖 | 每次檢查圖換新檔案名稱 |
| 中文路徑或空格導致命令失敗 | 用 Python subprocess 傳參數列表;檔案讀寫顯式 utf-8 |
| Whisper 幻覺出沒說過的句子 | 對照音頻人工校對全文後再對齊 |
| 想換其他渲染方案(如 Remotion) | 未驗證,不要自行替換,特效層只用 HTML/Canvas + Playwright |
| 新草稿不在剪映列表裡、字體不對 | 進出已有草稿或重啟;草稿開兩次 |