口播稿 / 口播音频 → 结构化讲解视频
深色底 + 逻辑图示 + 逐句精确字幕,Remotion 渲染,产出 MP4 + SRT。
视觉层只放提炼后的要点,逐字内容全部走字幕层,两层不混。
何时用
- 有一篇讲稿/逐字稿,想做成一版能直接发出去的讲解视频
- 有一段口播音频(录音、播客、访谈),想要带字幕的成片
- 要求「体现内容的结构化层次逻辑」「字幕和语音严格对应」
不适用的场景:白板手绘动画(另一个技能)、纯 PPT 导出、不要字幕的素材混剪。
两条输入路径
| 输入 | 路径 | 字幕来源 | 是否需要人工确认 |
|---|---|---|---|
| 文字稿(用户自己写的) | 变体 A:edge-tts 合成配音 | SentenceBoundary 事件,逐句精确 |
❌ 不需要,文字稿本身就是用户的版本 |
| 音频文件(mp3/m4a/wav/视频音轨) | 变体 B:Whisper large-v3 识别 | ASR segments 二次切分 | ✅ 必须,见下一节 |
⛔ 强制确认门禁(音频输入)
只要输入是音频,就必须在「出逐字稿」和「生成视频」之间停一次,等用户确认。
这不是建议,是硬约束——脚本层已经卡住(build_scenes.py 没有 --confirmed 直接拒绝执行)。
为什么必须有这一步
ASR 必然带错:专有名词错字、数字错位、整段漏识、双人对谈的说话人归属混乱。
这些错会一路带进字幕和图示——成片出去以后,观众看到的是「你说错了」,不是「AI 听错了」。
所以:先把文字定下来,再谈画面。
流程
-
转写
bash python scripts/transcribe.py <音频> --out asr --title "<标题>" --prompt "<领域术语>"
产出asr/asr_script.md(带时间码的逐字稿,就是交给用户的那份)、asr/asr_timed.txt、asr/asr_raw.json。 -
自检 ASR 空洞(脚本会自动打印 >2.5s 的间隙)
先判断是真漏还是停顿,规则见references/troubleshooting.md。有真漏就补识别后再给用户。 -
把逐字稿交给用户,并明确列出疑点
不要只说「转写好了请确认」——用户没法在 3000 字里自己找错。要主动列四类:
- 术语疑点:哪些词拿不准(同音、生造词、行业缩写)
- 数字/专名:金额、年份、产品名、人名
- ASR 空洞:哪几秒没有文字、判断是真漏还是停顿
- 说话人归属:双人/多人时哪句分给了谁
拿不准的保留原识别结果并标注,不要臆改内容。 -
等用户明确回话
有效的确认只有两种:明确说「确认/没问题/可以了」,或给出具体修订。
用户沉默、只说「嗯」、或问别的问题,都不算确认。 -
按批注修订,重出逐字稿(如有修订)
修订只改文字,不改时间轴;除非用户要求调语速或重切。 -
确认之后才允许继续
bash python scripts/build_scenes.py --scenes scenes.json --confirmed ...
门禁期间可以做什么
✅ 起草拆场方案(哪几段合成一场、每场配哪种图示)给用户参考
✅ 复制工程模板、装依赖、准备音频切分
❌ 生成 scenes-data.json(脚本会拒)
❌ 渲染、抽帧、出封面、说「马上就好」
❌ 用「先跑一版看看效果,回头再改字」当理由绕过
> 如果用户在给音频的同时明确说「字不用看,直接做」,照做,但在交付说明里写清「字幕基于未校对的 ASR,术语可能有误」,并附上逐字稿文件路径。
三个阶段的活
阶段一 · 拆场
把文本切成 8-13 场(3 分钟片约 6-8 场,12 分钟片约 16 场),每场定义:
{ id, chapter /* 章节标签,如「二 · 存储范式」 */,
title /* 大标题,一句话,<=16 字 */,
points /* 2-4 条提炼要点,每场视觉区用 */,
start, end /* 秒,边界必须落在语音端点,绝不跨句 */,
diagram: { type, data } }
- 每场 30-60 秒最舒服。某场超过 90 秒就再切一刀,否则一个画面停留太久
- 场边界取某句的 start 或 end;宁可让某场短一点,也不要一句话跨场
chapter是全片的骨架,写完通读一遍:把 chapter 连起来应该是一条完整论证线
阶段二 · 图示设计(核心)
按内容逻辑选型,10 类的参数与容量上限见 references/diagram-recipes.md:
| 逻辑 | 类型 | 逻辑 | 类型 | |
|---|---|---|---|---|
| 左右对照 | compare |
平行要点 | enumeration |
|
| 整体拆解 | decompose |
递进阶段 | stage |
|
| 因果/转化链 | flow |
单点 vs 系统 | pointvsnet |
|
| 多源汇聚 | integration |
层级堆叠 | layers |
|
| 时间次序 | sequence |
金句 | quote |
写完后逐条数字数:flow 5 步节点只能放约 8 个汉字/行,超了会断词换行。
阶段三 · 渲染与校验
# 1) 构建数据(--confirmed 是门禁)
python scripts/build_scenes.py --scenes scenes.json --audio src.wav --confirmed
# 2) 单帧冒烟:覆盖每种图示,秒级
npx remotion still src/index.ts video out/chk_0100.png --frame=100
# 3) 全量渲染(后台跑,别干等)
NODE_OPTIONS=--max-old-space-size=8192 npx remotion render src/index.ts video out/成片.mp4 --crf=18 --pixel-format=yuv420p
# 4) 校验 + 抽帧
ffprobe -v error -show_entries format=duration,size -show_entries stream=codec_type,codec_name \
-of default=noprint_wrappers=1 out/成片.mp4
python scripts/merge_srt.py --data src/scenes-data.json --out out --title 片子名
快速开始
# 1. 复制模板到工程目录
cp -r assets/template-remotion my-video && cd my-video
# 2. 装依赖(或联接到已有 Remotion 工程,省几百 MB)
npm install
# 或 PowerShell: New-Item -ItemType Junction -Path .\node_modules -Target <旧工程>\node_modules
# 3. 先用自带 demo 跑通链路(生成静音音轨,验证排版)
python ../scripts/make_demo_audio.py
npx remotion still src/index.ts video out/chk.png --frame=90
# 4. 换成真实内容:写 scenes.json → build_scenes.py --confirmed
模板自带 3 场 demo(金句/流程/对比),改 src/scenes-data.json 或走 build_scenes.py 都会被覆盖。
目录结构
script-to-structured-video/
├── SKILL.md 本文件(说明书)
├── references/
│ ├── diagram-recipes.md 10 类图示参数、容量上限、选型表
│ ├── subtitle-rules.md 字幕切分/不折行/时间轴对齐
│ └── troubleshooting.md Whisper / edge-tts / Remotion / 抽帧 排坑
├── scripts/
│ ├── transcribe.py 音频 → 逐句带时间戳 + asr_script.md
│ ├── build_scenes.py ASR+场景定义 → scenes-data.json(带 --confirmed 门禁)
│ ├── merge_srt.py scenes-data → 整片 SRT + 纯文本逐字稿
│ └── make_demo_audio.py 给模板生成静音音轨,跑通链路用
└── assets/template-remotion/ 可运行工程(Remotion 4 + React 19)
└── src/{index,Root,VideoComposition,Scene,Cover}.tsx + diagrams.tsx + scenes-data.json
视觉规范
- 底色
#0a0e17,面板rgba(18,26,43,0.72),强调色#38bdf8(蓝)+#fbbf24(琥珀) - 头部:章节标签(蓝、30px、字距 4)→ 大标题 66px/800 → 150×5 渐变分隔线
- 图示区:
top:320 left:80 w:1760 h:540,坐标空间 1760×540 - 字幕:底部居中 44px/600 白字,半透明黑胶囊,切换 0.12s 淡入,单行不折行
- 顶部 6px 进度条按章节推进,右上角
当前场/总场数
质量检查(交付前必须过)
- [ ] 每场 30-60 秒,无非预期超长场
- [ ] 字幕单条 ≤30 汉字、无换行、估算宽度 <1600px
- [ ] 场景累加时长与
totalDurationInFrames/fps差 <0.05s - [ ] 每种图示类型都出过单帧并肉眼核过排版(不能只看脚本跑通)
- [ ] 成片抽 3-4 个时间点,字幕与语音逐字对得上
- [ ] ffprobe:H.264 + AAC、分辨率/帧率/时长符合预期
- [ ] 音频输入时:逐字稿确认环节有据可查(用户明确确认过)
已知坑
见 references/troubleshooting.md。最常撞的四个:
- edge-tts v7 只有
SentenceBoundary,且必须串行调用(并发触发NoAudioReceived) remotion.config.ts用Config.setJpegQuality(),setQuality已废弃会直接报错scenes-data.json必须在src/下,放根目录 bundler 解析不到- 逐场切音频用 WAV 不用 MP3(MP3 有编码器延迟,多段拼接累积漂移)