cues.json says which phrase a moment lands on, the
cue stage turns that phrase into a second on its own section’s clock, and the recorder plays the
page to those seconds. Read this page when you choose a phrase, or when a cue and its page disagree.
Writing for the ear is the guide for writing phrases.
The cue id
A cue id is the slide id, a colon, and then the cue name the page writes. Sodata-in="expand" inside <template data-slide="4.1"> is the cue id 4.1:expand, and 4.1:expand
is what cues.json carries. The author writes a short cue name that means something inside its own
slide, and the runtime qualifies it with the slide it was written in, so two slides may each have a
moment called expand and no cue is ever ambiguous. Every other page names this rule and links here.
The slide id, not the section number, is the first half. A section can play a scene whose slides are
numbered differently, and the cue id follows the slide. Section 1 of the starter plays scene 1,
whose two slides are 1.1 and 1.2, which is why its rows begin with both.
Each of the four moments an element declares is a cue id of its own: data-in when it arrives,
data-back when it steps back, data-front when it comes forward, and data-out when it leaves. A
handler registered with DeckTalk.on takes the cue id too, because it may be registered anywhere in
the deck, while a slide’s own on map takes the bare cue name, because the slide is already known.
That split is the whole design. cues.json owns the seconds and the page owns the moments. No page
attribute says when a cue fires, and no row of cues.json says what a reveal looks like. Each file
can be edited without reading the other, and a rename in one is a finding against the other rather
than a silent miss.
The starter’s section 1 shows one cue, 1.2:script, in all three files.
data-in="script" inside the slide 1.2, so the cue id is 1.2:script.
cues.json gives that cue id the phrase what you will say, and its second is the start of the
word “what”.
What decktalk cue does
decktalk cue is the second stage. It reads the take index build/narrate/takes.json to find which
take each section plays, reads that take’s words file for the section’s words and their times,
resolves every row of cues.json against them, and writes build/cue-times.json. Every code it
raises begins with CUE.
build/cue-times.json as they
were, so a cue run for one section never drops the cues of the rest.
Which findings fail a run holds for cue as for every
command.
The same arithmetic runs inside decktalk check, against the words a voiced run would leave rather
than the words it already left, so a phrase that will not match is met before anything is bought.
Matching rules
The stage matches a cue phrase against the section’s spoken words with these rules.- It splits the phrase and the spoken words on whitespace.
- Each token keeps its letters and digits, in any script, and its apostrophes, with a curly
apostrophe read as the straight one. So
café,naïveandηare tokens as written. - Matching ignores case unless the cue sets
case_sensitiveto true. - A token with no letter or digit left is ignored, so the phrase
learning rate -matches aslearning rate. A letter is never ignored, so the phraselearning rate ηneeds a spokenη. - A word that punctuation divides, such as
state-of-the-artorR&D, matches whole and by its parts. The phrasesstate of the artandstate-of-the-artboth match a spokenstate-of-the-art, andzig-zagmatches a spokenzig zag. A phrase that starts inside such a word lands on that word’s start. A word with no letter or digit in it, such as an&or a/spoken as a word of its own, is skipped on both sides, soR & Dandtools / fastresolve. - The stage looks through the spoken words in order for a run that matches the phrase token for
token.
occurrencepicks which match, counting from 1, and the default is the first. - The second is the start of that run’s first word, plus the cue’s
offset_seconds, rounded to a millisecond and never earlier than the section’s own start. $startis the section’s own start, which is 0 seconds on its clock.$endis the end of the section’s last spoken word.
occurrence still resolves, on the first
match. The stage says so as a warning that names every match with its time, because the cue did
resolve and the choice was made for you.
Write a cue phrase the way the voice says it, because the spoken words come from the voice. The
starter’s script says “decktalk dot AI” and its end card shows decktalk.ai, so the cue 3.1:make
matches on “Make your own” and never on the text of the card. A number written in digits comes back
in whatever form the voice chose, so write numbers as words in the script and show digits on the
slide.
Directions are not spoken words. A plain direction such as [beat] becomes a dash the voice
reads as a short pause, and a [pause N] becomes a pause of N seconds. Neither is a word, so a
phrase that spans one still matches. script.md has the rules for directions.
Which sections have cues
Every section key incues.json must name a [[section]] in decktalk.toml, and a key that names
no section fails the load with an error naming the section. A section may have no cues at all. A clip
section is never read by the voice, so its rows resolve to nothing and the stage passes over them
rather than judging them.
min_seconds on a section says how long that section’s visuals need. A section whose speech ends
sooner is reported as a sentence rather than as a finding, because nothing is wrong with the film
yet.
Cue mismatches
Nine codes name a cue that does not agree with something. Five of them are read from the two files before a picture exists, three are measured from a frozen frame or from the finished film, and one compares the cue times on disk with the cue file they were placed from. Every one carries the sentence below, its severity, the object it judged and the fix when there is one.
What each one means for the film, and what clears it:
CUE_UNLISTEDis a moment on the page that nothing incues.jsongives a second to. Add the row, or take the moment off the page. Its fix adds the row for you, which the next section describes.CUE_UNKNOWNis a row whose cue id no slide of the section’s scene declares. The row is named and never deleted. When exactly one stale row sits beside exactly one moment nothing lists in the same section, the two are read as a rename and an unsafe fix changes the id alone, keeping the phrase you already wrote. The phrase is what survives a rename, so the row that carries it is the row for that moment.--allow CUE_UNKNOWNcarries on past it, for a deck that builds ids at run time.CUE_UNRESOLVEDis a phrase the section does not speak. Fix the phrase, or fix the script. A section with no take at all resolves nothing, and the message says which of the two it is.CUE_STALEis a cue file edited after the film was built.verifymeasures the film on disk, and that film was cut to the cue times of the last build, so a row whose phrase or offset changed since, a row added since and a row removed since are all measured against moments nobody asks for now. Nothing is wrong with the phrase. Rundecktalk build, which places the cues again and records only the sections they moved.CUE_NO_ONSETis a cue whose second is 0, which is where the section starts rather than where a word does, or a cue in the finished film that changed the picture with no frame rising byverify.onset_rise_points. Nothing measures its landing against a word, so the offset check cannot run for it. What a cue at 0 reveals arrives as a cut on the section’s first frame.CUE_OVERLAPis two cues closer together than the first one’s own motion lasts. The second moment starts while the first is still playing, so a viewer cannot tell them apart and neither can the measurement.CUE_NO_CHANGEis a cue where less of the picture changed thanverify.changed_share_min_percent, or whose margin over its control was underverify.margin_min_points. The reveal is too small or too pale to see, or it never played.CUE_THIN_CHANGEis a cue that passed with less thanverify.thin_change_factortimes that floor. It is a second opinion rather than a failure, and setting the factor to 1 turns it off.CUE_OFFis a reveal whose measured onset sits further from its word thanverify.cue_offset_max_ms, or a word whose click sounds further from the second it was promised thanverify.av_offset_max_ms. The sound has the wider limit, because an mp3 frame smears a transient and the encode adds its own.
decktalk config explain verify.cue_offset_max_ms prints the layers of any one of them.
The fix that writes cues.json
CUE_UNLISTED carries a safe EditFix that adds the row, so a deck can be written first and its
seconds named afterwards.
--fix lives on check and on build, which are the two commands that apply a fix to a project’s
files, and doctor --fix applies the fixes a machine offers. cue reports the same codes and
applies nothing.
Both comparisons read the moments off the catalog the page itself published rather than off a scan of
its markup, because data-spotlight, data-class and data-owns all declare moments no text scan can
see. check reads a catalog live. cue reads the one the last recording kept while that recording
still stands, and opens the page and reads it as it is now once anything the recording was made from
has changed, so a cue renamed in the page and in cues.json together is judged by its new name before
record has run. The two reach the same judgements. A section whose page has never been opened is
left unjudged rather than guessed at, so check --no-pages reaches neither CUE_UNLISTED nor
CUE_UNKNOWN and names both as judgements it could not make.
The fix writes {"id": "<cue id>", "phrase": ""} and leaves phrase empty, because the phrase is your
line and not DeckTalk’s. A project with no cues.json at all gets one whole file with a row for
every moment the deck declares. A project that has one gets the rows added to the section block they
belong to, or a new block for a section the file holds none for.
A fix only ever adds, so it is idempotent. The second run finds the rows it wrote already declared
and already listed, so no moment of the section is missing any more and it writes nothing. A
hand-written cues.json that the fix cannot place a row in is given the rows to paste instead, as a
fix that is printed and never applied.
The rename fix is the one fix here that is unsafe, because it rewrites an id you typed from a pairing
that is a reading rather than a fact. --fix prints it and does not apply it.
Phrase choice
These guidelines help a moment land on the word you meant. Writing for the ear explains each one.- Start the phrase with the word that names the thing that happens, because the second is the start
of the phrase’s first word. A noun such as
box of dialsworks, and so does a verb with its object, such assteps downhill. A connective such as “and then” does not. - If a word repeats in the section, use two or three words, or set
occurrence. Settingoccurrenceto 1 keeps the first match and silences the warning. - Set a small positive
offset_seconds, 0.1 to 0.2 seconds, so the viewer hears the word begin before the picture moves. - Use a negative
offset_secondsonly when the audience has to read along, and remember that a cue can never resolve before its own section starts. - Put a
[beat]or a[pause N]before a moment that should feel like an event. - Land a summary on
$end, so it arrives as the voice stops. - Set
verifyto false on a row whose change is too small or too slow for a frame difference to see, which leaves that cue out of the measurement rather than out of the film.
Sound on a cue
A[[mix.effect]] table names a section and a cue, and assemble places that sound at the
second the cue resolved to plus the effect’s own offset_seconds. A music marker matches a spoken phrase by
these same rules, through its own on, occurrence, case_sensitive and offset keys, and raises or
mutes the music there. Sound explains both.
Terms
Glossary holds the vocabulary of the whole tool.
Next
- Write phrases that land well: Writing for the ear
- Look up every key of the file: cues.json
- Learn which slide owns a cue: The page contract