Shot length, split and aspect override (#41) #91

Merged
crowmaki merged 3 commits from issue-41-shot-length into main 2026-10-08 06:57:57 +00:00
Owner

Closes #41. Part of #24.

What

  • Shot length. The length comes from the Lines' text estimate (dialogue 2.5 words/s plus 0.5 s per parenthetical; action 1.5 words/s, at least 1 s) plus a 0.5 s head and a 0.5 s tail handle, kept within 2–15 s. A length you set is the Shot's length, clamped to 2–15 s, whatever the estimate says.
  • Frame grid. Lengths round up to H3's grid: 5 + 17k frames at 24 fps, at most 362. Extra frames go to the tail handle. ShotView.length has both requested_ms and frames, ready for #51 to record on the job.
  • Blocking. With no length set, if the Lines plus handles run past 15 s, the Shot can't be queued. Setting a length lifts the block. The block offers a split at Line boundaries, packing Lines greedily so each part keeps both handles. If one Line or one dual dialogue pair can't fit a Shot with its handles, the block shows its own message instead. Both messages offer setting the length. Queuing doesn't exist yet, so the block is available as ProjectSession::require_queueable_length for #51 to call, and in the view.
  • Split. split_shot(shot, starts) is one undoable edit. The original Shot row becomes the first part, so its Takes stay there. The new parts are Shots in the same Setup (12B·1, 12B·2). They keep the aspect ratio override and drop any length override.
  • Aspect ratio override. Each Shot can override the Project's aspect ratio. ShotView.aspect_ratio is the ratio in effect.
  • Schema. Migration V13 adds shot.aspect_ratio and shot.length_override_ms.
  • UI. Each Shot row in the Setups block shows its length and frame count, a seconds box for the override, and an aspect ratio picker. A blocked Shot also shows the block message and a "Split into N shots" button.

Judgement calls

  • Handles are 0.5 s each. The spec gives no value.
  • Estimate rates and handles are constants for now. The spec wants rates per Project; they can move onto the project row when the Animatic (#61) needs to edit them.
  • A dual dialogue pair counts as one unit that lasts as long as its longer half.

Known follow-ups (not in #41)

  • Splitting renumbers the other Shots in the Setup, because Shots are numbered in script order (behaviour from #40). For example, 12B·2 can become 12B·3.
  • Undoing a split, like undoing "Add shot", hard-deletes the added rows. Once Takes exist (#51), both need an ADR-0004 guard.

Tests

  • shot_length unit tests: estimates, frame-grid rounding, clamping, handle squeeze, the override floor, the split plan, dual dialogue units, and both block messages.
  • tests/setups.rs: length in the view, the override (clamped, undoable), the aspect ratio override, blocking, split (single and multi-part, Shot id kept, undo/redo), and refused split points.
  • The Tauri smoke test covers the new commands. bun tests cover the caption and seconds helpers.
  • cargo test --workspace --all-features, cargo clippy, bun test src and bun run check all pass.
Closes #41. Part of #24. ## What - **Shot length.** The length comes from the Lines' text estimate (dialogue 2.5 words/s plus 0.5 s per parenthetical; action 1.5 words/s, at least 1 s) plus a 0.5 s head and a 0.5 s tail handle, kept within 2–15 s. A length you set is the Shot's length, clamped to 2–15 s, whatever the estimate says. - **Frame grid.** Lengths round up to H3's grid: 5 + 17k frames at 24 fps, at most 362. Extra frames go to the tail handle. `ShotView.length` has both `requested_ms` and `frames`, ready for #51 to record on the job. - **Blocking.** With no length set, if the Lines plus handles run past 15 s, the Shot can't be queued. Setting a length lifts the block. The block offers a split at Line boundaries, packing Lines greedily so each part keeps both handles. If one Line or one dual dialogue pair can't fit a Shot with its handles, the block shows its own message instead. Both messages offer setting the length. Queuing doesn't exist yet, so the block is available as `ProjectSession::require_queueable_length` for #51 to call, and in the view. - **Split.** `split_shot(shot, starts)` is one undoable edit. The original Shot row becomes the first part, so its Takes stay there. The new parts are Shots in the same Setup (`12B·1`, `12B·2`). They keep the aspect ratio override and drop any length override. - **Aspect ratio override.** Each Shot can override the Project's aspect ratio. `ShotView.aspect_ratio` is the ratio in effect. - **Schema.** Migration V13 adds `shot.aspect_ratio` and `shot.length_override_ms`. - **UI.** Each Shot row in the Setups block shows its length and frame count, a seconds box for the override, and an aspect ratio picker. A blocked Shot also shows the block message and a "Split into N shots" button. ## Judgement calls - **Handles** are 0.5 s each. The spec gives no value. - **Estimate rates and handles** are constants for now. The spec wants rates per Project; they can move onto the project row when the Animatic (#61) needs to edit them. - **A dual dialogue pair** counts as one unit that lasts as long as its longer half. ## Known follow-ups (not in #41) - Splitting renumbers the other Shots in the Setup, because Shots are numbered in script order (behaviour from #40). For example, `12B·2` can become `12B·3`. - Undoing a split, like undoing "Add shot", hard-deletes the added rows. Once Takes exist (#51), both need an ADR-0004 guard. ## Tests - `shot_length` unit tests: estimates, frame-grid rounding, clamping, handle squeeze, the override floor, the split plan, dual dialogue units, and both block messages. - `tests/setups.rs`: length in the view, the override (clamped, undoable), the aspect ratio override, blocking, split (single and multi-part, Shot id kept, undo/redo), and refused split points. - The Tauri smoke test covers the new commands. bun tests cover the caption and seconds helpers. - `cargo test --workspace --all-features`, `cargo clippy`, `bun test src` and `bun run check` all pass.
A Shot's length is derived from its Lines (text estimate: dialogue 2.5
words/s plus 0.5 s per parenthetical, action 1.5 words/s with a 1 s
minimum) plus 0.5 s head and tail handles, within 2-15 s, or from an
override clamped to 2-15 s. Lengths round up to H3's 5 + 17k frame grid
(max 362 at 24 fps) and the extra frames become tail handle.

Lines past 15 s block queuing with an offered split at Line boundaries;
split_shot keeps the Shot as the first part so its Takes stay there. A
Line or dual dialogue pair past 15 s on its own blocks with its own
message. A per-Shot aspect ratio override sets the effective ratio.
An override never cuts the Lines: the requested length is at least the
Lines' time. Squeezed slack comes off the head, and the grid's extra
frames always go to the tail. Estimate rates are named constants, the
15 s limit in messages comes from MAX_SHOT_MS, and check_run and the
split share the read-only and dual dialogue checks.
A set length is the Shot's length: it is never raised to the Lines'
estimate and it lifts the block. Without one, the block looks at the
Lines plus handles, and a Line that cannot fit a Shot with its handles
gets its own message. Both messages now offer setting the length.
crowmaki deleted branch issue-41-shot-length 2026-10-08 06:57:57 +00:00
Sign in to join this conversation.
No description provided.