Skip to main content
A setting is a number or a word a project could reasonably hold differently, and which some judgement names when it fails. Every one below publishes the range that is safe to turn it through, its true unit, the file it belongs in, and the findings its value moves. The range is the range the loader enforces: a value outside it is refused by name, with the range it left, before any stage runs, because a published bound you can cross into nonsense is worse than no bound at all. Bind the schema to your project file and an editor completes every key as you type it.
decktalk.toml

Which value wins

Every key has a scope, in the Scope column below, and the scope names the one file that may set it. A project key is set by these, each overriding the ones before it:
  1. The default in the table below.
  2. The same table in the project’s decktalk.toml.
  3. The environment variable each key publishes, such as DECKTALK_VIDEO_PRESET.
  4. --set table.key=value, for one run, on status, check, words, storyboard, serve, narrate, cue, record, score, assemble, verify, build and clip.
A machine key is set the same way, with the per-machine settings file in place of decktalk.toml. decktalk config explain KEY prints the value in force and the layer it comes from, so you never have to work out which one that is. Each file refuses a key of the other scope by name. A key about the film in the per-machine file is refused because the file that ships has to carry whatever the machine running it believes. DECKTALK_MACHINE_FILE names a different per-machine file.

Keys only a machine may set

These keys describe the machine rather than the film: where a tool or a cache lives, and how hard this machine may be driven. A project file that sets one is refused by name, because a project travels and a path or a limit that is right on one machine is wrong on the next. Write one into this machine’s file with decktalk config set KEY VALUE --scope machine, or set its environment variable. narration.concurrency, narration.retries, narration.store_dir, record.page_policy, record.programs, record.concurrency, record.chunk_frames_min, record.chunk_startup_seconds, record.step_seconds, record.page_deadline_seconds, record.deadline_slowdown, record.renderer_retries, record.encode_threads, elevenlabs.base_url, dtsp.base_url, dtsp.handshake_seconds, events.max_bytes, tools.chromium, tools.ffmpeg, tools.ffprobe, tools.timeout_seconds, tools.fix_timeout_seconds and tools.cache_dir.

Which key moves which failure

A finding names the key that decided it. This is the same index in reverse, for the case where you have a code and want the candidates before you run anything.

[video]

These keys set the frame size and the encoding of every recording and of the final mp4.
video.size An odd side cannot be encoded, because the film’s colour is stored at half the frame’s width and height, and a side past the range is a frame Chromium and x264 are not held to drawing.video.crf Above about 32 the encoder’s own ringing is larger than a small reveal, so a cue that played reads as no change and the check that would have caught it passes instead.video.slate_color The colour is placed inside an ffmpeg filter graph and the slate page’s stylesheet, so any other text could add a filter that opens a file or a rule that loads a URL.

[narration]

These keys govern how the script is turned into audio.
narration.concurrency A voice provider limits requests per account, and a busy answer is retried rather than paid twice.narration.takes_dir An empty value, a directory outside the project, an absolute path, the project directory itself, a directory inside the build directory or one that holds it is refused when the project loads, because a voiced take must land in a folder the project keeps, and a project someone else wrote would otherwise choose where this machine reads and writes its takes.narration.store_dir It holds the spoken words of every script voiced on this machine, so keep it out of a synced or shared folder. A relative path, a folder inside the project or one inside the tool cache is refused when the project loads. Write an absolute path or one that starts with ~.narration.sound_end_noise_dbfs Above about -25 dBFS the scan calls quiet speech silence, so the take is placed early and the cut that follows it lands on a word.

[record]

