# 演示视频标准制作方法(视频 + 配音 + 字幕解说) 一套可复现的流程:用 Playwright 自动操作真实应用录屏,叠加与配音**逐句同步**的字幕解说,再用 DashScope qwen-tts 生成自然中文配音并合成进视频。 ## 成品 - `e2e/videos/wenwumap-e2e.mp4` — 无声演示(含屏幕字幕) - `e2e/videos/wenwumap-e2e-voiced.mp4` — **带配音成品**(视频 + 字幕 + 中文解说,三者同步) ## 核心原则:声画字三同步 解说往往比单步操作时间长。若把语音顺序排布去避免重叠,会越积越晚、滞后于画面。正确做法是 **"画面等解说"**: 1. 先把每句解说生成语音并测得**时长**; 2. 录制时,**每一步至少停留其解说时长**(动作在这段时间内完成,解说同时播完); 3. 字幕直接显示**解说词本身**(即"配音字幕"),与语音同时出现; 4. 配音按字幕出现的**真实时间点**放置,不做重排。 这样画面动作、屏幕字幕、配音三者天然对齐。 ## 文件结构 | 文件 | 职责 | |------|------| | `e2e/narration.mjs` | 解说词词库:`步骤标签 → 完整解说`,及文本归一化 `clean()`。**唯一的文案来源** | | `e2e/gen-voice.mjs` | 预生成语音:逐句调用 qwen-tts(失败回退 macOS `say`),输出 `e2e/voice/*.wav` 与 `clips.json`(文本→{file,dur}) | | `e2e/run.mjs` | Playwright 录屏:注入字幕条、按 `clips.json` 时长让每步停留、导出录像与 `e2e/videos/narration.json`(字幕时间轴) | | `e2e/add-voice.mjs` | 按 `narration.json` 时间点把 `clips.json` 语音用 ffmpeg `adelay`+`amix` 合成进视频;解说超长时冻结末帧补足 | ## 前置依赖 - Node ≥ 20、pnpm;应用已在本地运行(`pnpm dev:web` + `pnpm dev:api`) - Playwright + Chromium:`pnpm add -w -D playwright && pnpm exec playwright install chromium` - `ffmpeg` / `ffprobe`(系统安装,需含 libx264) - DashScope 配音:`.env` 中的 `AI_API_KEY`(qwen-tts);离线兜底用 macOS `say` ## 制作步骤 ```bash # 1) 预生成解说语音(得到每句时长,供录制对齐) node e2e/gen-voice.mjs # 2) 录屏:每步停留至解说播完,字幕=解说词,导出 narration.json node e2e/run.mjs # 3) webm → mp4(H.264,便于合成与分享) ffmpeg -y -i e2e/videos/wenwumap-e2e.webm \ -c:v libx264 -pix_fmt yuv420p -movflags +faststart \ e2e/videos/wenwumap-e2e.mp4 # 4) 合成配音 → wenwumap-e2e-voiced.mp4 node e2e/add-voice.mjs ``` ## 改解说词 / 加步骤 1. 在 `narration.mjs` 的 `NARRATION` 里增改 `步骤标签: "解说词"`; 2. 在 `run.mjs` 中用相同的 `标签` 调 `safe("标签", async () => { ...操作... })`,字幕与停留自动按解说词处理; 3. 重新跑 1→4 即可。 > 字幕展示与配音文本都来自同一份解说词,无需两处维护。 ## 可配置项 - 配音音色:`QWEN_TTS_VOICE=Cherry|Serena|Ethan|Chelsie node e2e/gen-voice.mjs` - 离线兜底音色:`TTS_VOICE=Tingting`(macOS 中文语音) - 录制目标地址:`BASE_URL=http://localhost:3000 node e2e/run.mjs` ## 健壮性设计 - **限流重试**:qwen-tts 每句最多重试 3 次并间隔限速,失败自动回退系统 TTS,保证流程不中断。 - **容错操作**:`run.mjs` 的 `safe()` 单步失败只记录、不中断整段录制。 - **时长自适应**:解说总时长超过视频时,`add-voice.mjs` 冻结末帧补足,保证解说完整不被截断。 - **沙箱兼容**:图片等外链由浏览器侧加载/回退;服务端只依赖可达的 DashScope。 ## 已知注意点 - qwen-tts 有突发频率限制,密集重复生成会触发回退(混入系统语音)。`gen-voice.mjs` 已加间隔;如需全部自然语音,单独重试个别句子即可。 - 录制时长依赖 AI 流式回答耗时,单次运行略有浮动,但同步逻辑不受影响。