Take extension: Shots past 15 s by seamless continuation #140

Open
opened 2026-10-10 01:53:34 +00:00 by crowmaki · 0 comments
Owner

Problem Statement

H3 renders at most 15 seconds (362 frames) in one generation, so today a Shot can be at most 15 seconds. A filmmaker who wants a long, unbroken take has to split the Shot into several Shots of one Setup, and each part is a separate generation. The parts don't match at their boundaries: the picture jumps, the sound jumps, and the editor has to hide each join with a cut that the scene never asked for. A single Line or dual dialogue pair that runs past 15 seconds can't be queued at all. The length check tells the user to "rewrite it shorter, set the shot's length or wait for Take extension".

The slice spec (#24) deferred this as Take extension (seamless continuation with overlap). It reserved the extends kind of take_link for it, and ADR-0004 kept provenance readable so that extension can walk old chains of Takes.

Solution

A Shot may now run past 15 seconds. A long Shot is still rendered one H3 generation at a time, as a chain of Takes.

  • The first Take of a long Shot renders a first segment of up to 15 seconds.
  • Extending a rendered Take queues a new Take of the same Shot. Its new segment is guided by the source Take's last few frames and their audio (the overlap), so it continues the same moment. It then plays on through the Shot's next Lines.
  • The new Take's Renditions are the whole joined clip: the source's frames up to the overlap, the overlap blended across, then the new frames, with the audio joined the same way. The join is invisible. Dailies, the Animatic, Promotion, Bounce and the Edit package all see one continuous Take, never two clips with a cut.

The extension gets its own Take number and is linked extends to its source. The user can therefore seed-hunt a segment: extend 12A-3 three times, get 12A-4, 12A-5 and 12A-6, then circle the best one. A Take that does not yet cover all of its Shot's Lines is partial. The Animatic plays it over the Lines it covers and plays the Board for the rest, as it already does for a Take whose Shot has grown. "Queue to the end" queues the whole chain in one action. Each segment waits for the one before it, and a Take that covers the whole Shot comes out at the end.

User Stories

Long Shots

  1. As a filmmaker, I want a Shot to be longer than 15 seconds, so that one camera setup can hold an unbroken take for as long as the scene needs.
  2. As a filmmaker, I want a Shot whose Lines and handles run past 15 seconds to no longer be blocked from queuing, so that I am not forced to split it.
  3. As a filmmaker, I want a single Line or a dual dialogue pair longer than 15 seconds to be queueable, so that a long speech is no longer impossible.
  4. As a filmmaker, I want a Shot's length override to accept values past 15 seconds, so that I can hold a long Shot past its Lines.
  5. As a filmmaker, I want the Shot's length readout to show how many segments the Shot will take, and roughly where each one starts and ends, so that I know what rendering it will cost.
  6. As a filmmaker, I want splitting a long Shot to stay available as a manual action, not as a block, so that I can still choose real cuts when I want them.
  7. As a filmmaker, I want the existing "Split" suggestion for a long Shot to be offered alongside extending it, so that the choice between a cut and a continuous take is mine.

First segment

  1. As a filmmaker, I want queuing a Take of a long Shot to render the first segment (up to 15 s: head handle plus the Lines that fit), so that I can judge it before I spend GPU time on the rest.
  2. As a filmmaker, I want the first segment to end on a Line boundary when one falls in a sensible place, so that each segment's prompt describes whole Lines.
  3. As a filmmaker, I want a Line too long for one segment to break inside the Line, so that a long speech can span segments.
  4. As a filmmaker, I want a Take that covers only some of its Shot's Lines to be marked partial, with what it covers (for example "covers 3 of 7 Lines · 14.2 of 31 s"), so that I can tell finished Takes from ones still to extend.

Extending a Take

  1. As a filmmaker, I want an "Extend" action on any rendered partial Take in Dailies, so that I can continue the attempt I like best.
  2. As a filmmaker, I want to choose draft or Single-pass final when I extend, as when I queue a Take, so that I control cost.
  3. As a filmmaker, I want each extension to get a fresh seed by default, with "same seed" available, so that I can seed-hunt the next segment.
  4. As a filmmaker, I want to extend the same source Take several times, so that I can compare several continuations and circle the best.
  5. As a filmmaker, I want to extend an extension, so that a chain of segments reaches the end of a Shot of any length.
  6. As a filmmaker, I want the extension to use the Shot's current inputs (references, Board, prompt, framing, Performance, Generation profile), so that changes I made since the source still apply to the new segment.
  7. As a filmmaker, I want the overlap length to be a Project setting, picked from H3's frame grid (5, 22, 39 or 56 frames, default 22), and changeable when I extend, so that I can trade continuity strength against new material.
  8. As a filmmaker, I want the overlap to guide both picture and audio, so that motion, lighting, voices and Ambience carry across the join.
  9. As a filmmaker, I want the extension's new segment to cover the Shot's next Lines, up to what fits in 15 s after the overlap, so that each extension moves the scene forward.
  10. As a filmmaker, I want the new segment's prompt to describe only what happens in that segment (its Lines and the matching part of the action text, or the rest of a long Line), so that H3 does not replay earlier action.
  11. As a filmmaker, I want the composed segment prompt to be visible before I extend, and overridable for that one extension, so that I can steer a difficult continuation.
  12. As a filmmaker, I want an Extend on a Take whose source is still queued or rendering to wait for it, not fail, so that I can line up work ahead.
  13. As a filmmaker, I want "Queue to the end" on a long Shot and on a partial Take, so that one action renders a full-length Take without me babysitting each segment.
  14. As a filmmaker, I want a failed or cancelled segment in a queued chain to cancel the segments waiting on it, with a clear note, so that the queue never holds work that cannot run.

One continuous Take

  1. As a filmmaker, I want an extension's draft and final Renditions to be the whole joined clip from the Shot's start, so that I always review, circle and export one continuous take.
  2. As a filmmaker, I want the picture across the overlap blended evenly between the source and the new segment, and the audio joined at the overlap, so that no frame or sound repeats or jumps.
  3. As a filmmaker, I want the joined clip to carry its Line marks across all its segments, so that the Animatic and Bounce follow its real timing.
  4. As a filmmaker, I want the joining done in Finishing on the CPU, not on the GPU, so that a long chain does not re-render frames that already exist.
  5. As a filmmaker, I want a Take's poster, proxy and ProRes master made from the joined clip, so that every place in the app shows the whole Take.

Dailies

  1. As a filmmaker, I want an extension to show what it extends ("extends 12A-3") and to jump to it, so that I can follow a chain.
  2. As a filmmaker, I want Dailies to fold a source Take under its extensions by default, with a toggle to show every partial Take, so that the coverage wall is not cluttered by intermediate segments.
  3. As a filmmaker, I want screening to start an extension at the overlap, with a "from start" option, so that I review only new material when I seed-hunt.
  4. As a filmmaker, I want the details panel to list each segment of a Take with its own seed, Generation profile and recorded inputs, so that every segment's provenance is readable.
  5. As a filmmaker, I want to mark an intermediate Take NG once an extension supersedes it, without breaking the extension, so that review stays tidy.
  6. As a filmmaker, I want circling to work on partial Takes too, so that I can circle a good opening while the rest is still rendering.

Promotion and finals

  1. As a filmmaker, I want promoting a draft extension to produce a joined final whose overlap is guided by the source's final, so that the final join is as seamless as the draft join.
  2. As a filmmaker, I want promoting an extension whose source has only a draft to queue the source's Promotion first, with the extension's Promotion waiting on it, so that I never hand-sequence finals.
  3. As a filmmaker, I want a Single-pass final extension to require (or first queue) a final of its source, so that a final never joins onto draft frames.
  4. As a filmmaker, I want a re-promotion of a source with a new refine seed to make its extensions stale, so that I am not shown a joined final whose overlap no longer matches.

Staleness and re-rolls

  1. As a filmmaker, I want an extension to be stale when its own segment's inputs changed, so that staleness works as it does for any Take.
  2. As a filmmaker, I want an extension to be stale when its source is stale, with a reason that names the source and the source's own reasons, so that I know the early part of the clip is out of date.
  3. As a filmmaker, I want a new Stale reason group, Extension, for "Source re-promoted" and "Source stale", so that I can tell these reasons from the segment's own.
  4. As a filmmaker, I want to accept an Extension reason like any other, so that I can keep a Take whose source changed harmlessly.
  5. As a filmmaker, I want "Same take, new seed" on an extension to roll a new extension of the same source, so that only the last segment is re-rolled.
  6. As a filmmaker, I want re-rolling a stale extension whose source is stale to re-roll the chain from the earliest stale segment, so that the new Take is fully current.
  7. As a filmmaker, I want "Re-roll stale circled Takes" to handle chained Takes in the same way, so that batch re-rolls of long Shots work.
  8. As a filmmaker, I want restoring a purged extension to keep its source link and seed, and to restore its source first if the source was purged too, so that Restore brings back the same clip.

Animatic, Performance and Bounce

  1. As a filmmaker, I want the Animatic to play a circled partial Take over the Lines it covers and the Board for the rest, so that the rough cut stays complete while a chain is unfinished.
  2. As a filmmaker, I want a full-length extension to play in the Animatic as one event over all of its Shot's Lines, so that a long take reads as one shot.
  3. As a filmmaker, I want an extension over Lines a Performance covers to be sent its Performance slice for the new segment, with the overlap audio taken from the source, so that long Shots keep the locked timing.
  4. As a filmmaker, I want the Performance straddle rule to apply to the whole Shot, not to each segment, so that a long Shot still sits wholly inside or wholly outside the Performance.
  5. As a filmmaker, I want Bounce to read the joined clip like any other circled Take, so that long takes bounce without doubled audio.

Edit package

  1. As an editor, I want one clip per extension Take, holding the whole joined take, so that I cut long takes as single clips.
  2. As an editor, I want the metadata CSV to show what a Take extends and its segment count, so that I can understand a chain in Resolve.
  3. As an editor, I want the Animatic timeline in the Edit package to place a full-length extension as one clip, so that the exported rough cut matches the app.

Storage

  1. As a filmmaker, I want Storage to show that the joined Renditions of a chain repeat frames, and how much space removing intermediate Takes would really free, so that I can reclaim space safely.
  2. As a filmmaker, I want "Suggest cleanup" to tick the Renditions of intermediate partial Takes that a circled extension supersedes, so that long chains don't pile up.
  3. As a filmmaker, I want purging a source's Renditions to leave its extensions playable, so that cleaning up intermediates never breaks a circled Take.
  4. As a filmmaker, I want Promotion of an extension whose source final is purged to say so and offer to restore the source, so that the failure is explained.

Implementation Decisions

Domain language

Update CONTEXT.md as part of this work:

  • Shot: no longer "at most 15 seconds". It is one continuous segment of a Setup's coverage of any length. A Shot past one segment is rendered by Take extension.
  • New terms:
    • Segment: one H3 generation of at most 15 s within a Take.
    • Extension (a Take that extends another): a new Take of the same Shot that continues a rendered source Take. Its Renditions are the joined clip.
    • Overlap: the source's last frames and audio that guide the new segment.
    • Partial take: a Take that covers only a leading run of its Shot's Lines.
  • Shot splitting stays. When a Shot is split, its Takes (partial or full) stay on the first part and go stale through the existing Framing and Lines reasons.

Shot length

  • The 15 s cap and the TooLong and LineTooLong blocks go. A Shot's length estimate now gives a segment plan: the first segment is head handle plus Lines up to 15 s. Each later segment is overlap plus Lines up to 15 s. The last segment ends with the tail handle. Every segment rounds to H3's frame grid (5 + 17k frames, at most 362).
  • A segment ends at the last Line boundary that fits. A unit longer than a segment breaks inside it. With a Performance, it breaks by time on the forced audio. Without a Performance, it breaks at a word boundary estimated from the Project's reading rates, and the next segment's prompt quotes the rest of the Line.
  • StraddlesPerformance still blocks, judged for the whole Shot.
  • The plan is advisory. The real boundary of each extension follows the source Take's actual length and Line marks, not the estimate.

Take model and provenance

  • An extension is an ordinary Take with its own number, kind (draft or Single-pass final), seed and Generation profile. It has a take_link of kind extends to its source Take, the first use of the reserved kind. A Take extends at most one source, and a source can have any number of extensions.
  • The Take records, as take_input rows, the source Take and the exact source Rendition the overlap was cut from, and the overlap length in frames. It also records the segment's own inputs: its Lines (or Line part), composed or overridden segment prompt, slot assignment, Board, Performance slice and so on.
  • The Take records its coverage: the Lines it covers from the Shot's start, and its Line marks across the joined clip. The marks are the source's marks before the overlap plus the new segment's marks offset into the joined timeline.
  • Re-rolling an extension ("same take, new seed") keeps its source and records rerolled_from as today. Restore keeps the seed and source.
  • Queuing stays append-only and is not undoable, as today.

Jobs and shipped workflows

  • New shipped workflows (ADR-0002) for a guided H3 segment: draft, Single-pass final and Promotion variants. They load the overlap frames and overlap audio and guide them at frame 0 with MiniMaxH3AddGuide, as the reference workflow in scratch/ does. They render only the new segment and save its latents for Promotion. Each has a manifest with bindings for the overlap inputs, and the class types are added to preflight.
  • The job builder gains an extension request. It cuts the overlap frames and audio from the source Rendition, then builds the segment job from the Shot's current inputs restricted to the segment, with the overlap in place of the head handle. A start Keyframe is not sent to an extension segment, because the overlap replaces it, and it is shown as not sent. Mid and end Keyframes and the Board are sent as usual.
  • A job may wait on another Take's Rendition. An extension or extension Promotion whose source is not rendered yet waits in the queue, like a Not-ready workflow. If its source fails, is cancelled, or loses its Rendition, the waiting job is cancelled with a note. This gives "Queue to the end" and Promotion chaining.
  • Queue ordering is unchanged otherwise. A chain's segments are ordinary draft or final jobs.

Joining (Finishing)

  • Finishing gains a join step that runs on the CPU post-step lane before poster, timecode and proxy:
    • Picture: the source's frames before the overlap, then the overlap blended 50/50 between the source and the new segment, then the new segment after the overlap.
    • Audio: the source's audio before the overlap, then the segment's audio from the overlap on.
  • The joined output is the Rendition. A Rendition records its segment output separately, so Promotion and Storage can use it.
  • A draft extension joins onto its source's draft. A final joins onto its source's final.

Promotion

  • Promoting an extension refines its segment latent at final size and re-guides the overlap from the source's final. If the source has no final, the source's Promotion is queued and the extension's waits on it. If the source's final is purged, Promotion is blocked with an offer to Restore the source.
  • Re-promoting a source in place leaves extensions joined onto the old final, and they become stale with "Source re-promoted".

Staleness

  • A new Stale reason group, Extension:
    • "Source re-promoted": the recorded source Rendition is no longer the source's current final or draft.
    • "Source stale": the source Take is stale. This carries the source's own reasons.
  • The segment's own reasons are computed as for any Take against the Shot's current inputs for that segment.
  • Accepting a reason works as today.
  • A batch re-roll of a stale chained Take re-rolls from the earliest stale Take in its chain. Every Take it creates extends the one before it, ending in a new Take that covers what the old one covered.

Animatic, Bounce and Edit package

  • The Animatic's played Take already plays over the units it covers and plays the Board for the rest. Partial Takes use that path, with coverage from the Take's joined Line marks.
  • Bounce and the Edit package treat a joined Rendition like any other.
  • The metadata CSV gains "Extends" and "Segments" columns.

Dailies UI

  • Actions: "Extend" (opens a dialog with draft or final, seed, overlap length and a segment prompt preview with a one-off override), and "Queue to the end".
  • Chain display: a "partial" badge with coverage, an "extends" link, and folding of superseded partial Takes behind a toggle.
  • Screening starts an extension at its overlap.
  • The details panel lists segments.

Storage

  • Storage attributes the joined Rendition's size to the Take that owns it. "Suggest cleanup" ticks intermediate partial Takes superseded by a circled extension.
  • Purging a source does not affect an extension's already-joined Renditions. It only blocks that extension's future Promotion or Restore until the source is restored.

Testing Decisions

  • Good tests drive the public studio-core ProjectSession API only. They queue and extend Takes, run the RenderWorker against FakeComfy, and assert on what the app shows: Take views, coverage, links, Stale reasons, queue state, Animatic events, Edit package files, and Storage rows. They never assert on SQL rows or private helpers.
  • One seam: the ProjectSession API with FakeComfy + RenderWorker + real ffmpeg. FakeComfy learns the new segment workflows: it emits a segment of the requested frame count, with distinguishable frames (for example a brightness ramp) so the join can be checked.
  • Modules and behaviours covered:
    • Shot length and segment plan: long Shots no longer block, long Lines break across segments, the straddle rule still applies, and grid rounding.
    • Extension queuing: the extends link, recorded source Rendition and overlap, segment prompt and slots, the start Keyframe not sent, and waiting on an unrendered source with cancellation on source failure.
    • Joining: the joined Rendition length equals the source length minus the overlap plus the segment length. A frame sample before, inside and after the overlap matches the expected source, blend and segment. Audio length matches, and Line marks are offset correctly.
    • Promotion chaining, re-promotion staleness, and Extension Stale reasons, including inherited "Source stale" and accepting a reason.
    • Re-roll and batch re-roll of chains, and Restore of a purged extension.
    • The Animatic with partial and full extensions, Bounce over a joined Take, and the Edit package CSV columns and single clip.
    • Storage suggestions and purge safety.
  • Prior art:
    • Take-frame Keyframe tests: real ffmpeg, ramp clips, and frame sampling.
    • Animatic tests over circled Takes and Line marks.
    • The Promotion, staleness, stale re-roll and Performance-driven Take tests.
    • The Edit package and Storage tests.
  • Frontend: pure helpers (coverage labels, chain folding) get bun test files beside them, as the Dailies frame-keyframe helper does.

Out of Scope

  • Extending into a different Shot or Setup. Continuity across a cut stays with take-frame Keyframes and frame_from.
  • Extending backwards (prepending before a Take's start).
  • Re-rendering an earlier segment inside a chain in place. Re-rolling makes new Takes instead.
  • Automatic seed-hunting (rendering several extensions and picking one).
  • A per-segment Board or Keyframe set. Segments share the Shot's Board and Keyframes.
  • Takes with internal cuts ([Shot 2] blocks), which stay deferred as in #24.
  • A render daemon that runs while the app is closed.

Further Notes

  • The reference ComfyUI graph for continuation (overlap frames on the 5 + 17k grid, MiniMaxH3AddGuide at index 0 with image and audio, 0.5 blend over the overlap, audio trimmed and concatenated) is in scratch/ as the SEEDHUNTER v25 workflow. It is a starting point for the shipped workflows and has not yet been confirmed by running it in ComfyUI. Its exact overlap-blending and audio-join behaviour must be confirmed against real H3 output before the shipped workflows are frozen.
  • Re-guiding the overlap during Promotion from the source's final has not been confirmed yet. It depends on the latent-reuse findings in #14.
  • This builds on #24's provenance decisions (take_link kinds and ADR-0004) and on the Shot length rules from #41.
## Problem Statement H3 renders at most 15 seconds (362 frames) in one generation, so today a Shot can be at most 15 seconds. A filmmaker who wants a long, unbroken take has to split the Shot into several Shots of one Setup, and each part is a separate generation. The parts don't match at their boundaries: the picture jumps, the sound jumps, and the editor has to hide each join with a cut that the scene never asked for. A single Line or dual dialogue pair that runs past 15 seconds can't be queued at all. The length check tells the user to "rewrite it shorter, set the shot's length or wait for Take extension". The slice spec (#24) deferred this as **Take extension** (seamless continuation with overlap). It reserved the `extends` kind of `take_link` for it, and ADR-0004 kept provenance readable so that extension can walk old chains of Takes. ## Solution A Shot may now run past 15 seconds. A long Shot is still rendered one H3 generation at a time, as a chain of Takes. - The first Take of a long Shot renders a first **segment** of up to 15 seconds. - **Extending** a rendered Take queues a new Take of the *same* Shot. Its new segment is guided by the source Take's last few frames and their audio (the **overlap**), so it continues the same moment. It then plays on through the Shot's next Lines. - The new Take's Renditions are the **whole joined clip**: the source's frames up to the overlap, the overlap blended across, then the new frames, with the audio joined the same way. The join is invisible. Dailies, the Animatic, Promotion, Bounce and the Edit package all see one continuous Take, never two clips with a cut. The extension gets its own Take number and is linked `extends` to its source. The user can therefore seed-hunt a segment: extend `12A-3` three times, get `12A-4`, `12A-5` and `12A-6`, then circle the best one. A Take that does not yet cover all of its Shot's Lines is **partial**. The Animatic plays it over the Lines it covers and plays the Board for the rest, as it already does for a Take whose Shot has grown. "Queue to the end" queues the whole chain in one action. Each segment waits for the one before it, and a Take that covers the whole Shot comes out at the end. ## User Stories ### Long Shots 1. As a filmmaker, I want a Shot to be longer than 15 seconds, so that one camera setup can hold an unbroken take for as long as the scene needs. 2. As a filmmaker, I want a Shot whose Lines and handles run past 15 seconds to no longer be blocked from queuing, so that I am not forced to split it. 3. As a filmmaker, I want a single Line or a dual dialogue pair longer than 15 seconds to be queueable, so that a long speech is no longer impossible. 4. As a filmmaker, I want a Shot's length override to accept values past 15 seconds, so that I can hold a long Shot past its Lines. 5. As a filmmaker, I want the Shot's length readout to show how many segments the Shot will take, and roughly where each one starts and ends, so that I know what rendering it will cost. 6. As a filmmaker, I want splitting a long Shot to stay available as a manual action, not as a block, so that I can still choose real cuts when I want them. 7. As a filmmaker, I want the existing "Split" suggestion for a long Shot to be offered alongside extending it, so that the choice between a cut and a continuous take is mine. ### First segment 8. As a filmmaker, I want queuing a Take of a long Shot to render the first segment (up to 15 s: head handle plus the Lines that fit), so that I can judge it before I spend GPU time on the rest. 9. As a filmmaker, I want the first segment to end on a Line boundary when one falls in a sensible place, so that each segment's prompt describes whole Lines. 10. As a filmmaker, I want a Line too long for one segment to break inside the Line, so that a long speech can span segments. 11. As a filmmaker, I want a Take that covers only some of its Shot's Lines to be marked partial, with what it covers (for example "covers 3 of 7 Lines · 14.2 of 31 s"), so that I can tell finished Takes from ones still to extend. ### Extending a Take 12. As a filmmaker, I want an "Extend" action on any rendered partial Take in Dailies, so that I can continue the attempt I like best. 13. As a filmmaker, I want to choose draft or Single-pass final when I extend, as when I queue a Take, so that I control cost. 14. As a filmmaker, I want each extension to get a fresh seed by default, with "same seed" available, so that I can seed-hunt the next segment. 15. As a filmmaker, I want to extend the same source Take several times, so that I can compare several continuations and circle the best. 16. As a filmmaker, I want to extend an extension, so that a chain of segments reaches the end of a Shot of any length. 17. As a filmmaker, I want the extension to use the Shot's current inputs (references, Board, prompt, framing, Performance, Generation profile), so that changes I made since the source still apply to the new segment. 18. As a filmmaker, I want the overlap length to be a Project setting, picked from H3's frame grid (5, 22, 39 or 56 frames, default 22), and changeable when I extend, so that I can trade continuity strength against new material. 19. As a filmmaker, I want the overlap to guide both picture and audio, so that motion, lighting, voices and Ambience carry across the join. 20. As a filmmaker, I want the extension's new segment to cover the Shot's next Lines, up to what fits in 15 s after the overlap, so that each extension moves the scene forward. 21. As a filmmaker, I want the new segment's prompt to describe only what happens in that segment (its Lines and the matching part of the action text, or the rest of a long Line), so that H3 does not replay earlier action. 22. As a filmmaker, I want the composed segment prompt to be visible before I extend, and overridable for that one extension, so that I can steer a difficult continuation. 23. As a filmmaker, I want an Extend on a Take whose source is still queued or rendering to wait for it, not fail, so that I can line up work ahead. 24. As a filmmaker, I want "Queue to the end" on a long Shot and on a partial Take, so that one action renders a full-length Take without me babysitting each segment. 25. As a filmmaker, I want a failed or cancelled segment in a queued chain to cancel the segments waiting on it, with a clear note, so that the queue never holds work that cannot run. ### One continuous Take 26. As a filmmaker, I want an extension's draft and final Renditions to be the whole joined clip from the Shot's start, so that I always review, circle and export one continuous take. 27. As a filmmaker, I want the picture across the overlap blended evenly between the source and the new segment, and the audio joined at the overlap, so that no frame or sound repeats or jumps. 28. As a filmmaker, I want the joined clip to carry its Line marks across all its segments, so that the Animatic and Bounce follow its real timing. 29. As a filmmaker, I want the joining done in Finishing on the CPU, not on the GPU, so that a long chain does not re-render frames that already exist. 30. As a filmmaker, I want a Take's poster, proxy and ProRes master made from the joined clip, so that every place in the app shows the whole Take. ### Dailies 31. As a filmmaker, I want an extension to show what it extends ("extends 12A-3") and to jump to it, so that I can follow a chain. 32. As a filmmaker, I want Dailies to fold a source Take under its extensions by default, with a toggle to show every partial Take, so that the coverage wall is not cluttered by intermediate segments. 33. As a filmmaker, I want screening to start an extension at the overlap, with a "from start" option, so that I review only new material when I seed-hunt. 34. As a filmmaker, I want the details panel to list each segment of a Take with its own seed, Generation profile and recorded inputs, so that every segment's provenance is readable. 35. As a filmmaker, I want to mark an intermediate Take NG once an extension supersedes it, without breaking the extension, so that review stays tidy. 36. As a filmmaker, I want circling to work on partial Takes too, so that I can circle a good opening while the rest is still rendering. ### Promotion and finals 37. As a filmmaker, I want promoting a draft extension to produce a joined final whose overlap is guided by the source's final, so that the final join is as seamless as the draft join. 38. As a filmmaker, I want promoting an extension whose source has only a draft to queue the source's Promotion first, with the extension's Promotion waiting on it, so that I never hand-sequence finals. 39. As a filmmaker, I want a Single-pass final extension to require (or first queue) a final of its source, so that a final never joins onto draft frames. 40. As a filmmaker, I want a re-promotion of a source with a new refine seed to make its extensions stale, so that I am not shown a joined final whose overlap no longer matches. ### Staleness and re-rolls 41. As a filmmaker, I want an extension to be stale when its own segment's inputs changed, so that staleness works as it does for any Take. 42. As a filmmaker, I want an extension to be stale when its source is stale, with a reason that names the source and the source's own reasons, so that I know the early part of the clip is out of date. 43. As a filmmaker, I want a new Stale reason group, **Extension**, for "Source re-promoted" and "Source stale", so that I can tell these reasons from the segment's own. 44. As a filmmaker, I want to accept an Extension reason like any other, so that I can keep a Take whose source changed harmlessly. 45. As a filmmaker, I want "Same take, new seed" on an extension to roll a new extension of the same source, so that only the last segment is re-rolled. 46. As a filmmaker, I want re-rolling a stale extension whose source is stale to re-roll the chain from the earliest stale segment, so that the new Take is fully current. 47. As a filmmaker, I want "Re-roll stale circled Takes" to handle chained Takes in the same way, so that batch re-rolls of long Shots work. 48. As a filmmaker, I want restoring a purged extension to keep its source link and seed, and to restore its source first if the source was purged too, so that Restore brings back the same clip. ### Animatic, Performance and Bounce 49. As a filmmaker, I want the Animatic to play a circled partial Take over the Lines it covers and the Board for the rest, so that the rough cut stays complete while a chain is unfinished. 50. As a filmmaker, I want a full-length extension to play in the Animatic as one event over all of its Shot's Lines, so that a long take reads as one shot. 51. As a filmmaker, I want an extension over Lines a Performance covers to be sent its Performance slice for the new segment, with the overlap audio taken from the source, so that long Shots keep the locked timing. 52. As a filmmaker, I want the Performance straddle rule to apply to the whole Shot, not to each segment, so that a long Shot still sits wholly inside or wholly outside the Performance. 53. As a filmmaker, I want Bounce to read the joined clip like any other circled Take, so that long takes bounce without doubled audio. ### Edit package 54. As an editor, I want one clip per extension Take, holding the whole joined take, so that I cut long takes as single clips. 55. As an editor, I want the metadata CSV to show what a Take extends and its segment count, so that I can understand a chain in Resolve. 56. As an editor, I want the Animatic timeline in the Edit package to place a full-length extension as one clip, so that the exported rough cut matches the app. ### Storage 57. As a filmmaker, I want Storage to show that the joined Renditions of a chain repeat frames, and how much space removing intermediate Takes would really free, so that I can reclaim space safely. 58. As a filmmaker, I want "Suggest cleanup" to tick the Renditions of intermediate partial Takes that a circled extension supersedes, so that long chains don't pile up. 59. As a filmmaker, I want purging a source's Renditions to leave its extensions playable, so that cleaning up intermediates never breaks a circled Take. 60. As a filmmaker, I want Promotion of an extension whose source final is purged to say so and offer to restore the source, so that the failure is explained. ## Implementation Decisions ### Domain language Update CONTEXT.md as part of this work: - **Shot**: no longer "at most 15 seconds". It is one continuous segment of a Setup's coverage of any length. A Shot past one segment is rendered by Take extension. - New terms: - **Segment**: one H3 generation of at most 15 s within a Take. - **Extension** (a Take that extends another): a new Take of the same Shot that continues a rendered source Take. Its Renditions are the joined clip. - **Overlap**: the source's last frames and audio that guide the new segment. - **Partial take**: a Take that covers only a leading run of its Shot's Lines. - Shot splitting stays. When a Shot is split, its Takes (partial or full) stay on the first part and go stale through the existing Framing and Lines reasons. ### Shot length - The 15 s cap and the `TooLong` and `LineTooLong` blocks go. A Shot's length estimate now gives a **segment plan**: the first segment is head handle plus Lines up to 15 s. Each later segment is overlap plus Lines up to 15 s. The last segment ends with the tail handle. Every segment rounds to H3's frame grid (5 + 17k frames, at most 362). - A segment ends at the last Line boundary that fits. A unit longer than a segment breaks inside it. With a Performance, it breaks by time on the forced audio. Without a Performance, it breaks at a word boundary estimated from the Project's reading rates, and the next segment's prompt quotes the rest of the Line. - `StraddlesPerformance` still blocks, judged for the whole Shot. - The plan is advisory. The real boundary of each extension follows the source Take's actual length and Line marks, not the estimate. ### Take model and provenance - An extension is an ordinary Take with its own number, kind (draft or Single-pass final), seed and Generation profile. It has a `take_link` of kind `extends` to its source Take, the first use of the reserved kind. A Take extends at most one source, and a source can have any number of extensions. - The Take records, as `take_input` rows, the source Take and the exact source Rendition the overlap was cut from, and the overlap length in frames. It also records the segment's own inputs: its Lines (or Line part), composed or overridden segment prompt, slot assignment, Board, Performance slice and so on. - The Take records its **coverage**: the Lines it covers from the Shot's start, and its Line marks across the joined clip. The marks are the source's marks before the overlap plus the new segment's marks offset into the joined timeline. - Re-rolling an extension ("same take, new seed") keeps its source and records `rerolled_from` as today. Restore keeps the seed and source. - Queuing stays append-only and is not undoable, as today. ### Jobs and shipped workflows - New shipped workflows (ADR-0002) for a guided H3 segment: draft, Single-pass final and Promotion variants. They load the overlap frames and overlap audio and guide them at frame 0 with `MiniMaxH3AddGuide`, as the reference workflow in `scratch/` does. They render only the new segment and save its latents for Promotion. Each has a manifest with bindings for the overlap inputs, and the class types are added to preflight. - The job builder gains an extension request. It cuts the overlap frames and audio from the source Rendition, then builds the segment job from the Shot's current inputs restricted to the segment, with the overlap in place of the head handle. A start Keyframe is not sent to an extension segment, because the overlap replaces it, and it is shown as not sent. Mid and end Keyframes and the Board are sent as usual. - A job may **wait on another Take's Rendition**. An extension or extension Promotion whose source is not rendered yet waits in the queue, like a Not-ready workflow. If its source fails, is cancelled, or loses its Rendition, the waiting job is cancelled with a note. This gives "Queue to the end" and Promotion chaining. - Queue ordering is unchanged otherwise. A chain's segments are ordinary draft or final jobs. ### Joining (Finishing) - Finishing gains a **join** step that runs on the CPU post-step lane before poster, timecode and proxy: - Picture: the source's frames before the overlap, then the overlap blended 50/50 between the source and the new segment, then the new segment after the overlap. - Audio: the source's audio before the overlap, then the segment's audio from the overlap on. - The joined output is the Rendition. A Rendition records its segment output separately, so Promotion and Storage can use it. - A draft extension joins onto its source's draft. A final joins onto its source's final. ### Promotion - Promoting an extension refines its segment latent at final size and re-guides the overlap from the source's **final**. If the source has no final, the source's Promotion is queued and the extension's waits on it. If the source's final is purged, Promotion is blocked with an offer to Restore the source. - Re-promoting a source in place leaves extensions joined onto the old final, and they become stale with "Source re-promoted". ### Staleness - A new Stale reason group, **Extension**: - "Source re-promoted": the recorded source Rendition is no longer the source's current final or draft. - "Source stale": the source Take is stale. This carries the source's own reasons. - The segment's own reasons are computed as for any Take against the Shot's current inputs for that segment. - Accepting a reason works as today. - A batch re-roll of a stale chained Take re-rolls from the earliest stale Take in its chain. Every Take it creates extends the one before it, ending in a new Take that covers what the old one covered. ### Animatic, Bounce and Edit package - The Animatic's played Take already plays over the units it covers and plays the Board for the rest. Partial Takes use that path, with coverage from the Take's joined Line marks. - Bounce and the Edit package treat a joined Rendition like any other. - The metadata CSV gains "Extends" and "Segments" columns. ### Dailies UI - Actions: "Extend" (opens a dialog with draft or final, seed, overlap length and a segment prompt preview with a one-off override), and "Queue to the end". - Chain display: a "partial" badge with coverage, an "extends" link, and folding of superseded partial Takes behind a toggle. - Screening starts an extension at its overlap. - The details panel lists segments. ### Storage - Storage attributes the joined Rendition's size to the Take that owns it. "Suggest cleanup" ticks intermediate partial Takes superseded by a circled extension. - Purging a source does not affect an extension's already-joined Renditions. It only blocks that extension's future Promotion or Restore until the source is restored. ## Testing Decisions - Good tests drive the public `studio-core` `ProjectSession` API only. They queue and extend Takes, run the `RenderWorker` against `FakeComfy`, and assert on what the app shows: Take views, coverage, links, Stale reasons, queue state, Animatic events, Edit package files, and Storage rows. They never assert on SQL rows or private helpers. - One seam: the `ProjectSession` API with `FakeComfy` + `RenderWorker` + real ffmpeg. `FakeComfy` learns the new segment workflows: it emits a segment of the requested frame count, with distinguishable frames (for example a brightness ramp) so the join can be checked. - Modules and behaviours covered: - Shot length and segment plan: long Shots no longer block, long Lines break across segments, the straddle rule still applies, and grid rounding. - Extension queuing: the `extends` link, recorded source Rendition and overlap, segment prompt and slots, the start Keyframe not sent, and waiting on an unrendered source with cancellation on source failure. - Joining: the joined Rendition length equals the source length minus the overlap plus the segment length. A frame sample before, inside and after the overlap matches the expected source, blend and segment. Audio length matches, and Line marks are offset correctly. - Promotion chaining, re-promotion staleness, and Extension Stale reasons, including inherited "Source stale" and accepting a reason. - Re-roll and batch re-roll of chains, and Restore of a purged extension. - The Animatic with partial and full extensions, Bounce over a joined Take, and the Edit package CSV columns and single clip. - Storage suggestions and purge safety. - Prior art: - Take-frame Keyframe tests: real ffmpeg, ramp clips, and frame sampling. - Animatic tests over circled Takes and Line marks. - The Promotion, staleness, stale re-roll and Performance-driven Take tests. - The Edit package and Storage tests. - Frontend: pure helpers (coverage labels, chain folding) get `bun test` files beside them, as the Dailies frame-keyframe helper does. ## Out of Scope - Extending into a different Shot or Setup. Continuity across a cut stays with take-frame Keyframes and `frame_from`. - Extending backwards (prepending before a Take's start). - Re-rendering an earlier segment inside a chain in place. Re-rolling makes new Takes instead. - Automatic seed-hunting (rendering several extensions and picking one). - A per-segment Board or Keyframe set. Segments share the Shot's Board and Keyframes. - Takes with internal cuts (`[Shot 2]` blocks), which stay deferred as in #24. - A render daemon that runs while the app is closed. ## Further Notes - The reference ComfyUI graph for continuation (overlap frames on the 5 + 17k grid, `MiniMaxH3AddGuide` at index 0 with image and audio, 0.5 blend over the overlap, audio trimmed and concatenated) is in `scratch/` as the SEEDHUNTER v25 workflow. It is a starting point for the shipped workflows and has not yet been confirmed by running it in ComfyUI. Its exact overlap-blending and audio-join behaviour must be confirmed against real H3 output before the shipped workflows are frozen. - Re-guiding the overlap during Promotion from the source's final has not been confirmed yet. It depends on the latent-reuse findings in #14. - This builds on #24's provenance decisions (`take_link` kinds and ADR-0004) and on the Shot length rules from #41.
Sign in to join this conversation.
No description provided.