decktalk command runs each build stage on its own, or all seven stages with decktalk build.
This page lists every command with its options, the files it reads and writes, its output, and its
exit codes.
Global options
These options work with every command.-vand-qgo before or after the command name.-pgoes before the command name, or after it on every command exceptinit,setup, anddoctor.- Every other option goes after the command name.
- A repeatable option takes one value each time. Write
--only 3 --only 5, not--only 3,5. - Logs go to stderr. Tables and JSON go to stdout.
- A command reads each key from the environment first, then from
.envin the project. - DeckTalk never prints a key.
Environment variables
Note: a key value that starts with
< counts as unset, so the placeholders in .env.example never
reach the provider. Configuration lists every tuning field.
Setup commands
decktalk setup
Downloads Chromium, ffmpeg, and KaTeX, one time per machine.
static-ffmpeg, and KaTeX to the DeckTalk cache.
- On Linux,
setupalso installs Chromium’s system libraries. What setup downloads lists the paths and the permissions it needs. - A download that already exists is not downloaded again.
- If the KaTeX download fails,
setupwarns and still exits 0. Pages then load KaTeX from a CDN.
decktalk doctor
Reports each tool that DeckTalk needs and where it found the tool.
Reads Playwright’s Chromium (it launches it), the ffmpeg locations, the per-machine config path,
and the KaTeX cache. Writes nothing.
doctor never downloads anything.
Note: a
MISSING row is a certain finding. A warning row is an uncertain finding, so it exits 1
only with --strict. When ffmpeg is not found, doctor prints one ffmpeg MISSING row and no
ffprobe row. In the JSON, a warning row has "ok": false and "required": false.
decktalk init
Writes the scaffold into a new directory.
Reads the packaged template and the KaTeX cache. Writes
decktalk.toml, script.md,
cues.json, .gitignore, .env.example, media/markers.json, and deck/. deck/ holds
index.html, lesson.html, the fonts, decktalk-runtime.js, and katex/ when KaTeX is cached.
If KaTeX is not cached, init warns and writes CDN tags into deck/index.html. The warning starts
with KaTeX is not cached, so the pages in deck/ load it from a CDN.
decktalk runtime
Copies the packaged page runtime into the project.
decktalk-runtime.js under the project, or
deck/decktalk-runtime.js when the project has none. Run it after you upgrade DeckTalk.
decktalk preflight
Checks a voiced build before it spends credits or records anything. It plans the takes, resolves every cue, and
estimates each reveal from frozen frames of the pages.
Reads
script.md, cues.json, decktalk.toml, the pages, and build/audio. Needs no key.
Writes build/preflight/NN/step-<id>-cue-<cue>.png and step-<id>-before-<cue>.png, after it empties
build/preflight. --no-frames writes nothing. preflight never writes beats.json or build/audio.
preflight runs three checks.
- Takes. It prints the take plan of
narrate --dry-run. The plan says which sections a voiced run would voice, keep cached, or move, with the characters each section sends. - Cues. It resolves every cue phrase as
beatsdoes, with the same notes. A cached or moved take resolves on its own words. A section that would be voiced resolves on estimated words atsilent_words_per_minute, so its cue times are placeholders. - Frames. For each cue, it freezes the page just before the cue and at the cue, and compares the two frames
as
verifycompares frames. For each page section withcarries_previous = trueafter a page section, it compares the previous section’s last frozen frame with this section’s first one.
chg % estimates what verify
measures once the reveal has settled, with a control of 0. The verdicts use the [verify] limits.
- The frames follow cue mode. The first cued step mounts at t=0, and every other step mounts at its earliest cue. The frame before a cue that mounts its step shows the step that was on screen.
- A freeze fires a step’s cues in autoplay order. When the cue times run in another order, the row notes that the frames may differ from the recording.
- The estimate sees no motion, no camera push, and no close neighbor cue.
verifymeasures those on the final mp4. - The frames need
catalog[].cuesand&before=from the runtime. A page with an older copy ofdecktalk-runtime.jsskips every cue asRUNTIME_OUTDATED.
These are parts of a run on the scaffold after
decktalk narrate --silent, with carries_previous = true on
section 2.
decktalk build
Runs all seven stages in order and prints each stage’s table.
Note: with
--only, narrate still runs on every section and assemble still uses every section.
Recordings of other sections stay as they are. A silent build stops when the project has voiced
takes, as A silent build and a voiced build
explains.
Reads and writes what each stage reads and writes, below.
build does not measure cues. It exits 0 on TRUNCATED, STALLED, NO COVER, BLACK?, and
KATEX?. To gate a script on the whole video, run check and verify after the build, as
Build in CI and offline shows.
These are the last lines of a silent build of the scaffold.
Stages
build runs these seven commands in this order. Each one also runs on its own.
decktalk narrate
Voices the script and writes each section’s audio and word times.
Reads
script.md, decktalk.toml, and .env. --silent and --dry-run need no key.
Writes build/audio/NN-slug.mp3, NN-slug.words.json, manifest.json, narration.mp3, and
timeline.json. --dry-run writes nothing.
narratenever voices a clip section.narratecaches each section by provider, voice id, model, output format, voice settings, and text.--onlyrebuildsnarration.mp3andtimeline.jsonfrom every voiced section, not only the named ones.--onlywith no spoken section fails, for exampleno spoken sections match [5]; spoken sections are [1, 2, 3, 4, 6, 8, 9].- A placeholder fails a voiced run with
unfilled placeholders [...] in the script.
est), time budget (target), and audio
length (actual). The second table is the timeline in narration.mp3.
script.md gives the estimate formulas.
The take plan
--dry-run checks the narration cache the way a voiced run does, and ends with the take plan. Each
section gets one take status.
A
synthesize row gives its reason: no take yet, only a silent take exists,
the text, voice, model, or voice settings changed, the file name changed from <file>,
the mp3 or the words file is missing, or forced. sent counts the characters the voice receives,
with dashes and break tags. spoken counts the spoken words’ characters.
Without a key, a project with no voiced take plans every section as synthesize. A project with voiced
takes plans them as unknown, because the cache key needs the voice id.
--json, the payload under narrate has these keys.
decktalk beats
Resolves each cue phrase to a cue time and writes beats.json.
Reads
manifest.json, the words files, cues.json, and each page. Writes beats.json and
beats.anchors.json, even when it exits 1.
beats looks for each cue id in its page as a quoted literal, in single quotes, double quotes, or
backticks. A data-cue value, a key of a step’s cues object, and a handler key all count.
Cues gives the phrase matching rules.
The table columns are sec, speech (the speech end in seconds), need (min_seconds), and
cues (each id@seconds). A note line starts with !.
Note: a clip section with cues prints
-- and (no narration (clip section, or not rendered)).
decktalk record
Records each page section in headless Chromium to a webm.
Reads
timeline.json (not with --seconds), beats.json (not with --no-beats), and the pages.
Writes build/rec/NN-scene.webm and its sidecar NN-scene.json.
recordprints no table. It logs one[rec ]line per section and every page warning as[page].recordskips a page section that has no span and logsno narration span yet; skipped.- If the page stalls after narration t=0 for longer than
[align] stall_ms(150),recordrecords the section again. recordtries again up to[record] retries(2) times.
decktalk measure
Finds narration t=0 in each recording and writes it to the sidecar.
Reads each webm and its sidecar. Writes
lead_in_seconds and lead_method into the sidecar.
measure scans the first [align] scan_seconds (4.0) of the recording and finds the last magenta
frame. Narration t=0 is one frame after it. The table columns are trim (t=0 in the webm),
wall (the recorder’s own clock estimate), and method.
decktalk check
Checks each recording’s length, brightness, and recorder warnings.
Reads each webm and its sidecar. Writes nothing.
Each row describes one recording.
Note: one row can show several verdicts, separated by spaces. The JSON lists them in
verdicts and
puts the stall length in stall_ms.
decktalk assemble
Cuts, mixes, and writes the final video with its captions and chapters.
Reads
timeline.json, manifest.json, beats.json, the recordings and sidecars, the clips, the
markers file, the underscore, the ambience bed, and the sound effects. Writes
build/out/NN-section.mp4, <name>.mp4, a copy named <name>-YYYYMMDD-HHMM.mp4, <name>.srt,
<name>.vtt, <name>.chapters.txt, and build/out/slates/.
- Without
--strict, a missing clip plays a titled slate forslate_seconds, and a missing recording plays black. assembletrims each recording at thelead_in_secondsthatmeasurewrote. Ifmeasurehas not read the recording since it was recorded,assembleprintsSTALE MEASUREMENT. The section may then play early or late. Without--strict,assemblewarns and continues. With--strict, it stops.- A missing underscore, ambience bed, markers file, or sound effect logs a warning and plays without it.
- A silent build skips the loudness pass, so
--stricthas no loudness to fail on. assembleprints the final path and length on stdout.
decktalk verify
Checks section starts, cuts, cut continuity, and cues in the final video.
Reads
build/out/NN-section.mp4, build/out/<name>.mp4, narration.mp3, timeline.json,
beats.json, beats.anchors.json, manifest.json, and cues.json. Writes nothing.
- With no cue arguments,
verifychecks every cue inbeats.json, by section and then by cue time. - With no cue arguments,
verifyskips a cue thatcues.jsonmarks"verify": false. - Named cues run in the order given, positional cues first. A named cue runs even when it is opted out.
--onlyalso filters named cues. A named cue outside--onlygets no row.- The
verifystage insidebuildchecks starts, cuts, and continuity, and no cue.
verify prints up to four tables: section starts, cuts, cut continuity, and cues. The continuity table appears
only when a section sets carries_previous. A clip section has a start row but
no cut row. cut at is where the section’s narration ends in the final video. The cue table gains an
a/v column only when at least one measured cue has an a/v value. The JSON silent key says if
the build was silent. verify defines each column.
Note:
OFF CUE prints no distance. Compare the offset column with 80 ms (max_offset_frames) and the
a/v column with 120 ms (max_av_frames). A measured cue with no click shows - in the a/v column
and has the JSON reason NO_CLICK. NO_CLICK is not a failure.
verify explains each reason.
decktalk soundscape
Generates the underscore, the ambience bed, and sound effects from prompts.
Reads
[soundscape], the [mix] paths, and .env. Writes each audio file with a
.manifest.json beside it. Music longer than [elevenlabs] max_music_chunk_seconds also writes
-partN.mp3 files.
soundscape spends credits, as What spends credits explains.
Each item prints == <name> -> <path> [<status>], then its endpoint and request. A project with no
prompts prints nothing to generate.
Inspection commands
decktalk shots
Writes review screenshots of steps, or frames from a playing section.
Note: the
<page>/ folder, such as index/ or lesson/, appears only when shots covers two or
more pages. --page with one file writes no folder. Section frames never use one.
--cueneeds exactly one--stepand does not combine with--section.- A frozen step fires its cues in autoplay order, up to the named cue. Runtime describes freeze mode.
- An
--atvalue past 30 s fails witherror: TimeoutError: Page.wait_for_function: Timeout 30000ms exceeded.
--section, also beats.json and timeline.json. Writes the PNGs.
decktalk status
Prints what the project has and what is built.
Reads the project files and the build directory. It probes only the final video. Writes
nothing.
Note: the timeline shows narration times. A clip section adds its length to the final video only, so
final is longer than narration total. Time bases explains the
clocks.
--json payload. The values are types, not a sample.
status exits 0 unless the project does not load.
Clip commands
decktalk words
Prints each spoken section’s words, with times in seconds after the section starts.
Reads
timeline.json, and manifest.json for the script’s spelling. Writes nothing.
- Each time counts from the section’s own start, as
?words=andbeats.jsondo. Time bases explains the clocks. - A section’s
lead_secondscounts, so its first word starts after the lead. - Each row gives the word’s start, its end, and the word with the script’s punctuation and case.
- After a silent build, the times are estimates, and each section header says
estimated. - A page that prints real word times can take them from this output.
--json payload. The values are types, not a sample.
word is the word as the voice returned it, with punctuation removed. text is the same word with the script’s
punctuation and case.
decktalk clip
Cuts a span of a built page section into a video file and a words file, for a clip section.
Reads
build/out/NN-section.mp4, the section’s mp3, manifest.json, and timeline.json. Writes the clip
and its words file.
--fromand--touse the clock thatdecktalk wordsprints. Run it first to pick the span.- The picture is the section video’s frames from
--fromto--to, each time rounded to the nearest frame. - The sound is the section’s mp3 over the same span. A span inside the section’s
lead_secondsis silent. - The sound fades in and out over 10 ms, so a cut inside a word does not click.
- The clip is H.264 video and AAC audio, at the frame rate and sample rate in
[video]. - The words file lists each word wholly inside the span, in seconds after the clip starts, with the script’s
punctuation and case. A word that the span cuts in two is left out, and
clipprints a warning. - After a silent build, the sound is the click track and the words are estimates, and
clipprints a warning.
--from 2.87 rounds to frame 72, at 2.88 s. --hold 0.5 rounds to 12 frames, which is 0.48 s.
Cut a clip from a build puts the clip in a clip section.
Output and exit flags
status, beats, preflight, check, verify, and doctor take these three options.
An uncertain finding is a verdict that ends in
?. In beats and preflight, speech shorter than min_seconds is
also uncertain. On assemble and build, --strict has a different meaning. It fails on a missing
recording, or a missing clip in a section without optional = true.
This shape shows the JSON envelope. The values are types, not a sample.
Note: each
beats section is {key, speech_end, min_seconds, skipped, cues, notes}. Each note is
{cue, verdict, detail}, where verdict is UNRESOLVED, UNKNOWN, or null. Each verify cue row
is {section, cue, cue_seconds, final_seconds, changed_percent, control_percent, offset_ms, av_ms, verdict, reason}. verify defines them. Each preflight cue row is {section, cue, cue_seconds, step, changed_percent, verdict, reason, detail, note, before, after}, and each carry row is
{key, changed_percent, verdict, reason, detail, last, first}. The preflight takes rows are the take plan rows
without text, and beats is the beats payload without beats_file, plus estimated_sections.
- Every
keyis a two-digit section string such as"03". Averifycue row’ssectionis an integer. - A value that does not exist is
null. Every verdict is the name that the table prints. - Paths are relative to the project root, with forward slashes.
project.root,doctordetails, and paths outside the project stay absolute. - Only the JSON object goes to stdout, so
decktalk verify --json > verify.jsoncaptures nothing else.
Exit codes
--no-failmakesdoctor,beats,preflight,check,verify, andstatusexit 0 on findings.- With
--no-fail, the JSONokkey still says if the command passed. - An error is not a finding. A
DeckTalkErrorexits 1, even with--no-fail. - An unexpected exception prints
error: <type>: <message> (add -v for the traceback)and exits 1. - With
-v, an unexpected exception prints its full traceback.
Related
- Read a verify table: verify
- Gate CI on the video: Build in CI and offline
- Fix a message: Troubleshooting