Install
decktalk install fetches them up front instead.
A build that does not spend needs no account. A voiced build needs ELEVENLABS_API_KEY in the project’s
.env, and [voices.narrator] id in decktalk.toml, which is a published name rather than a secret and is
part of what names a take. DECKTALK_VOICES_NARRATOR_ID overrides it for anyone who keeps it out of the file.
A variable already exported wins over .env, and a value that still starts with < counts as unset.
Those are what the ElevenLabs voice needs. The local voice, provider = "dtsp", needs no key, costs
nothing, and reaches the server [dtsp] base_url names, which only this machine sets.
The four files an author writes
script.md, decktalk.toml, cues.json and the deck page, in that order. The section number, the
scene its [[section]] names and the slide ids of its cues all agree.
script.md
What the voice says. ## N. Title starts section N, and the rest of the line is its title.
Bracketed text is a direction the voice does not speak. A note on a line of its own and [beat]
inside a paragraph become a short pause, [pause 3] becomes a three second pause, and an ALL-CAPS
bracket such as [NUMBER] is an unfilled blank that raises SCRIPT_UNFINISHED. Any other bracket
inside a paragraph is refused.
A line holding only [voice NAME] hands what follows to that voice. Each stretch one voice reads is
a turn, voiced as its own take, and a section read by one voice is one turn. A line holding only a
note that is exactly a voice’s name, such as [guest], plays as a beat and raises
SCRIPT_VOICE_BARE. Markdown formatting is stripped before the text is sent, and the exact text
each turn sends is its take’s cache key.
Full rules: script.md.
decktalk.toml
The project file. [project] holds name, the optional script, cues and build paths, and the
optional language. One
[[section]] per script section, in order, each with a number and an optional chapter. A page
section adds page and scene, a clip section adds clip and plays a video file of your own, and a
render section adds render_command, a program that draws the section. A program runs only on a
machine whose record.programs allows it, and decktalk check lists each one as PROGRAM_NAMED.
Once you have read them, decktalk build --no-spend --set record.programs=run allows a project’s
programs for one run.
[narration] voice names the default voice and one [voices.NAME] table declares each voice.
[transition], [mix] and [score] follow, and every tuning table is optional.
Full rules: decktalk.toml and Configuration.
cues.json
Which spoken phrase each moment on the page waits for. decktalk schema cues prints its shape.
cues.json
id is a cue id. phrase is a word or short phrase from that section of the script, $start for the
section start or $end for the end of its last spoken word. occurrence picks which match, from 1.
case_sensitive defaults to false, offset_seconds shifts the second, and verify defaults to true.
cues.json owns seconds and the page owns what a thing looks like and what it means.
Full rules: cues.json and Cues.
The deck page
One HTML file underdeck/ that a [[section]] names. A [data-scene] wrapper is one scene, each
<template data-slide> inside it is one slide, and the runtime clones a slide when it mounts. The
runtime is /__decktalk/decktalk-runtime.js and KaTeX is under /__decktalk/katex/, which DeckTalk
serves on the origin it opens the page at, so the page loads nothing from the network.
Full rules: The page contract and Runtime.
The page vocabulary
An element has four moments, and each names a cue local to its slide.data-in="expand" inside <template data-slide="4.1"> is the cue id 4.1:expand, and that
is what cues.json carries. No attribute says when a cue fires.
Thirty attributes are published by decktalk schema page, with each one’s values, default, range,
warning code and motion span. They fall on four rows.
The closed word lists are small.
data-in-style is rise, settle, fade, pop, draw or
cut, and defaults to rise. data-out-style is fade or fall, and defaults to fade.
data-words is highlight or appear, data-count is last or first, data-enter is
crossfade or cut, and data-motion-ease is firm, glide, settle or spring, and defaults to
firm.
A moment is over in under half a second. Anything longer is a motion, declared on the element it
moves and timed between two cues, and anything that moves undeclared is refused. A script declares
one with DeckTalk.motion, and DeckTalk.frame with the region it draws in is a frame hook, which
draws each frame from the section clock. Things that move covers motions, loops,
frame hooks and render sections.
MEASURABLE_SPAN_SECONDS is 0.5, the one ceiling above which a cue cannot be measured.
data-in-seconds runs from 0.12 to 0.44 in steps of 0.04, which is three to eleven frames at 25
frames per second. data-stagger runs from 0.04 to 0.2 in steps of 0.04, and a staggered
container’s total is the step times the children less one, plus the entrance, which must stay under
0.5 seconds. data-preview-seconds defaults to 8 and runs from 1 to 60.
Read the table rather than this summary:
The six stages
build runs them in this order, and each skips work whose inputs have not moved.
build/final/ holds <name>.mp4, <name>.srt, <name>.vtt, <name>.chapters.txt,
<name>.words.json, placements.json, <name>-transcript.html and <name>-poster.png, and
<name>-captioned.mp4 when [output] captioned is true and <name>-<YYYYMMDD-HHMM>.mp4 when
[output] timestamped_copy is true. build/frames/ holds the slides check freezes,
build/storyboard.html and build/storyboard/ hold the contact sheet, and build/events/ holds
one JSON Lines file per run.
Every path: Build artifacts.
The commands
Every one of them takes--json. Run decktalk <command> --help for the whole list of its flags.
Set up this machine
Read the project, buying nothing
check makes no film and replaces the idea of a rehearsal before a paid run. check --no-pages
judges the written files with no browser at all and names on stderr the codes it could not reach.
check --no-frames keeps the browser and drops the freeze comparison. check --fix applies every
safe fix. storyboard writes build/storyboard.html, which is the human checkpoint before anything
is bought.
Read the settings and the schemas
decktalk schema NAME takes a command name, or apply, finding, error, event, cues, page or
setting.
Run one stage, in this order
--replace-voiced and --replace-score are the two flags here that buy what you already own, and
--turn and --take buy one turn’s take again. With --spend, --replace-voiced voices each named
section again, --turn 4.2 voices section 4’s second turn again and nothing else, and
--replace-score buys each bought sound again. A voiced take bought again is set aside in
takes/rejected/, never deleted. With --no-spend, --replace-voiced plays a placeholder in place of the voiced take
and --replace-score keeps every bought sound. --force builds again from nothing and never spends, so it keeps every voiced take and every bought sound. A build that finds nothing
moved keeps assemble and verify and reports them as kept, and --force measures again.
Run them all, or cut one piece out
build --watch stays running, rebuilds the changed section and never spends.
Every flag: CLI.
The flag families
Seven global flags work on every command, before or after the command name.--version is the
eighth, and it works on decktalk itself.
--yes is recognised on every command and always refused with USAGE, and the refusal names the
flags that answer that command’s prompts. Every prompt DeckTalk asks has a flag of its own, so a
blanket yes would be a flag that agreed to things nobody named.
The scope flags narrow what a command works on. --section N takes 3, 3,5 or 7-9 and
repeats, and it is on check, words, storyboard, build and every stage command. On clip it
names exactly one section.
build adds --from, --to and --skip, assemble adds --skip, storyboard adds --slide,
--after, --before and --at, and check takes deck pages as positional arguments beside the
project’s own.
The spend flags are on the three commands that can buy something, which are narrate,
score and build. --no-spend plays every take on disk, puts a placeholder where a take from a
voice that bills is missing and reports it as TAKE_MISSING, and needs no API key. A free provider such as dtsp
makes its takes either way once a voice is named. --spend buys what is missing without asking first. --max-cost N refuses before the first call if the most the run can cost is over N US
dollars, and it is compared against the spend object’s ceiling_dollars. With neither flag, a run
with something to buy prices it and asks on a terminal, and without a terminal it refuses with the
error code APPROVAL. A run with nothing to buy is not asked, and neither is one whose voice
declares itself free, which buys without asking. --no-spend never buys, whatever the price.
The findings flags are on every command that can judge something, which are doctor, check,
storyboard, narrate, cue, record, score, assemble, verify and build.
--fail-on error is the default, --fail-on warning also fails on a warning, and
--fail-on never fails on none. --allow CODE carries on past one code and repeats. --fix
applies every safe fix and --no-fix applies none, on doctor, check and build.
--set KEY=VALUE overrides one setting for one run, repeats, and is on status, check,
words, storyboard, serve, build, clip and every stage command. No flag duplicates a
settings key, so reduced motion is --set motion.reduce=true and not a flag of its own.
The JSON contract
Every command’s--json is one flat object. There is no wrapper, no command key and no
exit_code key.
decktalk schema is the one exemption: it prints the contract document itself with no reserved keys
around it, because a JSON Schema document inside a wrapper is not that document.
A finding carries code, message, severity, location, stage, fix and docs. severity
is error or warning. location carries a required where naming the object judged, plus
file, line, section and cue. fix is one of edit or command, each with a title and
an applicability of safe, unsafe or display. An edit that changes a setting names its key. In the library
Project.apply(finding) applies one.
--events prints one JSON line per event on stderr as it happens, and every run of a project also
appends build/events/<run>.jsonl. The discriminator key is event, and its names are
run.start, run.done, stage.start, stage.done, section.start, section.done, stage.progress,
finding.raised, cost.priced, take.charged, sound.charged, tool.fetch and run.log. run.done, stage.done and section.done carry an
outcome of ran, kept, skipped, stopped or failed, and run.done carries the error of a run
that did not finish.
Whole contract: The JSON contract.
Exit codes and error codes
0 is a clean run, 1 is a finding at or above the--fail-on threshold, 2 is a refused command line
or spend, which is USAGE or APPROVAL, 3 is every other error, and 130 is a run the caller
stopped. Exit codes and Error codes are
the tables.
A non-zero exit with error null is a finding, so read findings, change the project and run the
command again. A non-null error is an error, so stop and tell the person.
Every finding code has a page of its own, and decktalk schema prints them all with their
sentences, their severities and the settings keys that move them.
Settings
A project key is set by its default, thendecktalk.toml, then DECKTALK_<TABLE>_<KEY>, then
--set table.key=value for one run. A machine key, about this machine rather than the film, takes
the per-machine file machine.toml in place of decktalk.toml, and a project file that sets one is
refused. decktalk schema setting --scope machine prints those keys, and
Which value wins has the rule and the file’s path on
each platform.
The settings sit in [video], [narration], [record], [audio], [verify], [voices.NAME], [mix],
[motion], [elevenlabs], [dtsp], [score], [output], [events] and [tools]. decktalk.toml also carries
the tables that are project content rather than tuning, which are [project], [[section]],
[transition], the prompts of [score] with [score.effects.<name>], and
[[mix.effect]]. [mix] and [score] are each both things at once, because each holds
content keys the document owns beside settings the settings loader declares.
The published range is the safe range. A bound is there because a value past it deletes a check,
corrupts the evidence a later stage measures or breaks a tool, and the loader refuses a value
outside it, naming the file and the line. decktalk config explain KEY prints the value in force and
the layer it comes from, along with the key’s sentence, its unit, its range, its hazard and the finding
codes it moves.
Two environment variables name no key: DECKTALK_PROJECT and DECKTALK_MACHINE_FILE. Every other
DECKTALK_ name is a key or a typo.
Every key: Configuration.
Python
Nothing in the library prints, and every call returns the same object the CLI serialises.decktalk.open(path, *, machine=None, overrides=(), threshold=Threshold()) returns a Project,
whose Threshold decides which findings fail its calls, and
decktalk.init(path, *, machine, name, example, skills, overwrite) writes one.
Machine.from_environment() is the only function that reads the environment, the per-machine file
or the working directory. Project carries the twelve calls narrate, cue, record,
score, assemble, verify, build, status, check, words, storyboard and clip,
each taking cancel, along with apply, serve, reload, sections_touching, price, select
and programs. No library call
spends without spend=True, max_cost is checked before the first paid call, and
ApprovalRequired is raised rather than buying.
Every public name: Python API.
The calls that discover the rest
This card is a summary of what the tool already publishes. When a fact here and a fact from the tool disagree, the tool is right.Related
- Look up a command: CLI
- Look up a setting: Configuration
- Read a result: The JSON contract
- Look up a term: Glossary
- Fix a message: Troubleshooting
- Build a project someone else wrote: Pages and programs you did not write