decktalk init --example motion my-motion writes a project that does every kind of motion on this
page. Its first section moves a packet across the frame, turns a ring and springs a card in. Its
second fills a bar from script. Its third is drawn by a Python script rather than a page.
That script is a program the project names, and a machine refuses a project’s programs until you
allow them, because a program runs with your user’s rights and can read every file you can, your
.env included. Read render/draw_bars, then build the example on placeholders with it allowed
for that one run:
Choose the noun
A
<video> or an <audio> element on a page is
PAGE_REALTIME_MEDIA. It plays at its own rate rather
than on the stepped clock, so the recording could not say which frame of it shows at which second.
Footage belongs in a clip section, and a moving picture a program makes belongs in a render section.
The four eases
data-motion-ease, and ease in DeckTalk.motion, names how a motion moves between its two cues.
firm is the default because an arrival has to stop on a frame edge to be measured. Verify finds an
arrival as the last frame on which the motion still moved, and a motion that keeps some speed to the
end has a last moving frame that sits exactly on its cue. A motion that eases to rest moves less and
less, so its last measurable frame comes before its cue by however long the slow tail is, and a
viewer sees it settle before the word.
So a settle or spring arrival is allowed only on a cue that cues.json marks "verify": false.
Anywhere else, decktalk check raises
MOTION_EASE_UNMEASURABLE before anything is
recorded. A departure is measured whatever the ease, because every ease leaves its first frame
moving.
A motion in markup
A motion names the@keyframes it moves through, the cue it departs on and the cue it arrives on.
Both are cue names local to the slide, like a moment’s, and both join the slide’s cues, so each needs
its row in cues.json. This is the packet in the example’s first section.
deck/index.html
cues.json
travel for exactly the seconds
between the two. Nothing in the markup is a length, so rewriting the sentence between the two words
makes the packet travel faster or slower and still land on “now”.
Until its departure the element rests as its own style draws it, so the first step of its
@keyframes should be that same style. A first step that differs makes the element jump on the
departure frame.
A motion whose arrival is not after its departure, or whose cue has no second, never plays, and the
page reports it as PAGE_MOTION_CUE_UNKNOWN.
The label beside the packet is an ordinary data-in on the same cue the packet arrives on. Verify
measures it as a reveal with the packet masked out, which is what keeps the cue measured as a step.
A spring that comes to rest
The card in the same slide springs in from “spring” and comes to rest on “rest”. A spring has no edge to measure, so the arrival cue opts out of verify.deck/index.html
cues.json
A loop
A loop names the@keyframes it turns through and how long one turn takes. data-loop-seconds runs
from 0.2 to 60 and is 1 when it is left out.
deck/index.html
A motion drawn from script
DeckTalk.motion(el, { from, to, ease, draw }) is the same noun for a page that draws the motion
itself. from and to are cue ids, ease is one of the four eases and is firm when it is left
out, and el is the element, or a selector for it, that the motion draws inside.
draw(progress, seconds) is called on every frame between the two cues, with the eased progress
from 0 to 1 and the section second. Nothing is drawn before the departure, and the last call is made
exactly at the arrival with progress 1. This is the bar in the example’s second section.
Nothing is drawn after the arrival, so draw finishes by then. Just before its last call, draw is
called once more with progress 1 at half a second past the arrival, and when the element shows
something different there, such as a fade timed from the second once the progress reached 1, the page
reports PAGE_MOTION_UNFINISHED at the arrival’s cue:
the picture stops where the arrival left it. Move the arrival to a later cue, or end what draw
changes by the arrival.
deck/index.html
data-owns. That is
how a slide owns a cue only a script serves.
A cue the page does not know, or an arrival that is not after its departure, is
PAGE_MOTION_CUE_UNKNOWN, and the motion draws
nothing.
A frame hook and its region
DeckTalk.frame(fn, { region }) calls fn(t) on every frame with the section second, for
something that is drawn rather than animated: a canvas, a typed line, a scrolling voice line.
region is the element, or a selector for it, that the hook draws inside, and verify masks that box
out of every cue while it is on the page.
A hook with no region is PAGE_MOTION_UNDECLARED,
because nothing tells verify where it draws. A hook is also how the recorder knows a frame changed:
it writes the frame before again for a frame where nothing it knows of moved, so anything a page
draws outside the DOM, a cue, an animation or a declared motion is drawn from a hook. A page that
holds a canvas is captured on every frame regardless. Still
frames lists what counts. A hook that throws is reported once as
PAGE_FRAME_THREW and is not called again.
This voice line scrolls under a fixed playhead at the speed of speech. It is drawn from the second
alone, so a recorded frame and a preview frame of the same second are the same picture.
deck/index.html
--dt-width, which the runtime puts on :root.
The pictures above the voice line still arrive with data-in on their words, and verify measures
each of them with the voice line masked out.
A composition page
A composition page is a page section whose page draws the whole picture itself, in a canvas, in WebGL or with three.js. It is an ordinary page section, and it reads its timing from the runtime rather than keeping a clock.
Key every change on a cue’s second from
DeckTalk.cues rather than on a number of your own, so a
line voiced again moves the composition with it. A cue that only the composition uses still needs a
slide that owns it, through data-owns or a script slide’s owns.
A WebGL canvas drawn from a frame hook records frame for frame, and two recordings of it are the
same frames. That is tested with raw WebGL and a context created with preserveDrawingBuffer: true.
three.js draws through the same WebGL and is not tested itself.
A render section
A render section is a section whose picture a program draws rather than a page. It names arender_command and no page and no scene.
decktalk.toml
cue resolves its cues from
its words, and the voice runs straight through it. That is the difference from a clip section,
which carries its own sound and pauses the narration while it plays.
record writes the section’s motion document and runs the command once, in an empty scratch folder,
with each {name} word in it replaced.
The motion document holds the frame, the length, every spoken word and every cue, and every second
in it is on the section clock.
build/recordings/render/03/motion.json
round(cue * fps).
The command is a program the project names, so it runs only on a machine that allows it through
record.programs, as programs a project names says. It
runs with your user’s rights and can read every file you can, .env included. It runs in an empty
scratch folder rather than the project, a word that names a project file by a relative path such as
render/draw_bars is handed to it as that file’s absolute path, and it is given the scrubbed
environment with no proxy, so a credential in your shell does not reach it. It may run for
tools.timeout_seconds. It fails the section when it exits with an error or writes no video. The section is recorded again when the command, the
motion document or a project file the command names changes, so editing render/draw_bars draws
the section again.
A machine whose record.page_policy is untrusted runs no program a project names, so a render
section is refused there with INPUT.
Landings
A command may write{landings} as a list of lanes in the shape a page reports its own, and verify
then masks and measures them as it does a page’s.
build/recordings/render/03/landings.json
A file in any other shape fails the section. A section whose command writes no landings has every
cue skipped as
rendered, and verify says on its stream that it measured none of them, because a
frame difference over a picture nobody described could read the picture’s own motion as a reveal.
render/draw_bars in the example is a Python script with no dependency beyond the standard library.
It reads the motion document, composes one ffmpeg filter graph in which a bar slides in on each of
the three cues, runs the ffmpeg it was handed, and writes one lane per bar so verify measures each
departure against its word.
Remotion, a three.js scene under a frame stepper of its own, or any program that turns a JSON file
into a video fits the same contract. Wiring Remotion as a render_command is untested, and it is
never a dependency of DeckTalk. Remotion is free for individuals and small companies and paid above
that, so read its licence before a project depends on it.
What verify does with each
The recorder samples every declared motion, loop and region on every frame it steps, and the recording log keeps one lane for each: the box it swept, the size of the element, the first and last second it moved, and the cues it lands on. The lane report gives its fields. Masks. Every cue is measured with every lane that is alive anywhere from its control spans to its last probe masked out of the changed share, the control share and the onset. TheMasked
column of the verify table says how much of the frame that took. Over
verify.motion_mask_max_percent of the frame, 40 percent by default, raises
MOTION_MASK_LARGE, a warning that the cue was judged on
what was left.
Landings. A cue that is only a motion’s departure or arrival, where the page reveals nothing
else, is skipped in the cue table as motion_landing and measured on the motion’s own lane instead.
Inside the lane, frame by frame, the motion counts as moving while more than
verify.motion_floor_percent of its own area changes, 0.5 percent by default. Its departure is the
first moving frame from one reference lead before its cue, and its arrival is the last moving frame.
Each landing is a row in a second table, under the cue table.
A landing on a cue that
cues.json marks "verify": false has no row. Verify
gives the whole measurement.
On a still
storyboard and check draw stills, and a still has no clock. A loop rests in its own style, and a
motion whose departure cue has fired is drawn where it ends.
The findings
Related
- Read the noun beside the moment: The page contract
- Look up every call a page may make: Runtime
- Read what verify measures: Verify
- Play footage you already have: Play a clip