These keys tune how record opens each page section in headless Chromium and steps it frame by frame.
record.page_policy A service that renders pages other people wrote sets untrusted on its machine, because a trusted page can reach anything the machine can, including a cloud metadata endpoint.record.programs run executes whatever a project’s decktalk.toml names as soon as record or build reaches it, so set it only on a machine that builds projects whose programs you have read.record.concurrency Each recorder steps its own Chromium and its own encode, so a number above the machine’s share makes every chunk wait on the others and the run slower rather than faster.record.chunk_frames_min Every chunk loads the page again, so chunks much shorter than a page load spend the machine on loading rather than on frames.record.chunk_startup_seconds A start-up stated far too low splits short sections into chunks that each spend more loading the page than recording it.record.page_deadline_seconds A deadline set near the time a frame takes stops healthy recordings on a busy machine.record.deadline_slowdown A value near one stops a recording that a loaded machine is merely slow to make, because the two calibrations are this machine’s speed when it is idle.record.encode_threads x264 buffers frames for every thread it runs, so a large number costs each recorder hundreds of megabytes and buys no speed, because the encode is never what a recording waits on.

[audio]

These keys are the final audio: its encoding, and the loudness it is normalised to and judged against.
audio.true_peak_max_dbtp Four times oversampling under-reads a true peak and the AAC encode overshoots on top of that, so a ceiling above about -1 dBTP reports a clean mix that clips on a listener’s decoder.

[verify]

These keys are the limits verify judges the assembled mp4 against.
verify.reference_lead_extra_ms The lead is already the offset limit plus the grid guard, so extra lead is only ever the escape hatch for a deck whose reference frame is still inside its own reveal. Above about 80 milliseconds the reference frame reaches back into the previous cue and the check compares two changes rather than one.verify.probe_diff_luma A high value counts only a change that crosses most of the range, so a reveal that fades in or moves a light element on a light slide reads as no change at all.verify.changed_share_min_percent Above about 5 percent only a change across most of the slide passes, so every small reveal in the deck reports a failure it cannot fix.verify.onset_rise_points The rise is measured over a quarter-size frame, so one point is already tens of thousands of pixels. Above about one point no frame ever qualifies, every cue reports a null offset, and the check that names a late reveal stops running while the run still exits clean.verify.click_floor_dbfs DeckTalk generates its own click at -24 dBFS, so a floor at or above that level finds no click at all and every a/v row measures nothing while reporting no failure.verify.cue_offset_max_ms A viewer sees a reveal land late at about a fifth of a second, so above roughly 200 milliseconds the limit passes films whose pictures visibly miss their words.verify.motion_floor_percent Above a few percent the slow last frames of a firm arrival read as still, so its arrival is measured early and a motion that landed on its word fails.verify.motion_mask_max_percent Near the top of the range a cue is judged on a sliver of the frame, so a reveal under a large declared motion passes on very little evidence.verify.av_offset_max_ms An mp3 frame smears a transient across about 26 milliseconds and the encode adds its own, so a limit under 80 milliseconds reports a failure that no edit to the film can clear.

[mix]

The settings half of [mix], which is how each layer is ramped. Its files and levels are project content.

[motion]

These keys decide how much motion a build renders, which changes the film it produces.
motion.scale A scale above one slows motion down, and a span slowed past the measurable ceiling makes its own cue unmeasurable, so each scaled span is clamped at that ceiling rather than obeyed.

[elevenlabs]

These keys are ElevenLabs’s own: its speech fields, its model, its rate, its output format and its API. The key it is bought with is ELEVENLABS_API_KEY, and base_url is the machine’s to set. The score stage buys from the same API with the same key.
elevenlabs.stability ElevenLabs takes a share and refuses anything else, so a value read as a percentage fails the request rather than the load.elevenlabs.dollars_per_1000_characters It is zero until somebody states it, and --max-cost refuses a run while the price is still the default, because DeckTalk would otherwise be capping a spend against a number it invented. ElevenLabs bills per character, so a zero somebody stated still asks before it buys.elevenlabs.output_format Every take already bought was bought in the format named here, so another one buys every take again.elevenlabs.base_url The script, and for a provider that bills the API key, travels to whatever host this names, so only the machine names it and a project file that sets it is refused.

[dtsp]

