返回 ppt-master
audio-narration.md
根目录 / docs / audio-narration.md
1 # Audio Narration & Video Export
2
3 [English](./audio-narration.md) | [Chinese](./zh/audio-narration.md)
4
5 ---
6
7 PPT Master can turn the speaker notes into per-slide narration via [`edge-tts`](https://github.com/rany2/edge-tts) (Microsoft Edge's online neural voices) by default, or via ElevenLabs, MiniMax, Qwen TTS, and CosyVoice when you need higher-quality cloud narration or a cloned voice. The edge path also writes a page-local SRT from the same TTS stream. It can then embed the audio back into the PPTX for PowerPoint's native video export.
8
9 ## What you get
10
11 - One audio file per slide under `<project_path>/audio/`, named to match the SVG (`01_cover.mp3`, `02_market_landscape.mp3`, …).
12 - With edge, one matching subtitle file per slide under `<project_path>/notes/subtitles/` (`01_cover.srt`, `02_market_landscape.srt`, …). Each file uses a page-local timeline with a `00:00:00,000` origin and edge's word-boundary timing.
13 - When canonical `animations.json` exists, an SVG-to-SRT timing plan derives `narration_animations.json` whose click-free object animations wait for the relevant subtitle cue. When neither animation sidecar exists, narrated export creates no sidecar and keeps the default `fade` page transition with no per-element builds. Both paths can produce a deck-wide `<project_path>/notes/subtitles/total.srt` aligned to the final PPTX timeline; after PowerPoint exports a video, the same command can calibrate page starts against its audio track for frame-accurate sidecar subtitles.
14 - Optional re-export: a new PPTX in `exports/` with each `m4a` / `mp3` / `wav` file embedded into the matching slide and slide auto-advance timings set to the audio length, so kiosk/auto-play and video export work without manual timing.
15 - Optional native video export on Windows: `powerpoint_video.py` delegates the final narrated PPTX to PowerPoint 2016+ and waits until its native MP4 encoder succeeds or fails.
16 - The original speaker notes are preserved.
17
18 ## How it works
19
20 1. **Speaker notes are written as pure spoken narration.** PPT Master's notes spec deliberately produces TTS-friendly prose — no bracketed stage markers, no `Key points:` / `Duration:` meta-lines — so what is read aloud is exactly what's on the page.
21 2. **AI picks the voice for you.** When you ask for narration, the AI checks the deck's primary language (`zh-CN` / `en-US` / `ja-JP` / `ko-KR` / …), pulls the selected provider's voice catalog, and recommends 3–6 candidates with a one-line tone description for each (e.g. "steady male voice for financial reporting"). It also recommends a speaking rate or provider defaults based on notes density.
22 3. **One question, one answer.** You are asked once — provider, voice, rate, "embed audio back into PPTX", and "continue to video" — all with a recommended default. Reply "ok" to accept everything, or just call out the part you want to change.
23 4. **Generation runs.** With edge, the script writes each page's MP3 and SRT from the same stream to `audio/` and `notes/subtitles/`; cloud providers currently write audio only. For Generate PPTX with canonical custom animation, the AI maps current SVG content groups to numbered SRT cues and derives click-free `narration_animations.json`; without animation sidecars, it skips that derivation and retains `fade` / no per-element builds. It then re-exports the deck with audio attached and merges the local SRT files using timing values read from that final PPTX. When automatic video export was selected and compatible Windows PowerPoint is available, it continues through PowerPoint's native encoder and waits for the MP4 before aligning the delivery SRT. Long-audio import and automatic long-audio splitting are not supported.
24
25 Subtitles remain external artifacts: PPT Master does not embed them into the PPTX or burn them into the MP4. Automatic video export delegates to installed Windows PowerPoint; it is not a separate renderer.
26
27 The shared stage is documented in [`workflows/stages/generate-audio.md`](../skills/ppt-master/workflows/stages/generate-audio.md).
28
29 ## Two embedding paths
30
31 | Command | Purpose |
32 |---|---|
33 | `--recorded-narration audio` | Prepare PowerPoint's recorded timings and narrations. Requires complete per-slide audio and writes page auto-advance timings. Use this for narrated/video export. The re-export is saved as `exports/<name>_<timestamp>_narrated.pptx`. |
34 | `--narration-audio-dir audio` | Lower-level audio embedding. Embeds matched files and allows partial coverage. Use this for testing or manual PowerPoint finishing. Exports get the same `_narrated` name suffix. |
35
36 ## Triggering it
37
38 Just say so in chat after the deck has been exported:
39
40 ```
41 You: Generate narration audio for this deck
42 You: Generate narration for this deck and re-export with audio embedded.
43 You: Add Japanese voice narration; pick a calm female voice.
44 ```
45
46 The Generate route also runs this stage when final Stage 2 resolves effective
47 Narration Audio to enabled. A later explicit request still wins over the
48 proactive default. The AI handles the rest.
49
50 ## Languages
51
52 Anything `edge-tts` supports — roughly 90 locales including all major Chinese variants (`zh-CN` / `zh-TW` / `zh-HK` Cantonese), English (US/UK/AU/IN), Japanese, Korean, French, German, Spanish, Portuguese, Russian, Arabic, etc. List voices for any locale yourself with:
53
54 ```bash
55 python3 skills/ppt-master/scripts/notes_to_audio.py --list-voices --locale ja-JP
56 ```
57
58 ## Manual usage (advanced)
59
60 If you want to skip the AI flow and call the script directly:
61
62 ```bash
63 # 1. Make sure speaker notes are split (post-processing Step 7.1):
64 python3 skills/ppt-master/scripts/total_md_split.py <project_path>
65
66 # 2A. Generate MP3/SRT pairs with edge-tts (default, no API key)
67 python3 skills/ppt-master/scripts/notes_to_audio.py <project_path> \
68 --voice zh-CN-YunjianNeural --rate +0%
69
70 # 2B. Or generate MP3s with ElevenLabs (requires ELEVENLABS_API_KEY)
71 export ELEVENLABS_API_KEY="your-elevenlabs-api-key"
72 python3 skills/ppt-master/scripts/notes_to_audio.py <project_path> \
73 --provider elevenlabs \
74 --voice-id <elevenlabs-voice-id> \
75 --elevenlabs-model eleven_multilingual_v2
76
77 # 2C. Or generate MP3s with MiniMax (supports system and cloned voice_id)
78 export MINIMAX_API_KEY="your-minimax-api-key"
79 # Defaults to the China endpoint. For overseas access, set MINIMAX_TTS_BASE_URL=https://api.minimax.io/v1/t2a_v2.
80 python3 skills/ppt-master/scripts/notes_to_audio.py <project_path> \
81 --provider minimax \
82 --voice-id <minimax-voice-id> \
83 --minimax-model speech-2.8-hd
84
85 # 2D. Or generate audio with Qwen TTS (system voice or cloned voice)
86 export DASHSCOPE_API_KEY="your-dashscope-api-key"
87 python3 skills/ppt-master/scripts/notes_to_audio.py <project_path> \
88 --provider qwen \
89 --voice-id <qwen-voice> \
90 --qwen-model qwen3-tts-flash \
91 --qwen-language-type Chinese
92
93 # 2E. Or generate MP3s with CosyVoice (system voice or cloned/designed voice_id)
94 export COSYVOICE_API_KEY="your-dashscope-api-key"
95 python3 skills/ppt-master/scripts/notes_to_audio.py <project_path> \
96 --provider cosyvoice \
97 --voice-id <cosyvoice-voice> \
98 --cosyvoice-model cosyvoice-v3-flash
99
100 # 3-4. Only when canonical animations.json exists, print the SRT-set
101 # fingerprint, then author
102 # <project_path>/narration_timing.json by comparing each current
103 # SVG content group with the numbered cues in that page's SRT. A missing
104 # cue means the group has no spoken counterpart and uses normal sequencing.
105 # When neither animation sidecar exists, skip directly to step 5.
106 python3 skills/ppt-master/scripts/narration_sync.py fingerprint <project_path>
107
108 # 4. Derive click-free narration_animations.json from canonical animations.json
109 python3 skills/ppt-master/scripts/narration_sync.py animations <project_path> \
110 --narration-padding 0.5 --force
111
112 # 5. Re-export PPTX with audio embedded
113 python3 skills/ppt-master/scripts/svg_to_pptx.py <project_path> \
114 -o <final_narrated_pptx> --recorded-narration audio \
115 --narration-padding 0.5
116
117 # 6. Merge page-local SRT using the final PowerPoint timings
118 python3 skills/ppt-master/scripts/narration_sync.py subtitles <project_path> \
119 --pptx <final_narrated_pptx> --force
120
121 # 7. Optional on Windows: export through PowerPoint and wait for completion
122 python3 skills/ppt-master/scripts/powerpoint_video.py --check
123 python3 skills/ppt-master/scripts/powerpoint_video.py \
124 <final_narrated_pptx> -o exports/<final_video>.mp4
125
126 # 8. Calibrate page starts against the exported audio track and write a
127 # same-stem sidecar SRT
128 python3 skills/ppt-master/scripts/narration_sync.py subtitles <project_path> \
129 --pptx <final_narrated_pptx> --video <powerpoint_exported_video> \
130 -o exports/<powerpoint_exported_video_stem>.srt --force
131 ```
132
133 Before sending any TTS request, `notes_to_audio.py` verifies that every
134 Generate SVG page or Native Enhance slide has a readable, non-empty per-slide
135 note. Missing or empty notes return exit code `2`; generate those notes first,
136 then rerun audio generation.
137
138 For edge, `--voice` is required. Use `--list-voices --locale <locale>` to see what's available.
139 Edge generates up to three slide-level audio/SRT pairs concurrently by default.
140 Use `--concurrency <N>` to tune it or `--concurrency 1` for serial
141 troubleshooting. Cloud providers remain serial.
142
143 The edge command creates `audio/<stem>.mp3` and `notes/subtitles/<stem>.srt` from the same streaming request. Sentence-ending punctuation closes a cue. A cue over 20 visible characters first splits at commas, semicolons, or colons, then at the nearest word boundary only if it is still too long. Use `--subtitle-max-chars` to change the limit. Adjacent timing overlap up to 100 ms is tolerated by moving the later cue start to the previous cue end; larger overlap fails. Each SRT uses a page-local timebase with a zero origin and preserves edge's `WordBoundary` timing, including any leading silence before the first cue. The cloud-provider commands currently create audio only.
144
145 When canonical custom animation exists, `narration_timing.json` remains deliberately separate from read-only `animations.json`. It records the ordered SRT-set SHA-256, narration padding, ordered SVG group IDs, and optional 1-based cue numbers. `narration_sync.py animations` rejects a stale fingerprint, validates the group IDs against the current SVGs, and writes the derived `narration_animations.json` with only supported PowerPoint fields. A group with `effects[]` still maps to one cue: its first active row is anchored to that cue, while later rows retain their relative delay. With no animation sidecars, skip that derivation. `narration_sync.py subtitles` reads the final PPTX's actual presentation order plus millisecond slide-advance and transition values, so `total.srt` follows the native PPTX timeline. A relative `--pptx` path is resolved under `<project_path>`.
146
147 PowerPoint's video encoder can quantize each slide/media segment to its output frame clock. Those small per-page differences may accumulate even when the PPTX timing values are correct. Passing the finished `.mp4` / `.wmv` / `.mov` with `--video` uses normalized audio correlation to locate each original page narration in the exported audio track. It changes only the page-level offsets: edge's cue text and page-local `WordBoundary` timing remain untouched. This is a post-export subtitle calibration step and does not rewrite the video.
148
149 Use the default text-flow mode for the final narrated SVG export. It keeps authored line breaks in one editable, no-wrap text frame; narration does not require per-line text frames.
150
151 ```json
152 {
153 "version": 1,
154 "srt_sha256": "<sha256 of the ordered page-local SRT set>",
155 "narration_padding": 0.5,
156 "slides": {
157 "01_title": {
158 "groups": [
159 { "id": "page-title", "cue": 1 },
160 { "id": "supporting-visual" }
161 ]
162 }
163 }
164 }
165 ```
166
167 For ElevenLabs, `--voice-id` is required. List voices from your ElevenLabs account with:
168
169 ```bash
170 export ELEVENLABS_API_KEY="your-elevenlabs-api-key"
171 python3 skills/ppt-master/scripts/notes_to_audio.py --provider elevenlabs --list-voices
172 ```
173
174 For MiniMax, Qwen, and CosyVoice, pass the provider-specific system voice or cloned voice ID/name with `--voice-id`. Voice cloning itself is performed in the provider's console/API first; `notes_to_audio.py` uses the resulting voice ID to generate per-slide narration.
175
176 Audio embedded into PPTX must use a PowerPoint-reliable format: `m4a` (AAC), `mp3`, or `wav`. Built-in generation defaults to `mp3`; transcode provider output such as `pcm`, `opus`, or `flac` before embedding.
177
178 ## Use a cloned voice
179
180 Four cloud providers — **ElevenLabs**, **MiniMax**, **Qwen**, **CosyVoice** — let you clone a voice from a short sample and then synthesize new speech in that voice. PPT Master narrates the entire deck in your cloned voice as long as you can hand it a `voice_id`. (`edge` does not support cloning.)
181
182 **The split of responsibilities**: voice cloning itself happens in the provider's console or API — you upload a sample (typically 10 s – a few minutes of clean audio) and the provider returns a `voice_id`. PPT Master is on the *consumption* side: it takes that `voice_id` and reads every slide's notes in that voice. PPT Master never uploads your sample anywhere.
183
184 | Provider | Where to clone | Sample length |
185 |---|---|---|
186 | ElevenLabs | [elevenlabs.io](https://elevenlabs.io) → Voices → Add Voice → Instant / Professional Voice Cloning | 1 min (Instant) / 30 min+ (Professional) |
187 | MiniMax | [platform.minimaxi.com](https://platform.minimaxi.com) → Voice Clone | ~10 s – 5 min |
188 | Qwen TTS | [DashScope console](https://dashscope.console.aliyun.com) → Speech Synthesis → Voice Replica | ~10 s – 5 min |
189 | CosyVoice | [DashScope console](https://dashscope.console.aliyun.com) → Speech Synthesis → Voice Replica | ~10 s – 5 min |
190
191 **How to use it after cloning** — in chat, just say so. The AI will skip the voice-recommendation step and use your `voice_id` directly:
192
193 ```
194 You: Generate narration with my cloned MiniMax voice; voice_id is xxxxxxx
195 You: Generate the narration with my cloned ElevenLabs voice id abc123
196 ```
197
198 Or call the script directly:
199
200 ```bash
201 python3 skills/ppt-master/scripts/notes_to_audio.py <project_path> \
202 --provider minimax --voice-id <your-cloned-voice-id> \
203 --minimax-model speech-2.8-hd
204 ```
205
206 Replace `--provider minimax` with `elevenlabs` / `qwen` / `cosyvoice` as needed; `--voice-id` accepts the cloned voice the same way it accepts a system voice.
207
208 **Notes**:
209
210 - **Authorization** — only clone voices you own or have explicit permission to use. Each provider's terms forbid impersonation.
211 - **Language coverage** — the cloned voice inherits the speaker's accent. For multilingual decks (e.g. Chinese with English terms), pick a provider whose model handles your sample's language mix; ElevenLabs `eleven_multilingual_v2` and CosyVoice tend to be the most forgiving.
212 - **Provider retention** — reuse the `voice_id` while that voice remains available in your provider account. Retention, deletion, and expiration policies are provider-specific.
213
214 ## Dependency
215
216 ```bash
217 python3 -m pip install edge-tts
218 ```
219
220 Already listed in `skills/ppt-master/requirements.txt`. `edge-tts` calls Microsoft's online TTS service — an internet connection is required at generation time. The MP3s themselves are local files; nothing about playback or PowerPoint export depends on the network afterwards.
221
222 Cloud TTS providers do not require extra Python packages; they use HTTPS directly. Configure the relevant API key in the current shell or in `.env` based on `.env.example`.
223
224 Automatic MP4 export adds no Python package. It requires Windows PowerPoint 2016+ and Windows PowerShell; macOS and systems without compatible PowerPoint keep the narrated PPTX and use manual export.
225
226 ## Tips
227
228 - **Pacing**: On the Generate PPTX route, speaker notes scale with the independent information groups in the final SVG; 2–5 sentences is a typical rhythm, not a cap. Start with `+0%`; for a dense, deliberately detailed script, try `-5%`.
229 - **Mid-deck regeneration**: change a single slide's `notes/<page>.md`, re-run `notes_to_audio.py` (it overwrites all MP3s, so re-run for the whole deck — the cost is small).
230 - **Mixed-language decks** (Chinese with English technical terms etc.): `edge-tts` neural voices handle the embedded foreign words reasonably well in most locales — pick the dominant language voice and try one slide first.
231
232 ## Export as video
233
234 Once the narrated PPTX is in `exports/`, Windows PowerPoint 2016+ can export it automatically through:
235
236 ```bash
237 python3 skills/ppt-master/scripts/powerpoint_video.py \
238 <final_narrated_pptx> -o <final_video.mp4>
239 ```
240
241 The command uses recorded timings and narrations, defaults to 1080p/30 fps, and returns only after PowerPoint reports success or failure. The embedded audio plays as each slide's narration, while the per-slide auto-advance timings drive the video's pacing. `--recorded-narration` rejects `on-click` object animation because it does not generate object-level click timings.
242
243 **Manual PowerPoint fallback (Windows / Mac, Office 2016+)**:
244
245 1. Open the narrated `.pptx` from `exports/`.
246 2. **File → Export → Create a Video**.
247 3. Pick a quality and "Use Recorded Timings and Narrations".
248 4. Save as `.mp4` (`.wmv` is also available on Windows).
249 5. Run the optional subtitle calibration command above and place its same-stem SRT beside the video.
250
251 PowerPoint for Mac can export MP4/MOV manually, but Microsoft documents that
252 animation effects do not play in its movie export. Use the Windows automation
253 path when animation fidelity matters.
254
255 **Keynote (Mac)**: open the deck → **File → Export To → Movie…** — Keynote also honors embedded audio and per-slide timings, output `.m4v` / `.mov`.
256
257 **Tips**:
258
259 - **No mic, no recording session needed** — the audio is generated, not recorded, so re-runs are deterministic.
260 - **Animation fidelity on Windows** — PowerPoint's Windows video export preserves PPT Master's native page transitions and click-free object animation. Mac movie export has the limitation noted above. See [Animations & Transitions](./animations.md).
261 - **Want to tweak just one slide's audio?** Edit `notes/<page>.md`, re-run `notes_to_audio.py` and the embedding step, then re-export the video — total turnaround is usually under a minute per slide.
262 - **File size**: a 20-page deck at Full HD typically lands at 30–80 MB depending on imagery. Drop to HD if you need a smaller file for sharing.
263
263 lines MARKDOWN