Repository navigation
Place scenes on an absolute timeline with a beat grid #336
Description
Part of #326. Batch 1 — #329, #330, #331 and #334's second half all depend on the TimePoint type this workstream introduces.
build_frame_tasks builds a flat Vec<FrameTask> where the index is the frame number, and a transition's frames replace scene frames instead of overlapping them. Six scenes declaring 15.0 s therefore render 13.5 s, and every cut after the first transition drifts: -0.30 s, -0.60 s, -0.90 s, -1.15 s. At 115 BPM that last one is more than two beats. A rhythmic edit is currently impossible without compensating every duration by hand, and changing one transition re-times everything after it.
Owned files
crates/rustmotion-core/src/schema/time.rs(new —TimePoint)crates/rustmotion-core/src/schema/scenario.rs(Scenario.bpm,beat_offset,duration,timing;Scene.at,Scene.tail)crates/rustmotion/src/encode/video/tasks.rs(build_frame_tasks,build_slide_view_tasks)
Do NOT write: schema/animation.rs, engine/animator.rs (#330), schema/vars.rs (#329), any audio file (#331).
Deliverables
-
TimePoint— a value that is a bare number (seconds), or a string carrying a unit:"2.5s","8b","8b+120ms". Beat units requirebpmand error withunresolved_beat_unitwithout it. The grid isbeat_offset + n * 60/bpm; the reel being reproduced anchors its grid at 2.2 s, not at 0, sobeat_offsetis not decoration. -
One rule for anchoring, stated once in the schema docs.
aton a scene is absolute by definition. Everything inside a scene is relative to that scene. The prefix@forces absolute:"@8b". -
Scene.at, defaulting to"auto"— immediately after the previous scene's end, which is today's sequencing minus the subtraction. -
Transitions become a declared overlap. Scene i occupies
[at_i, at_i + duration_i). A transition of length d means scene i-1 is also rendered during[at_i, at_i + d), past its own end.Scene.taildefaults to"freeze"and reuses thefreeze_atmachinery;"continue"lets its animations run on. Total duration becomesat_last + duration_last, with no subtraction. -
snap: "beat"at scenario level rounds everyat,start_atanddelayto the nearest beat. This is the cheapest line in the whole chantier for getting a rhythmic edit by default, without the author having to think about it. -
off_grid_cutas a validation warning whenbpmis set and a cut does not land on a beat. -
The behaviour change sits behind
"timing": "v2"at the scenario root. Absent means today's subtraction plus a deprecation warning fromrender, following the pattern the legacy top-levelsceneswarning already uses.
Acceptance
- Six scenes declaring 2.2 + 2.6 + 2.6 + 3.12 + 2.08 + 2.4 with five transitions render 15.0 s under
timing: v2 - The same file without
timing: v2renders 13.5 s and warns --frames a-bstill addresses the same index space
Activity
[-]WS-1 timeline: absolute scene placement and a beat grid[/-][+]Place scenes on an absolute timeline with a beat grid[/+]LeadcodeDev commentedon Sep 26, 2026
Delivered on
mainat 187cf7c (squash of #340). Verified present onmain, not taken on the PR's word.