These keys are the dtsp provider’s own: where its local server listens, the model it reads with, and how long the server has to say which aligner it serves. dtsp speaks the DeckTalk speech protocol to decktalk-voice, a separate local server that is not part of this repository and is not yet public. The same server times the words of a take whose voice sent none. It needs no key, bills nothing, and base_url is the machine’s to set.
dtsp.base_url The script, and for a provider that bills the API key, travels to whatever host this names, so only the machine names it and a project file that sets it is refused.

[score]

The settings half of [score]: how the music, the ambience and the effects are asked for. Each item’s own table holds its prompt and its file, which are project content, beside the settings that size its request, so a key is spelled the same way the item it sizes spells it.
score.dir An empty value, a directory outside the project, an absolute path, the project directory itself, a directory inside the build directory or one that holds it is refused when the project loads, because a bought sound must land in a folder the project keeps, and a project someone else wrote would otherwise choose where this machine writes what it buys.

[score.ambience]

The settings half of [score.ambience]: how the ambience bed is asked for. Its prompt and file are content.
score.ambience.dollars_per_minute It is zero until somebody states it, and --max-cost refuses a score while any rate it buys at is still the default, because DeckTalk would otherwise be capping a spend against a number it invented.

[score.effects]

The settings half of [score.effects]: how each effect is asked for unless its own table says.
score.effects.dollars_per_minute It is zero until somebody states it, and --max-cost refuses a score while any rate it buys at is still the default, because DeckTalk would otherwise be capping a spend against a number it invented.

[score.music]

The settings half of [score.music]: how the music is asked for and joined. Its prompt is content.
score.music.dollars_per_minute It is zero until somebody states it, and --max-cost refuses a score while any rate it buys at is still the default, because DeckTalk would otherwise be capping a spend against a number it invented.

[output]

These keys switch the files a build writes beside the final mp4.

[events]

These keys bound the events files a run writes under build/events/.
events.max_bytes A file with no bound grows with every tool call a long film makes, on a disk a host shares.

[tools]

These keys name the tools DeckTalk drives, for a machine that supplies its own.
tools.fix_timeout_seconds A fix that fetches a browser and an encoder downloads a few hundred megabytes, so under a minute a slow link stops it part way every time.tools.cache_dir A relative path is refused when the machine loads. Write an absolute path or one that starts with ~.

[voices]

Every voice of the project, one table per voice, each named by the name a voice direction in the script calls it by. The table [narration] voice names is the default voice. These keys are the three every voice has: which provider reads its turns, in which voice and at what pace. Each voice is one [voices.NAME] table. Everything a provider is particular about, its own fields, its model and its rate, is in that provider’s own table, and a voice may state any of that table’s chosen keys for itself alone, so changing provider never sends one vendor’s fields or model to another. Write one table per voice, named by the name the script’s voice directions use, such as [voices.guest]. A voice name is a lower-case letter followed by lower-case letters and digits. Each key below is set for that voice alone, and its variable spells the voice’s name, such as DECKTALK_VOICES_GUEST_ID. A key that names a provider table’s key reads that table’s value until the voice states its own.
voices.<name>.id The id is placed in the path of every speech request, so a value that could hold a slash, a dot or a query would let a project somebody else wrote send the key to another endpoint of the service.voices.<name>.speed The provider refuses a multiple outside its own range, so a slower read is a script change rather than a setting.voices.<name>.stability ElevenLabs takes a share and refuses anything else, so a value read as a percentage fails the request rather than the load.voices.<name>.output_format Every take already bought was bought in the format named here, so another one buys every take again.

The numbers that are not settings

These are the numbers that decide something and are still not settings. A derived number is written as its expression, so it follows the keys it reads at every frame size and every rate. A constant is a fact about a codec, a standard, or a tool DeckTalk drives, and it is fixed for the same reason a sample rate is. Neither can be set, and both are here so that a setting you cannot find is a number you can read.
  • Set the sections, the voice and the mix: decktalk.toml
  • Read the [verify] limits in context: Verify
  • Turn a key for one run: CLI