Subchapter 29.81
references/storyboard-format.mdMarkdown6 KBView on GitHub
STORYBOARD.md is the single reviewable plan the user approves at Step 3 and the manual
each frame-worker follows at Step 4. It is hierarchical: one block per frame, written
as a heading (the parser recognizes ). Inside each frame block are its (the treatment
units). The assembler reads the frame level ( → , ); the worker
reads its own frame block. A frame’s
( → ), which the worker uses as
and the key.
## Frame N — <frame_id>Framedurationdata-startsrcsrc file stemcompositions/frames/01-f1.html01-f1data-composition-idwindow.__timelinesStep 2 writes the skeleton (frame fields, groups TBD); Step 3 fills the groups + brand. It
is a build spec, not code — the planner writes WHAT, the worker decides HOW. Never write
millisecond tweens here.
YAML frontmatter (the video-wide spine) + one ## Frame N — <frame_id> block per frame.
---
compositionId: bgm
duration_s: 30.0 # == audiomap.audio.duration_sec, exactly
canvas: { w: 1920, h: 1080, fps: 30 }
style: # brand spine — from the chosen frame.md preset (Step 3)
font: "EB Garamond / Inter / JetBrains Mono" # the preset's typography, verbatim
palette: ["#FAF9F5", "#141413", "#CC785C", "#181715"] # ≤4–6 swatches from the preset's colors
assets: false # false, or a note like "assets/ has 6 user photos"
build_notes: ["one paused timeline per frame", "no remote assets"]
avoid: ["generic slideshow", "tiny unreadable hero text"]
---
## Frame 1 — f1
- src: compositions/frames/01-f1.html # worker writes here; assembler refs it; stem (01-f1) = composition id
- duration: 7.198s # = span length; the assembler reads this for cumulative data-start
- span_sec: [0.0, 7.198] # track seconds; frames tile the track
- pacing: beat_cut # beat_cut | phrase_flow (from the skeleton; obey it)
- mood: [hype]
- feel: accelerating onset stream into a held downbeat
### Groups
- **g1** — template: `intro-kinetic-cascade`
- span_sec: [0.0, 4.017] # frame-LOCAL build is 0-based; these are TRACK seconds (worker subtracts frame start)
- params: { theme: "light", icon: "bolt", phrases: "[…]", climax: "{…}" }
- role_bindings: { phrase: { times: [0.14, 0.55, 0.87] }, climax: { in: 3.79, iconAt: 4.9 } }
- copy: "GROWTH THROUGH CREATIVITY"
- **g2** — free_design
- span_sec: [4.017, 7.198]
- free_design: { dominant_system: "per-onset typography", primitives: ["content-swap", "braam-punch"], density_topology: "accumulate" }
- anchors: [4.10, 4.80, 5.50, 6.20] # onset seconds the reveals ride (from audiomap)
- copy: ["BUILD", "SHIP", "REPEAT"]
## Frame 2 — f2
…| field | meaning |
|---|---|
heading ## Frame N — <frame_id> | frame_id matches the src stem; N = the 1-based index. |
src | compositions/frames/NN-<frame_id>.html — where the worker writes; the assembler references it. Stem = data-composition-id. |
duration | the frame span length in seconds (e.g. 7.198s) — required; the assembler sums these for cumulative data-start. |
span_sec | [start, end] track seconds. duration = end − start. |
pacing | beat_cut | phrase_flow — from the skeleton; the worker must obey (no hard-cut on phrase_flow). |
mood, feel | from the skeleton; tone + the one-line music situation the planner matched against. |
### Groups list | ≥1 group; groups tile the frame span in order. |
Every group is template OR free_design OR asset — never two, never none. All three
carry span_sec (track seconds, tiling the frame) and may carry copy.
template: <catalog id> + params (keys from the catalog entry) + role_bindings (real audiomap anchor seconds) + copy.free_design: { dominant_system, primitives: [catalog ids], density_topology } + anchors (real beat / onset seconds) + copy.asset: { treatment, clips: [public/…], anchors?, overlay_copy? }. treatment ∈ beat_cut (one clip per anchor — only on a beat_cut frame) | ken_burns (slow push — fits phrase_flow) | bg_under_text (clip dimmed behind a template / free group). See montage.md.duration_s); a frame’s groups tile its span; no group < ~1 bar; no group boundary inside a rolls[] run.params keys come from the template’s template-catalog.md entry.audiomap.json — the worker converts to frame-local by subtracting the frame start.phrase_flow frame MUST NOT use beat_cut asset treatment or per-onset hard cuts.style is set once; every group’s palette draws from it.compositionId, duration_s (== audiomap), canvas, style.span_sec + src + positive duration + pacing + ≥1 group; frames tile the track.phrase_flow frames have no beat_cut.