竖屏实拍口播短视频剪辑(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 |
| 新草稿不在剪映列表里、字体不对 | 进出已有草稿或重启;草稿开两次 |