Skip to content

Place scenes on an absolute timeline with a beat grid #336

Description

@LeadcodeDev

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

  1. TimePoint — a value that is a bare number (seconds), or a string carrying a unit: "2.5s", "8b", "8b+120ms". Beat units require bpm and error with unresolved_beat_unit without it. The grid is beat_offset + n * 60/bpm; the reel being reproduced anchors its grid at 2.2 s, not at 0, so beat_offset is not decoration.

  2. One rule for anchoring, stated once in the schema docs. at on a scene is absolute by definition. Everything inside a scene is relative to that scene. The prefix @ forces absolute: "@8b".

  3. Scene.at, defaulting to "auto" — immediately after the previous scene's end, which is today's sequencing minus the subtraction.

  4. 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.tail defaults to "freeze" and reuses the freeze_at machinery; "continue" lets its animations run on. Total duration becomes at_last + duration_last, with no subtraction.

  5. snap: "beat" at scenario level rounds every at, start_at and delay to 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.

  6. off_grid_cut as a validation warning when bpm is set and a cut does not land on a beat.

  7. The behaviour change sits behind "timing": "v2" at the scenario root. Absent means today's subtraction plus a deprecation warning from render, following the pattern the legacy top-level scenes warning 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: v2 renders 13.5 s and warns
  • --frames a-b still addresses the same index space

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions