电影感成片流水线(cinematic-cut)
把"一段原始素材"变成"一条能发出去的片子",中间不靠手搓,靠一条确定性流水线。
引擎是 scripts/cine.py,Agent 只负责两件机器做不了的事:读画面做判断、写旁白定文案。
何时使用
- 用户提供一段原始视频,要求"剪成电影感 / 大片 / 有质感 / 帮我剪一下"
- 要求在一段口播或空镜上加旁白、配乐、封面、片尾字幕
- 需要把一批同类素材统一成同一种风格批量出片
- 目标平台是抖音/视频号(竖屏 9:16)或 B 站/公众号(横屏 16:9)
不适用:需要逐帧精修、多机位套底、复杂特效合成的专业影视后期。
铁律:这个顺序不能颠倒
顺序不是随便排的,每一步都在为下一步提供输入。颠倒会返工。
| 约束 | 原因 |
|---|---|
| 先分析,再剪辑 | 不看画面就定切点等于瞎猜。静音检测只给"哪里没声音",不给"哪里不好看" |
| 先定旁白,再定片头片尾长度 | 旁白语音的长度直接决定片头/片尾字卡要停多久。反过来做必然要重排 |
| 先出封面和字卡,再合成 | 合成是最贵的编码,全片只编码一次。字卡先生成好,合成时当素材用 |
| 字卡不参与调色链 | 字卡自带设计配色,套滤镜会发灰发脏 |
| 最后统一 loudnorm | 旁白、原声、配乐三路电平各不相同,必须在混完之后统一拉到 -14 LUFS |
九步流程
Step 0 · 确认三件事(不要跳过)
向用户问清,或按素材自行判断并在交付时说明:
- 成片用在哪 → 决定画幅(9:16 / 16:9)和时长上限
- 要不要旁白 → 旁白是"编者视角"的重写。原片有说话的,旁白走"开头引入 + 结尾升华",不要盖在原声上
- 风格取向 →
warm-film(暖调纪实,默认)/teal-orange(青橙商业片)/mono-noir(黑白硬朗)
Step 1 · 素材分析(probe)
python cine.py probe <源视频> --out <work>/analysis.json --frames <work>/frames
产出:时长、分辨率、帧率、编码、有无音轨、原始响度、静音段列表、6 张抽帧。
> 必须亲眼看这 6 张抽帧。要判断的是:口播还是空镜?机位稳不稳?主体在画面哪个位置?有没有废镜头?这些机器判断不了。
记下原始响度:手机原片常在 -30 LUFS 以下,用户会以为"没录上声音",这是后续必须救的重点。
Step 2 · 剪辑决策(edl)
python cine.py edl --analysis <work>/analysis.json --out <work>/edl.json
规则:
- head=auto:开头若有一段 >1s 的静音/底噪,直接从其后切入,避免废镜头
- 每处停顿保留 lead=0.16s 前导 + trail=0.20s 后导,其余删掉
- 相邻片段交替微放大 1.03 / 1.065,把跳切的位移藏进画幅呼吸里
输出 20~30 段左右的 EDL,主片通常比原片短 10~20%。
Step 3 · 旁白(文稿 + 配音)
旁白先写文稿,再合成。写作要求:
- 一句一个信息点,单句 ≤ 20 字(TTS 长句会失去语气)
- 开头 1~2 句做钩子,结尾 1 句做升华,中间不要念
- 说人话,不用"首先其次最后",不堆形容词
python cine.py tts --script <work>/narration.json --out <work>/vo
逐句合成并记录每句精确起止时间,这是后面字幕对齐的依据。
默认音色 zh-CN-YunjianNeural(纪录片男声,沉稳);女声可用 zh-CN-XiaoxiaoNeural,年轻男声 zh-CN-YunxiNeural。
Step 4 · 背景音乐(bgm)
python cine.py bgm --duration <总时长> --mood calm --out <work>/bgm.wav
- 用户提供音乐 →
job.bgm.source指过去,直接用 - 没有 → 程序化合成无版权氛围垫乐(
calm/warm/tense/epic四种情绪),避免版权风险 - 默认
gain_db=-9,混音时走侧链闪避:有人说话时自动压低 BGM,说完再抬起来
Step 5 · 封面(cover)
python cine.py cover --job job.json
从成片同一套调色的帧里取底图(不是原始帧,否则封面和成片不是一个色),叠加:
- 金色小标签(话题/地点)+ 细分割线
- 大标题 2 行(Sans Bold,带黑色描边保证任何背景都可读)
- 副标题一行(灰)
- 整体暗角 + 下部渐变压暗 + 上下细黑边
输出 *_cover.jpg,既是封面也可当视频首帧。
Step 6 · 片尾字幕(credits)
python cine.py credits --job job.json
黑底 + 金句 2 行(思源宋体 Heavy,书面感)+ 行动号召 + 底部技术署名(素材/剪辑/配乐)。
金句从原片里提炼,不要另写——观众要听到"他自己的话被放大"。
Step 7 · 合成(compose)
python cine.py compose --job job.json
一次编码完成全部拼装:
画面:[封面卡] + [主体 N 段拼接 → 调色 → 遮幅 → 首尾淡化] + [片尾卡] → concat → yuv420p
声音:[片头旁白] + [主体(降噪→EQ→压缩)] + [片尾旁白] → concat → +BGM(侧链闪避) → amix → loudnorm -14 LUFS
- 遮幅:横屏自动加 2.39:1 黑边(
letterbox=auto),竖屏不加 - 片头/片尾时长 =
max(设计值, 旁白时长 + 0.9s),保证话说完画面还在
Step 8 · 质检(qc)
python cine.py qc --file <成片>
必须核对:时长对得上预期、分辨率/帧率正确、响度落在 -17 ~ -12 LUFS;
再抽 3 帧(开场/中段/结尾)亲眼看:开场是不是封面、中段调色对不对、结尾是不是字卡。
Step 9 · 交付
见下方"输出形态"。交付时说明:砍掉了多少秒、旁白几句、用的哪种调色、成片规格。
一条命令跑完
python cine.py all --job job.json
依次执行 probe → edl → tts → cover → credits → compose → qc。
调试阶段建议分步跑,先确认封面和字卡好看,再做合成(合成最慢,3~5 分钟,必须放后台跑)。
job.json 配置
{
"input": "素材绝对路径.mp4",
"output_dir": "输出目录",
"name": "成片名",
"aspect": "auto",
"look": "warm-film",
"letterbox": "auto",
"cover": {
"enabled": true,
"tag": "烟台 · 夜生活",
"title": "烟台的夜生活",
"title_sub": "到底有没有?",
"kicker": "一个烟台人的较真",
"frame_at": 0.55
},
"narration": {
"enabled": true,
"voice": "zh-CN-YunjianNeural",
"rate": "-8%",
"intro_lines": ["片头旁白第一句", "第二句"],
"outro_lines": ["片尾旁白"]
},
"bgm": { "enabled": true, "source": null, "mood": "calm", "gain_db": -9 },
"credits": {
"enabled": true,
"quote": ["金句上半句", "金句下半句"],
"cta": "你们那儿呢?",
"footer": "评论区聊聊",
"duration": 3.0,
"credit_lines": ["素材 · 原创拍摄", "剪辑 · 电影感成片流水线"]
},
"cut": { "head": "auto", "silence_db": -32, "min_silence": 0.55, "lead": 0.16, "trail": 0.20 }
}
aspect:auto 跟随素材 / 9:16 / 16:9 / 1:1
look:见 references/look-presets.md
letterbox:auto 横屏自动加 2.39:1 黑边,竖屏不加
输出形态
<output_dir>/
├── <name>_cinematic.mp4 成片(H.264 / 1080 竖屏或 1920 横屏 / 30fps / AAC 192k / -14 LUFS / +faststart)
├── <name>_cover.jpg 电影感封面(与成片同款调色)
└── .build/ 中间产物(可删)
├── analysis.json 素材体检报告
├── edl.json 剪辑决策(每段起止时间)
├── build_report.json 本次成片的完整参数存档
├── vo/vo_manifest.json 旁白逐句时间轴
├── bgm.wav 配乐
├── credits.png 片尾卡
└── filter.txt 实际执行的 ffmpeg 滤镜图(排错用)
成片规格按平台对齐:竖屏 1080×1920、横屏 1920×1080、-14 LUFS(抖音/视频号/YouTube 通用)、+faststart 让网页端秒开。
排查
| 症状 | 原因 | 处理 |
|---|---|---|
| 找不到 ffmpeg | 环境未装 | 装 imageio-ffmpeg,或设 CINE_FFMPEG 指向 ffmpeg.exe |
| 旁白合成 403 / 超时 | edge-tts 连不上微软服务 | 重试一次;仍失败则 narration.enabled=false,仅出调色成片 |
| 中文显示成方块 | 缺字体 | 检查 C:/Windows/Fonts 是否有 HarmonyOS Sans / Noto Sans SC / msyhbd |
| 字卡发灰发脏 | 字卡进了调色链 | 字卡必须在 concat 之前独立生成,不进 grade |
| 成片比预期长 | 旁白比设计时长长 | 正常,片头/片尾会自动让位给旁白 |
| 响度偏低/偏高 | 三路电平没统一 | 确认 loudnorm 在 amix 之后,不是每路各加一个 |
| 合成报 filter 解析错 | 路径里有盘符冒号 | 必须用 cwd=work + 相对路径,不要用绝对路径拼滤镜 |
更细的调色公式与参数取舍见 references/look-presets.md。