Remotion 卡点短视频流水线은(는) 무엇을 하나요?
Goal:给定一个选题和一首 BGM,产出一条 88–90 秒 / 16:9 / 无配音 / 中英双语字幕 / 每个场景切在乐句重拍上 的成片, 外加封面三版、发布包、待核事实清单。整套东西都是代码,改字幕就是改字符串,重渲一次约 35 分钟。
何时使用
- "把这个主题拍成一条抖音知识视频 / 博弈局解说"
- "用某某 BGM 做一条卡点视频"
- "把小说里这一段做成视频"(虚构 IP,见
references/fact-check.md) - 需要成套交付:成片 + 封面 + 发布文案 + 事实核实
何时不使用
- 要配音旁白(本流程是无配音字幕叙事;要配音就得先出 TTS 轨再对齐)
- 要真人/AIGC 素材混剪(本流程是纯代码 SVG 画面)
- 只要图文不要视频
〇、风格 DNA(先读,全部是实测结论)
| 维度 | 规范 | 为什么 |
|---|---|---|
| 画幅 | 1920×1080 / 30fps(竖版另开 Composition) | 账号已锁定 16:9,数据上内容效率更高 |
| 时长 | 88–90 秒(≈42 小节) | 落在"60–90s 单集"测试档 |
| 声音 | 无配音,BGM + 合成音效 | 风格要求;也避免 TTS 对齐成本 |
| 字幕 | 中英双语两行,中文 ≤22 字、每句停留 ≥2.2 秒 | 本账号风格(抖音通用建议是单语,此条为账号选择) |
| 切入 | 第 1 秒 = 一句完整冲突句 + 一个具体物 | 2 秒跳出率是最大漏点 |
| 叙事 | 一个人 + 一个问题 + 一条因果链 | 忌"概念图鉴"和"群像混剪" |
| 结构 | 钩子→片名→规则→陷阱→反击→反噬→揭晓→升华→收尾 | 见 references/script-template.md |
| 节奏 | 每个场景从乐句重拍硬切;关键动作落在拍点 | 卡点来自音乐结构,不是手动对齐 |
| 画面 | 深色底 + 金属/木/金色质感 + 大字号 + 少量标签 | 手机缩放下可读 |
| 安全区 | 场景元素 y ≤ 850;字幕 y≈870–1000;左上抬头 y 50–95 | 实测最容易翻车的地方 |
| 结尾 | 必须给可截图的清单(收藏点)+ 一句提问 | 收藏率是最大短板 |
| 严谨 | 虚构 IP 必须标"图示为示意";事实分层标注 | 见 references/fact-check.md |
一、八步流程(逐步执行,不可跳步)
第 1 步:立项(选题 + 确认)
- 用户没给选题时,先给 3 个候选(每个写清:一句话内核 / 第 1 秒钩子 / 凭什么能画 / 收藏点 / 风险),让用户点单。
- 候选必须先验证存在性再提交:虚构 IP 要能查到章节名或条目;知识类要能查到出处。
- 用户点单后,把该选题的原始资料要到手(原文段落最好;只有二手整理时必须标注来源层级,见第 8 步)。
第 2 步:音轨与节拍(决定一切时间)
# ① 抽音轨(mp4/mp3 都行;没系统 ffmpeg 会自动用 imageio-ffmpeg 的二进制)
python scripts/extract_audio.py 输入.mp4 work/ # → work/audio.f32 + work/music.mp3
# ② 节拍 / 重拍 / 段落 / 调性
python scripts/analyze_beats.py work/audio.f32 src/beats.json
# ③ 扫能量,选窗口(关键一步)
python scripts/scan_energy.py src/beats.json work/audio.f32 --seconds 89
- 输出会给出:START_BAR / END_BAR、逐小节能量图、静音坎落在窗口百分之几。
- 把反转放在静音坎之后的第一记重拍上——这是全片最值钱的一秒。
- 窗口不要吃掉结尾的衰减段(那会留下死尾)。
- 若某首歌已被系列用过,优先挑没被用过的后半段,避免观感重复。
第 3 步:写剧本(src/script.ts)
- 每个场景声明
bars(占几小节),所有场景 bars 之和必须等于 END_BAR − START_BAR(否则placeScenes会按比例缩放并告警)。 - 字幕写在
subs:{zh, en, at},at是场景内第几拍(可写 4.5 这种半拍)。一句占 4–5 拍最舒服。 - 音效写在
cues:{id, beat, sfx, vol, impact};impact:'big'= 白闪 + 震屏 + 色散 + 音乐侧链让位 40 帧。 - 节奏预算:
句子数 × 2.5–3 秒 ≈ 总时长。89 秒大约 30 句。
第 4 步:画面零件与场景(src/*/kit.tsx + src/*/scenes.tsx)
- 先把零件写全再写场景:一个题材的零件通常 6–10 个(本例:铁盒/锁/钥匙/粉碎机/微波炉/人物剪影/雕像/灯/彩券/柜台/道币)。
- 零件全部纯 SVG,坐标写死在 1920×1080 上,靠
translate/scale复用。 - 场景组件只负责按拍点排零件:
const bf = (n) => beatFrame(scene, n),进场一律用pp(f, bf(n), 8)这种缓动进度。 - 检查清单见
references/visual-kit.md。
第 5 步:工程搭建
一个工程放多支片:src/<episode>/{script.ts,timeline.ts,fx.tsx,kit.tsx,scenes.tsx,Main.tsx},
在 src/Root.tsx 注册第二个 <Composition>,各自用自己的 beats.json 和 music.mp3。
- 第二支必须带自己的节拍外壳(
fx.tsx里的 Shell/ImpactFlash 必须用本片的 cueFrame,否则冲击点会错位)。 - 音频用
<Audio startFrom={OFF}>,内容整体<Sequence from={-OFF}>,这样场景内部一律用"音乐帧"计时。 - 详见
references/pipeline.md。
第 6 步:静帧自检(不过不渲染)
node <node> node_modules/@remotion/cli/remotion-cli.js still <Comp> out/s1.png --frame=<场景中点>
逐场景渲一张,肉眼过四件事:
- 字幕有没有压到场景元素(最常见)
- 元素重叠(标签压标签、标签压图形)
- 安全区(元素 y ≤ 850)
- 手机缩放下文字是否可读(中文 ≥24px、主标题 ≥120px)
第 7 步:出片与成片自检
node <node> node_modules/@remotion/cli/remotion-cli.js render <Comp> out/<name>.mp4 --codec=h264 --crf=18 --concurrency=6
python scripts/check_mp4.py out/<name>.mp4 # 时长 / 轨道数 / 分辨率 / 音频参数
check_mp4.py 不需要 ffprobe:直接解析 mp4 box,确认 vide + soun 双轨、时长对得上、1920×1080、AAC 48kHz。
第 8 步:交付
python scripts/make_covers.py --src out/<某静帧>.png --crop x0,y0,x1,y1 \
--title 主标题 --kicker 副标 --sub 一句话 --out-prefix out/封面_XXX
交付四件套:
- 成片 mp4(拷到工作区根目录,文件名带主题)
- 封面三版(16:9 / 3:4 / 9:16)——绝不用自动截帧
- 发布包(正文 + 置顶评论 + 封面方案 + 24 小时判定表),模板见
references/cover-and-publish.md - 待核事实清单(虚构 IP 必备)+ 剧本分镜(时间码表)
二、铁律(全部是实测踩出来的)
- 第 1 帧不是片头是钩子:一张完整冲突句 + 一个具体物("人质被锁在微波炉里,倒计时正在走")。
- 字幕安全区:场景元素一律压在 y ≤ 850,字幕在 870–1000。静帧自检时优先看这条。
- 一句字幕 ≤22 字、停留 ≥2.2 秒;中文主句 + 英文对照两行。
- 结尾必须能截图:一个三步/三信号清单 + "建议先存下来";只给感慨的结尾拿不到收藏。
- 静音坎 = 反转点:
scan_energy.py会告诉你坎在第几小节,把最强的反转放它后面。 - 大冲击要点:
impact:'big'会触发白闪 + 震屏 + 色散 + 音乐让位;全片 5–8 次足够,多了就麻木。 - 不要匀速滑动:所有进场用缓动(
Easing.out(cubic)),标签出场带一点位移+缩放。 - 字体:不要用"按旧文案裁剪的子集字体"(新文案会缺字)——直接写系统字体栈
'Noto Sans SC','Microsoft YaHei'。 - public/ 会被整体拷贝:只保留用到的音效(本例 148 → 16 个,每次渲染少拷 60MB)。
- Remotion 的 ETA 早期虚高:别被"剩余 3 小时"吓到;实测稳定在 ~1.35 帧/秒,2700 帧约 35 分钟。
- 虚构 IP 三层标注:原著原文 / 读者整理 / 我的推测——片子里只写前两层的共识部分,其余进待核清单。
- 不要在片子里写死数字("四个生肖"→"好几个生肖")、不要写死章节号("第 359 章"→"约第 359 章前后")。
三、目录约定
<project>/
├── public/music.mp3 # 本片 BGM
├── public/music.f32(+.json) # 节拍分析用(可删)
├── public/sfx/*.wav # 按调性合成的音效
├── src/beats.json # analyze_beats 输出
├── src/script.ts # 文案总表(改内容只动这里)
├── src/timeline.ts # 场景→重拍映射 + OFF/TOTAL
├── src/Root.tsx # 注册 Composition
├── src/fx.tsx # 震屏/白闪/色散/双语字幕
├── src/<episode>/** # 第二支及以后:独立 script/timeline/fx/kit/scenes/Main
├── tools/ # 本 skill 的 scripts/
└── out/ # 静帧 + 成片 + 封面
四、参考文件
references/pipeline.md—— 环境搭建与命令全集(含这台机器的全部坑:没有 ffmpeg / scipy / npm)references/script-template.md—— 剧本结构模板 + 拍点换算表 + 本次两条片的真实时间码references/visual-kit.md—— 画面零件规范、安全区、配色、常见重叠陷阱references/sfx-and-mix.md—— 音效合成(按调性)、侧链让位、响度references/fact-check.md—— 虚构 IP 核实方法与「读者复述」标注规范(含可用的 B 站接口)references/cover-and-publish.md—— 封面三版规范 + 发布包模板 + 24 小时判定examples/十日终焉-两集.md—— 两个真实案例的结构、数据与决策记录
五、能力边界(对用户诚实)
- 本流程不产生配音;要旁白必须另配 TTS 并重新对齐字幕。
- 网络受限环境下(很多域名被 DNS 拦)虚构 IP 的规则细节可能只有二手来源 —— 此时必须走第 8 步的待核清单,不硬写。
- 渲染是算力活:4 核笔记本上一条 89 秒 1080p 约 35 分钟;不要承诺"几分钟出片"。
- 版权:BGM 从抖音视频里提取只适合自用参考;发布时请挂站内曲库/原声卡片。