script.md holds the words that the voice says, split into numbered sections. This page lists
its heading rules, its stage directions, and how DeckTalk cleans the text before the voice
receives it.
script.md
Headings
A numbered heading starts a section. Any other heading ends it.
Note: the times in a budget are
M:SS. The budget’s length is the target column of the narrate
table. A ### heading inside a section does not end it. narrate removes the ### marks and the
voice speaks the heading text.
The script and decktalk.toml must agree on section numbers.
- The script needs at least one numbered heading.
- Every numbered heading needs a
[[section]]table with the samenumber. If one is missing,narratefails withscript sections [N] have no [[section]] in decktalk.toml. - A page section needs a
## N.heading. Without one,recordskips the section andassemblefails. - A clip section does not need a heading.
narratenever voices a clip section, so its body can describe what plays. - Text before the first numbered heading is never spoken. The scaffold keeps its notes there,
above a
---line.
Directions and placeholders
Text in square brackets is not spoken.
A direction splits the text at its place. A beat adds a dash to the text before it, and the voice
pauses at the dash. A timed pause adds a break tag instead.
[pause N] is the only direction that
sends a break tag. Writing for the ear explains when to use each.
narrate refuses a section that still has a placeholder. Pass --allow-placeholders to voice it
anyway. decktalk narrate --dry-run lists every placeholder.
How directions combine
Silence that DeckTalk adds
A page section in
decktalk.toml can add its own silence.
ffmpeg adds this silence to the audio. The speech provider does not receive it.
lead_seconds goes into
narration.mp3 before the section’s mp3, which stays as the voice returned it.
The tail is not part of the narration cache. If you raise min_tail_seconds, the next narrate pads each cached mp3
and sends no request.
narrate measures the tail before it pads. A silence that ends within 0.06 s or one mp3 frame of the end of the
file counts as the tail, because the mp3 encoder adds up to 50 ms of padding there. A cached mp3 that narrate
already padded is not padded again when its tail is within 0.06 s of min_tail_seconds. So a second run leaves
each cached mp3 and its duration unchanged.
Configuration lists every [narration] key.
Markdown stripping
narrate cleans the text of each section in this order.
narratereplaces a link[text](url)with its text.narrateturns each direction into a pause mark.narrateremoves the markers of inline code, bold, and emphasis.narrateremoves heading marks, list bullets, and list numbers at the start of a line.narratejoins the lines of a paragraph with single spaces. A blank line separates paragraphs.narratereplaces each pause mark with a dash or a break tag at the end of the text before it.
decktalk narrate --dry-run prints the exact text for each section.
Length
The narrate table and a silent build estimate each section’s length with these formulas.words is the number of spoken words. Timed pause seconds add up every [pause N] and every
written break tag. The defaults are 140 for words_per_minute and 150 for
silent_words_per_minute. direction_break_seconds, lead_break_seconds, and min_tail_seconds
are each 0.7 by default.
Note: an em dash with a space before it counts as a beat, even when you type it in the prose. A
voiced section lasts as long as the audio that the speech provider returns, plus the added silence.
Numbers and symbols
Write numbers and symbols the way the voice should say them. Cue phrases incues.json match
spoken words, so the script and the cue must use the same words.
The scaffold writes “decktalk dot app” in the script and shows decktalk.app on the slide. A cue on
“decktalk dot app” resolves. A cue on “decktalk.app” matches nothing, because matching removes the
dot and leaves one token.
Related
- Plan a script by ear: Writing for the ear
- Map sections to pages: decktalk.toml
- Tie a reveal to a phrase: cues.json