Narration & voices
Videos are silent by default, which is usually right for a demo. When you do want a voice, it is a compose-time change — never a re-recording.
Turn it on
output:
audio:
narration: tts
provider: say # or: kokoro
sfx: true # soft click at each click beatThen give steps a narration: line. It is the spoken script and is separate from caption:, the short card on screen — a caption has to fit a box, a sentence does not.
- click: 'role=button[name="Create user"]'
caption: "Create it."
narration: "One click, and the account is live."Pacing stretches automatically so every line finishes before its step ends, and the whole track is loudness-normalised to −16 LUFS.
The two voices
| Provider | Voice | Setup | Platforms |
|---|---|---|---|
say | macOS built-in (robotic but instant) | none | macOS only |
kokoro | natural neural — heart (default) or michael | npm i -g kokoro-js — about 400 MB once, plus a 90 MB model on first use | Mac · Linux · Windows |
Kokoro sounds markedly better and runs entirely offline. Whether that is worth the download is your call — playhead doctor tells you which providers this machine currently has.
Behind a TLS-intercepting proxy, the one-time model download needs your system CA: NODE_EXTRA_CA_CERTS=/etc/ssl/cert.pem playhead render …
Audition before you commit
playhead say "One click, and the account is live." --provider kokoroSpeaks the line immediately, through the same engine and cache a real render uses. No spec, no render, no waiting.
Adding voice to a video you already made
playhead compose out/capture --spec demo.yaml -o out-voicedAudio is composed, not captured. Add the audio block and narration lines to the spec, re-compose the existing bundle, and the app is never touched again.