Skip to main content
The page contract is the set of rules that lets the recorder play an HTML page in time with the narration. To write a page, follow Your first deck.
  1. decktalk-runtime.js implements the contract. A page can also follow it by hand.
  2. The URL of a page picks one of four modes.
  3. The recorder hides the page under a magenta cover, then starts the page clock at narration t=0.
  4. Each step mounts at the earliest cue it owns, and each cue fires at its cue time.
  5. Your CSS styles the slides. The runtime adds only the stage element (#dt-stage), slide transitions, and reveal effects.

Modes

A page holds scenes, and a page section plays one scene. A scene has steps, and each step renders one slide. A page plays in one of four modes, and window.__decktalk.mode holds the mode value. Modes in the runtime reference lists the URL, the clock, and what mounts in each mode.

Browser preview and recording

A browser preview opens the page without ?beats=, so it plays in autoplay. A recording plays in cue mode. This table shows which values matter in each. data-at defaults to 0. So a browser preview shows a data-cue element with no data-at as soon as its step mounts, before its cue.

The handshake

With t0=signal in the URL, the page starts its clock only when the recorder calls DeckTalk.startClock(). A browser preview has no t0=signal, so its clock starts at the load event. The recorder wait comes after window.__sceneReady resolves and before the recorder removes the cover. Two [record] settings set it.
The defaults are settle_seconds = 0.5 and min_lead_seconds = 1.5. The cover hides the page during the wait. How it works explains why the first frame after the cover is narration t=0. From the first paint until the recording stops, the recorder keeps a 2 px square turning in the bottom-right corner at 3 % opacity. The square keeps the browser drawing frames at the same pace before and after t=0. A still page then records each reveal on its scheduled frame, not a frame or two early. The square is too faint for verify or check to measure, and decktalk shots never shows it. A page needs no motion of its own for timing. A page that starts its own clock at load fires every cue early, by the whole time from load to t=0. Every reveal in the video then comes before its word. After the recording, the recorder reads these values from the page and writes them to the sidecar:
  • window.__decktalk.warnings. The recorder also logs each warning.
  • The page’s uncaught errors. A missing or empty window.__decktalk.catalog counts as one more error.
  • window.__decktalk.frameGaps.
  • window.__decktalk.syncLog.
The check stage reports PAGE ERROR for a page error. It reports KATEX? for a warning that mentions KaTeX or data-tex. decktalk check lists every verdict.

Cue ownership

Each cue in ?beats= has one owner, a step of the playing scene. The runtime picks the owner with three rules.
  1. A step whose id equals the cue id owns the cue.
  2. A step whose cues list or object names the cue owns the cue.
  3. Otherwise, the step whose id is the longest prefix of the cue id owns it. For example, step 4.2 owns cue 4.2b1, and step 9 owns cue 9a.
Rules 1 and 2 have the same priority. The first step in the scene that matches either rule owns the cue. The runtime looks only in the playing scene. In cue mode, ownership decides when each step mounts:
  • A step mounts at the earliest cue time it owns.
  • The first step to mount does so at t=0, even when its earliest cue is later.
  • A step that owns no cue in ?beats= never mounts.
  • The last step to mount stays until the recording ends.
A mismatch between cues.json, the page, and its steps adds a warning. Cue mismatches lists each one, with its result.

When a cue fires

When a cue fires, the runtime adds its id to window.__decktalk.fired. Then it does three things, in this order:
  1. Every element on the mounted slide whose data-cue matches the cue appears.
  2. The mounted step’s on[id] handler runs, if the step has one.
  3. Every handler that DeckTalk.on(id, fn) registered for the cue runs, in the order of registration.
Each handler gets the slide element and a context object, { id, at, frozen, step }. A handler finds its elements with slide.querySelector and needs no global variable. Handler context describes the fields. An element with data-sync starts to show its words one at a time when it appears.

Build artifacts a page can read

A page gets its cue times as ?beats=, from build/audio/beats.json. It gets the section’s spoken words as ?words=, and the words of the section before it as ?prevwords=, both from build/audio/timeline.json. A tool of your own can read those files too. Build artifacts has the shape of each file.

Terms

Next