| name | voiceover-slide-video |
| description | Turn a Chinese voiceover draft or spoken script into a PPT-style HTML slide deck, page-paced TTS narration, burned-in subtitles, imagegen cover art, and an aligned MP4 video. Use when the user provides a口播稿/讲稿/脚本 and asks to make a PPT-style video, narrated slide video, HTML slides with voiceover, Bilibili-style subtitles/cover, or to combine frontend-slides output, TTS audio, and slide timing into a reusable video workflow. |
Voiceover Slide Video
把口播稿变成“PPT 风格 HTML + 配音 + 字幕 + 封面 + 对齐视频”。默认中文协作,默认偏向低密度 speaker-led 幻灯片。
输出目录(最高优先级)
- 默认输出根目录固定为
~/ai-artifacts/voiceover-slide-video/。如果 ~/ai-artifacts/ 或下级目录不存在,先自动创建。
- 每个任务使用独立子目录:
~/ai-artifacts/voiceover-slide-video/<口播稿文件名>/,其中 <口播稿文件名> 不含扩展名。若输入不是文件,使用简短、可辨识的主题名。
- 在开始生成前先确定并创建
OUTPUT_DIR。HTML、SSML、WAV、manifest、幻灯片帧、ASS 字幕、无字幕视频、烧录字幕视频、封面和其他中间产物都必须写入这个目录;中间帧统一放入 OUTPUT_DIR/frames/。
- 口播稿及其所在目录只作为输入来源。禁止默认在口播稿旁边创建视频、音频、封面、字幕、幻灯片或临时文件。 这条规则同样适用于输入文件位于笔记库、知识库或代码仓库时。
- 只有用户明确指定输出目录时,才覆盖上述默认目录。用户只提供口播稿路径不代表要求输出到稿件旁边。
- 所有脚本调用都传入
OUTPUT_DIR 下的绝对路径,不依赖脚本自身的默认输出路径。
推荐在执行开始时统一声明:
OUTPUT_DIR="$HOME/ai-artifacts/voiceover-slide-video/<口播稿文件名>"
mkdir -p "$OUTPUT_DIR/frames"
核心流程
-
确定输出目录
- 按“输出目录”规则创建
OUTPUT_DIR 和 OUTPUT_DIR/frames/。
- 后续每一步都只向
OUTPUT_DIR 写入生成物。
-
整理口播稿
- 保留用户原意,先识别自然分页。用户说明“多个换行代表 PPT 页面”时,把空行分隔视为页面边界。
- 如果原稿已有
<speak> 和 <break>,不要直接相信复刻音色会解析 SSML;把 <break> 当作页面/停顿提示处理。
- 页面内尽量不要切成很多短 TTS 段,否则每段都会带模型自己的起止静音,节奏会怪。
-
调用 frontend-slides
- 必须使用
frontend-slides skill 生成单文件 1920×1080 固定舞台 HTML。
- 如果用户没有指定风格,代为选择偏“黑橙、编辑感、强标题、低密度、演讲驱动”的风格,接近当前 ACW 示例。
- 生成后用截图检查至少首页、中间页、结尾页:无控制条、无溢出、无重叠、比例为 16:9。
-
抽取页面口播
- 根据最终 HTML 的 slide 数和页面内容,把口播整理成 page-level SSML。
- 理想情况:每张视觉幻灯片对应 1 个 TTS 文本段,页面之间用
<break time="..."/>。
- 结尾页常见有两段:CTA + 下一集提示;允许最后一张 slide 对应 2 个 TTS 文本段。
- 推荐页面间本地静音:
1.2s-1.6s。短内容页用 1.2s,章节/强调页用 1.5s-1.8s。
-
合成配音
- 使用
scripts/segmented_tts.py。它会逐段调用 TTS,只把正文发给接口,并在本地插入真实静音。
- API Key 必须通过环境变量传入,不写进仓库、脚本、日志或最终文档。
- 对声音复刻音色,默认使用
BYTE_TTS_RESOURCE_ID=seed-icl-2.0。
- 输出 WAV 最稳;如果需要 MP4,后续视频脚本会转成 AAC。
-
渲染幻灯片帧
- 使用
scripts/render_slides.js 截取最终 HTML 的每张 .slide 为 slide_01.png、slide_02.png。
- 如果 HTML 需要 Google Fonts 或外部资源,可传 Chrome 参数
--proxy-server=http://127.0.0.1:8118。
-
合成视频
- 使用
scripts/make_video.py,根据 TTS manifest 自动计算每张幻灯片的停留时长。
- 输出 MP4:H.264,1920×1080,30fps,AAC 音频。
- 合成后用 ffmpeg/ffprobe 或
ffmpeg -i 检查总时长、视频流、音频流,并抽帧检查片头/中段/结尾。
-
生成字幕
- 使用
scripts/make_ass_subtitles.py 从 SSML + manifest 生成 ASS 字幕。
- 默认字幕风格:白字、黑描边、阴影、底部居中,适合 B 站知识视频。
- 使用
scripts/burn_subtitles.py 把 ASS 烧进 MP4,生成 *-subtitled.mp4。
- 抽帧检查字幕:不要遮挡关键页面文字;必要时调
--font-size、--max-chars 或 ASS 的 MarginV。
-
生成封面
- 必须使用
imagegen skill。直接用自然语言描述完整封面,包括中文标题、副标题、系列编号、视觉风格和约束。
- 不要默认把封面拆成“AI 生成底图 + 本地加字”;
imagegen 可以直接生成带文字的完整封面。
- 封面建议 16:9,尺寸用
2048x1152 或 3840x2160。风格默认延续“黑橙编辑感、技术杂志封面、强标题、高对比”。
- 封面的关键文字必须集中在画面中心的 4:3 安全区内,避免做成横贯全宽的一整行;视频平台裁切成 4:3、1:1 或列表缩略图时,标题和集数仍要完整可读。
- 生成后必须视觉检查中文字是否准确清晰。如果有乱码、错字、多余文字,重新生成或再编辑。
脚本用法
口播稿转 page-level SSML
python3 path/to/scripts/make_page_ssml.py voiceover.txt "$OUTPUT_DIR/voiceover.ssml" --break-seconds 1.4
这只适合“空行即页面”的初稿。最终仍要对照 HTML slide 数人工微调。
分段配音并输出 manifest
BYTE_TTS_API_KEY="$BYTE_TTS_API_KEY" \
BYTE_TTS_RESOURCE_ID="seed-icl-2.0" \
BYTE_TTS_SPEAKER="S_Uv1IFLY72" \
BYTE_TTS_OUTPUT="$OUTPUT_DIR/voiceover.wav" \
BYTE_TTS_MANIFEST="$OUTPUT_DIR/manifest.json" \
python3 path/to/scripts/segmented_tts.py < "$OUTPUT_DIR/voiceover.ssml"
可选环境变量:
BYTE_TTS_SPEAKER:音色 ID。
BYTE_TTS_RESOURCE_ID:默认 seed-icl-2.0,复刻音色通常用这个。
BYTE_TTS_MODEL:默认 seed-tts-2.0-standard。
BYTE_TTS_OUTPUT:输出 .wav;只有确认本机 MP3 编码可用时才输出 .mp3。
BYTE_TTS_MANIFEST:输出每段语音和静音的时长 JSON。
截取 HTML 幻灯片
NODE_PATH="/path/to/node_modules" \
node path/to/scripts/render_slides.js "$OUTPUT_DIR/deck.html" "$OUTPUT_DIR/frames" --proxy-server=http://127.0.0.1:8118
如果 Playwright 不在默认 Node 解析路径里,使用 Codex workspace dependencies 提供的 Node.js 与 node_modules。
合成视频
python3 path/to/scripts/make_video.py \
--frames-dir "$OUTPUT_DIR/frames" \
--manifest "$OUTPUT_DIR/manifest.json" \
--audio "$OUTPUT_DIR/voiceover.wav" \
--output "$OUTPUT_DIR/final.mp4"
生成并烧录字幕
python3 path/to/scripts/make_ass_subtitles.py \
--ssml "$OUTPUT_DIR/voiceover.ssml" \
--manifest "$OUTPUT_DIR/manifest.json" \
--output "$OUTPUT_DIR/subtitles.ass" \
--font-size 58 \
--max-chars 21
python3 path/to/scripts/burn_subtitles.py \
--video "$OUTPUT_DIR/final.mp4" \
--ass "$OUTPUT_DIR/subtitles.ass" \
--output "$OUTPUT_DIR/final-subtitled.mp4"
该脚本依赖 imageio-ffmpeg。如果缺失,可以通过代理安装:
HTTP_PROXY=http://127.0.0.1:8118 HTTPS_PROXY=http://127.0.0.1:8118 \
python3 -m pip install --user imageio-ffmpeg
节奏规则
- 不要每个句子都切段;按页面切段。
- 页面内部依靠标点和模型自然节奏,不强插
<break>。
- 页面之间插真实静音,而不是依赖 TTS SSML。
- 复刻音色不可靠支持
<break>;如果需要停顿,必须本地插入静音。
- 视频页面时长以 TTS manifest 为准,不靠平均分配。
封面规则
- 触发封面需求时使用
imagegen skill。
- Prompt 要直接描述完整封面,例如:中文 B 站知识视频封面、主题、准确标题文字、准确副标题、系列编号、黑橙编辑感、技术杂志封面、无水印、无乱码、无多余文字。
- Prompt 必须明确“所有关键文字集中在画面中心 4:3 安全区内,不要横贯全宽,不要把标题贴近左右边缘;左右两侧可以放抽象视觉或背景元素,但不能放必须阅读的信息”。
- 优先让
imagegen 直接处理文字。只有用户要求或多次生成文字失败时,才考虑本地叠字修正。
- 生成后用视觉工具检查文字准确性和缩略图可读性;重点检查中心 4:3 裁切后标题、副标题和集数不被截断。
字幕规则
- 默认烧录字幕而不是外挂字幕,方便直接发布。
- 默认样式:白字、黑色粗描边、轻微阴影,底部居中。
- 生成 ASS 时把每个 TTS 段拆成若干字幕行,时间在该段语音时长内按字数近似分配。
- 字幕行尾不要单独保留句号、逗号、问号、冒号等尾标点;如果一条字幕只剩标点,应丢弃或并入前文后再清理。
- 不要把英文单词、缩写、带连字符/斜杠的英文数字 token 强行拆成前后两条字幕,例如
Prompt、Workspace、seed-tts-2.0 必须整体出现;宁可让该行略长一点。
- 字幕来源是 SSML 文本,不做语音识别;这样可以避免错字。
交付物
所有产物统一放在已确定的 OUTPUT_DIR 中。默认是 ~/ai-artifacts/voiceover-slide-video/<口播稿文件名>/,用户明确指定时才使用其他目录:
*.html:最终 PPT 风格 HTML。
*.ssml:最终 page-level 口播稿,用户要求时必须发给用户确认。
*.wav:真实静音已插入的配音。
*.mp4:最终对齐视频。
*.ass:字幕工程文件。
*-subtitled.mp4:已烧录字幕的视频。
*cover*.png:imagegen 生成的封面。
最终回复要包含文件路径、时长、分辨率、音频格式、字幕/封面状态,以及是否做过抽帧检查。