Complex Shots: Blender previz playblast as a video reference #139

Closed
opened 2026-10-10 00:21:37 +00:00 by crowmaki · 2 comments
Owner

Problem Statement

A Board tells H3 about staging, composition and camera movement with a few still Panels and Notation symbols. That works for simple Shots, but it isn't enough for Shots with complex staging: several subjects moving at once, or subject motion combined with a camera move. For those Shots H3 has to guess the timing and the paths through space, and the filmmaker re-rolls Takes again and again hoping one moves right. H3's Reference-to-Video node accepts up to three video references, but the app never sends one, so the filmmaker has no way to show H3 the exact motion and camera they want.

Solution

The filmmaker can mark a Shot as complex. A complex Shot shows a coloured dot on the storyboard (the Board timeline) and on the other Shot listings. The dot's colour shows how far its previz has got.

A complex Shot gets a Blender previz workflow. From the Shot, the filmmaker clicks "Open in Blender". The app builds a Blender scene for the Shot in a folder of its own: a camera at the Shot's aspect ratio and length, one flat-coloured proxy figure per subject, the Shot's Performance slice on the timeline (when a Performance drives it), Line markers, and the Board Panels and location angle as camera background references. The filmmaker animates the figures and the camera, then runs one "Playblast for AI Studio" action in Blender. That renders a flat-shaded, untextured video at the Shot's exact length into the Shot's folder.

The app notices the new playblast and attaches it to the Shot as a new previz version. The playblast then:

  • fills one of H3's video slots in the Shot's Slot list,
  • is named in the composed prompt as a motion and camera reference only, with each figure colour mapped to its subject ("Mara is the red figure in <Video 1>"),
  • replaces the Shot's Board in the Animatic until a Take is circled, and
  • counts toward staleness, so Takes made with an older playblast show a Stale reason.

User Stories

  1. As a filmmaker, I want to mark a Shot as complex, so that I can choose a heavier previz workflow for just the Shots that need it.
  2. As a filmmaker, I want to unmark a complex Shot, so that a Shot I flagged by mistake goes back to the plain Board workflow.
  3. As a filmmaker, I want marking and unmarking a Shot complex to be undoable, so that it behaves like every other authored edit.
  4. As a filmmaker, I want a coloured dot on each complex Shot in the Board timeline, so that I can see which Shots need previz while I storyboard.
  5. As a filmmaker, I want the same dot wherever Shots are listed (the Scenes view's Setups block, the Animatic's cut tracks, Dailies), so that complex Shots are recognisable everywhere, like the over-budget badge.
  6. As a filmmaker, I want the dot's colour to tell me whether the Shot has no playblast yet, has a current playblast, or has a playblast that no longer matches the Shot's length or aspect ratio, so that I can see previz progress at a glance.
  7. As a filmmaker, I want the dot's tooltip to say what its colour means, so that I don't have to memorise the colours.
  8. As a filmmaker, I want Shots that aren't complex to show no dot, so that the storyboard stays uncluttered.
  9. As a filmmaker, I want an "Open in Blender" action on a complex Shot, so that I can start its previz in one click.
  10. As a filmmaker, I want the app to build the Blender scene for me the first time I open it, so that I don't set up the camera, the frame range and the figures by hand.
  11. As a filmmaker, I want "Open in Blender" to reopen my saved Blender file after the first time, so that my animation is never overwritten.
  12. As a filmmaker, I want an explicit "Rebuild Blender scene" action that sets the old file aside instead of deleting it, so that I can start over after big changes to the Shot without losing work.
  13. As a filmmaker, I want the Blender camera to use the Shot's effective aspect ratio, so that the playblast frames the Shot the way H3 will render it.
  14. As a filmmaker, I want the Blender frame range and frame rate to match the Shot's length at H3's frame rate, so that the playblast's timing lines up with the Take.
  15. As a filmmaker, I want one proxy figure per subject of the Shot, named after its Character, so that I know which figure is which while I animate.
  16. As a filmmaker, I want each figure in its own distinct flat colour from a fixed palette, so that H3 can tell the subjects apart in the playblast.
  17. As a filmmaker, I want the colours assigned in the Shot's subject order and kept stable while the subjects don't change, so that the prompt's colour mapping stays correct.
  18. As a filmmaker, I want the Shot's Performance slice placed on the Blender timeline when a Performance drives the Shot, so that I can time the motion to the dialogue.
  19. As a filmmaker, I want timeline markers at each Line's start (from Line marks when a Performance drives the Shot, otherwise from the script estimate), so that I know where each Line falls while I animate.
  20. As a filmmaker, I want the Board's Panels available as camera background images in Blender, so that I can match the staging I already boarded.
  21. As a filmmaker, I want the Setup's location angle available as a camera background image, so that I can place figures and the camera against the real Location.
  22. As a filmmaker, I want a single "Playblast for AI Studio" action inside Blender, so that the output always has the right size, length, shading, format and file location.
  23. As a filmmaker, I want the playblast to be flat-shaded and untextured, with the background references hidden, so that H3 reads only motion and camera from it and not look or identity.
  24. As a filmmaker, I want the app to pick up a playblast as soon as Blender writes it, so that I don't have to import it by hand.
  25. As a filmmaker, I want a playblast written while the Project was closed to be picked up when I next open it, so that previz done offline isn't lost.
  26. As a filmmaker, I want each playblast kept as a new previz version, never overwriting the last one, so that Takes keep pointing at the exact video they were sent.
  27. As a filmmaker, I want the newest playblast to be the Shot's current previz, so that rendering again in Blender is all it takes to update the reference.
  28. As a filmmaker, I want to import a playblast file by hand as well, so that I can use a previz made in another tool or on another machine.
  29. As a filmmaker, I want a playblast shorter than 2 seconds or longer than 15 seconds to be refused with a clear message, so that I never attach a video H3 can't take.
  30. As a filmmaker, I want a playblast whose length or aspect ratio doesn't match the Shot to be kept but flagged, so that I can see the mismatch and fix it, as with an off-ratio Keyframe.
  31. As a filmmaker, I want to preview the current playblast in the Shot's previz panel, so that I can check it before I queue Takes.
  32. As a filmmaker, I want to see the Shot's previz versions with their times, so that I know which one is current.
  33. As a filmmaker, I want the current playblast to appear in the Shot's Slot list as a video candidate, so that it is sent to H3 like any other reference.
  34. As a filmmaker, I want the Slot list to show a separate video section with H3's three video slots, so that the video budget is clear and kept apart from the image and audio budgets.
  35. As a filmmaker, I want to exclude the playblast from a Shot's Slot list, so that I can try a Take without it while keeping it attached.
  36. As a filmmaker, I want the composed prompt to describe the playblast as a motion and camera reference only, so that H3 doesn't copy its flat grey look.
  37. As a filmmaker, I want the composed prompt to map each figure colour to its subject, so that H3 moves the right Character along the right path.
  38. As a filmmaker, I want my Prompt override to be able to use <Video N> slot tags, with the same broken-tag checks as picture and audio tags, so that hand-edited prompts stay safe to queue.
  39. As a filmmaker, I want a Take queued on a complex Shot to send the playblast in an H3 video slot, so that the generation follows the previz motion.
  40. As a filmmaker, I want each Take to record which previz version it was sent, so that its provenance is complete.
  41. As a filmmaker, I want a Take to become stale when the Shot's current playblast changes, with a Stale reason like "Previz: v2 → v3", so that I know which Takes predate the latest previz.
  42. As a filmmaker, I want to accept a previz Stale reason on a Take, so that a harmless previz tweak doesn't flag a Take I'm happy with.
  43. As a filmmaker, I want "Re-roll stale circled Takes" to pick up previz changes, so that a whole Scene can be refreshed after previz is done.
  44. As a filmmaker, I want the Animatic to play a complex Shot's current playblast in place of its Board until a Take is circled, so that the Animatic shows the real motion and timing.
  45. As a filmmaker, I want unmarking a Shot complex to keep its previz versions and Blender file, so that marking it complex again brings everything back.
  46. As a filmmaker, I want a Shot that isn't complex never to send a playblast, so that the flag is the one switch for the whole previz workflow.
  47. As a filmmaker, I want splitting a complex Shot to keep the flag and the previz on the first part, as with Takes, so that splitting never throws away previz work.
  48. As a filmmaker, I want the previz folder named by the Shot's stable identity, not its label, so that relabelling Shots (12B·1 → 12B·2) never breaks the link.
  49. As a filmmaker, I want to set the Blender executable in the app's settings, with the usual install locations detected for me, so that "Open in Blender" works without setup on a normal install.
  50. As a filmmaker, I want "Open in Blender" to explain what is missing when Blender can't be found, so that I know how to fix it.
  51. As a filmmaker, I want previz versions and Blender files to appear in Storage with their sizes and users, so that I can reclaim space from old playblasts.
  52. As a filmmaker, I want a previz version that a Take was sent to be protected the same way other provenance is, so that Purge never makes a Take's record unreadable.
  53. As a filmmaker, I want deleted or Missing playblast files handled like Missing Renditions, so that a file moved outside the app doesn't crash anything.

Implementation Decisions

Domain language

  • New glossary terms for CONTEXT.md (via /domain-modeling): Complex shot (a Shot flagged for Blender previz), Previz (a complex Shot's Blender scene and its playblast versions) and Playblast (one rendered previz video, one previz version). The Animatic entry already reserves "previz" for Blender playblasts, so this matches the existing vocabulary.

Data model (studio-core, new migration)

  • A Shot gains a complex flag, false by default. Setting and clearing it is an undoable edit. When a Shot is split, the first part keeps the flag and the previz.
  • A new append-only previz version record belongs to a Shot: its version number, the video's content hash, duration, frame count, pixel size, how it arrived (picked up from the folder or imported by hand), and its time. The Shot's current previz is its newest version that has its file. Versions are never edited, only added, like Reference versions.
  • The playblast video is stored in the Project's media folder, next to Renditions (videos are too big for the .studio file), as a content-hashed copy. A later write to the same path in the Blender folder becomes a new version and never touches an earlier one.
  • Each Shot has a previz working folder in the media folder, named by its stable Shot id. It holds the generated scene spec, the bootstrap script, the saved Blender file and the playblast output. The folder is a workspace; the stored versions are the record.
  • Unmarking a Shot complex keeps its previz versions and folder (ADR-0004, provenance-preserving deletion).
  • Take inputs gain a previz input that records the previz version sent and its slot.

Shot read model

  • The Shot view gains complex and a previz status: none, current, or mismatched (length or effective aspect ratio differs from the Shot). Every Shot listing reads this for the dot, as the over-budget count is read today.

Blender scene spec and bootstrap

  • A pure core function builds a scene spec for a Shot: the aspect ratio and a working resolution, the frame rate and frame count, the subjects in Shot subject order with their Character names and palette colours, the Line markers (from the Performance's Line marks when a Performance drives the Shot, otherwise the script estimate), the Performance slice audio path when there is one, the Board Panel images, the location angle image, and the playblast output path.
  • The palette is fixed and ordered. A subject keeps its colour for as long as the Shot's subject list is unchanged.
  • The app ships one Blender Python bootstrap script, in the same spirit as ADR-0002's shipped workflows: the app owns it and versions it. It reads the scene spec. On first run it builds the scene (ground plane, camera, proxy figures with flat object colours, the audio strip, markers and camera background images), saves the Blender file in the folder and registers a "Playblast for AI Studio" operator. On later runs it opens the saved file and registers the operator again.
  • The operator sets the output path, resolution, frame range, viewport shading (solid, flat lighting, object colour, no overlays, background images hidden) and H.264 MP4 output, then runs a viewport render of the animation.
  • "Open in Blender" writes or refreshes the spec and bootstrap, then launches Blender with the bootstrap. "Rebuild Blender scene" moves the saved Blender file aside within the folder before it builds the scene again.
  • The Blender executable is an app-level setting with auto-detection of the usual install locations, following the pattern of the ffmpeg locator.

Playblast pickup

  • A core command ingests a playblast file for a Shot. It probes the file with ffmpeg, refuses anything shorter than 2 s or longer than 15 s, copies the file into storage, creates the version, and marks it mismatched when its frame count or aspect ratio differs from the Shot's. This is one undoable edit.
  • A core scan compares each complex Shot's folder output with its newest version and ingests what is new. It runs when a Project opens and whenever the app's folder watcher fires. The watcher only triggers the scan, so it holds no logic.
  • Manual import goes through the same ingest command.

Slot budget

  • SlotMedium gains Video, with H3's 3 video slots. The only candidate today is the complex Shot's current previz. It follows the existing Slot list rules: default order, user edits, exclusion and over-budget. A Shot that isn't complex has no video candidates.
  • Video slot numbers produce <Video N> tags.

Prompt composer

  • When a playblast is sent, the composer adds a sentence that names it a motion and camera reference only (ignore its colours, shading and the look of the figures) and maps each palette colour to its subject by name and slot tag.
  • Prompt-override slot-tag checks cover <Video N> in the same way as picture and audio tags.

Workflows and jobs

  • The h3.draft and h3.final manifests gain video slot bindings (ref_videos.ref_video_{n}, count 3) and a video load node that is added for each filled slot. The workflow version goes up, with changes_output: false, because a Take with no video slot builds the same graph. Promotion reuses the draft's latent and sends no video.
  • The job builder uploads the previz file to ComfyUI with the job's other inputs. The Take records the version sent.
  • Preflight covers any node pack the video loader needs.

Staleness

  • A previz added, dropped, moved to another slot or changed to another version is a Stale reason in the existing Board/Keyframes group, labelled "Previz: vN → vM", compared by version identity. Accepted reasons and stale re-rolls work on it unchanged.

Animatic

  • A Shot block with no circled Take shows the Shot's current playblast when the Shot is complex and has one; otherwise it shows the Board as today.

Storage

  • Storage lists previz versions and Blender working files with their sizes and users. A version that a Take was sent is kept as provenance, the same way as other Take inputs. Missing previz files are handled like Missing Renditions.

Frontend

  • A small ComplexShotDot component sits beside OverBudgetBadge wherever Shots are listed. Its colour comes from the previz status. A pure helper maps the status to colour and tooltip.
  • The Shot's panel gains a previz section with the complex toggle, "Open in Blender", "Rebuild Blender scene", "Import playblast…", the current playblast player and the version list. The Slot list view gains a Video section.

Testing Decisions

  • Good tests check behaviour that can be seen through the public ProjectSession commands, the reads and the jobs that reach ComfyUI. They never check tables, internal structs or the order of internal calls.
  • The main seam is studio-core integration tests (crates/studio-core/tests/), using ProjectSession, RenderWorker and FakeComfy. A new previz test file covers:
    • marking and unmarking a Shot complex, with undo, and the flag and previz staying on the first part when a Shot is split;
    • the scene spec for a Shot: aspect ratio, frame count, subjects and stable colours, Line markers with and without a Performance, Board and location angle images, and the output path;
    • ingesting a playblast: versions are append-only, the current one is the newest, files under 2 s or over 15 s are refused, length and ratio mismatches are flagged, and the scan picks up a file dropped into the Shot's folder, both on open and when called again;
    • the video Slot list: candidate present only when the Shot is complex, exclusion, and <Video N> numbering;
    • the composed prompt's motion-only sentence and colour mapping, and broken <Video N> tags in an override;
    • the job FakeComfy receives: the uploaded video and the ref_videos input wired up, and none for Shots that aren't complex or for Promotion;
    • staleness: a new previz version makes a Take stale with a Previz reason, accepting it, and stale re-rolls;
    • the Animatic: playblast in place of the Board until a Take is circled;
    • Storage: previz rows, and a version a Take was sent being protected.
  • Test playblasts are short videos generated with the bundled ffmpeg in a test helper.
  • Prior art: tests/keyframes.rs (Shot-attached media, undo, FakeComfy jobs), tests/slot_budget.rs, tests/prompt_composer.rs, tests/prompt_override.rs, tests/staleness.rs, tests/animatic_takes.rs, tests/storage.rs, tests/shipped_workflows.rs (manifest checks for the new video bindings).
  • Frontend: one vitest unit test for the status → colour/tooltip helper, as in src/lib/scenes/*.test.ts.
  • Not tested automatically: the Blender bootstrap script and the operating-system folder watcher. Both are thin shims over the tested core: the script only reads the scene spec, and the watcher only calls the scan. Check them by hand with a real Blender install before merging.

Out of Scope

  • A blocking plan or blocking editor, and building the Blender scene from blocking (figure positions, a Location blockout). Figures start in a default line-up in front of the camera.
  • The MCP server, MCP prompt templates and driving Blender through a Blender MCP or an agent.
  • Prop proxies in the Blender scene.
  • Any video reference other than the previz playblast (e.g. a Take used as a video reference), and so more than one video candidate per Shot.
  • Detecting complex Shots automatically.
  • Exporting playblasts in the Edit package or its timelines.
  • Testing how closely H3 follows playblast camera moves and whether figure colours map reliably to subjects. That is an open question from the original plan, to settle by use.

Further Notes

  • This is the "Blender previz" tier from the original production plan (scratch/scratch-plan.md, Previz section). It was deferred from the first slice (#24: "Video slots stay unused").
  • H3's ComfyUI Reference-to-Video node already exposes three ref_videos inputs (seen in the hand-tuned seed-hunter graph), so no new model is needed. Only the shipped workflow manifests change, which ADR-0002 expects: improvements are ported by hand.
  • ADR-0003 holds: the scene spec, ingest, slots, prompt and staleness all live in studio-core. Tauri only launches Blender and forwards watcher events to the scan.
  • Glossary gap: add Complex shot, Previz and Playblast to CONTEXT.md.
## Problem Statement A Board tells H3 about staging, composition and camera movement with a few still Panels and Notation symbols. That works for simple Shots, but it isn't enough for Shots with complex staging: several subjects moving at once, or subject motion combined with a camera move. For those Shots H3 has to guess the timing and the paths through space, and the filmmaker re-rolls Takes again and again hoping one moves right. H3's Reference-to-Video node accepts up to three video references, but the app never sends one, so the filmmaker has no way to show H3 the exact motion and camera they want. ## Solution The filmmaker can mark a Shot as **complex**. A complex Shot shows a coloured dot on the storyboard (the Board timeline) and on the other Shot listings. The dot's colour shows how far its previz has got. A complex Shot gets a Blender **previz** workflow. From the Shot, the filmmaker clicks "Open in Blender". The app builds a Blender scene for the Shot in a folder of its own: a camera at the Shot's aspect ratio and length, one flat-coloured proxy figure per subject, the Shot's Performance slice on the timeline (when a Performance drives it), Line markers, and the Board Panels and location angle as camera background references. The filmmaker animates the figures and the camera, then runs one "Playblast for AI Studio" action in Blender. That renders a flat-shaded, untextured video at the Shot's exact length into the Shot's folder. The app notices the new playblast and attaches it to the Shot as a new previz version. The playblast then: - fills one of H3's video slots in the Shot's Slot list, - is named in the composed prompt as a motion and camera reference only, with each figure colour mapped to its subject ("Mara is the red figure in `<Video 1>`"), - replaces the Shot's Board in the Animatic until a Take is circled, and - counts toward staleness, so Takes made with an older playblast show a Stale reason. ## User Stories 1. As a filmmaker, I want to mark a Shot as complex, so that I can choose a heavier previz workflow for just the Shots that need it. 2. As a filmmaker, I want to unmark a complex Shot, so that a Shot I flagged by mistake goes back to the plain Board workflow. 3. As a filmmaker, I want marking and unmarking a Shot complex to be undoable, so that it behaves like every other authored edit. 4. As a filmmaker, I want a coloured dot on each complex Shot in the Board timeline, so that I can see which Shots need previz while I storyboard. 5. As a filmmaker, I want the same dot wherever Shots are listed (the Scenes view's Setups block, the Animatic's cut tracks, Dailies), so that complex Shots are recognisable everywhere, like the over-budget badge. 6. As a filmmaker, I want the dot's colour to tell me whether the Shot has no playblast yet, has a current playblast, or has a playblast that no longer matches the Shot's length or aspect ratio, so that I can see previz progress at a glance. 7. As a filmmaker, I want the dot's tooltip to say what its colour means, so that I don't have to memorise the colours. 8. As a filmmaker, I want Shots that aren't complex to show no dot, so that the storyboard stays uncluttered. 9. As a filmmaker, I want an "Open in Blender" action on a complex Shot, so that I can start its previz in one click. 10. As a filmmaker, I want the app to build the Blender scene for me the first time I open it, so that I don't set up the camera, the frame range and the figures by hand. 11. As a filmmaker, I want "Open in Blender" to reopen my saved Blender file after the first time, so that my animation is never overwritten. 12. As a filmmaker, I want an explicit "Rebuild Blender scene" action that sets the old file aside instead of deleting it, so that I can start over after big changes to the Shot without losing work. 13. As a filmmaker, I want the Blender camera to use the Shot's effective aspect ratio, so that the playblast frames the Shot the way H3 will render it. 14. As a filmmaker, I want the Blender frame range and frame rate to match the Shot's length at H3's frame rate, so that the playblast's timing lines up with the Take. 15. As a filmmaker, I want one proxy figure per subject of the Shot, named after its Character, so that I know which figure is which while I animate. 16. As a filmmaker, I want each figure in its own distinct flat colour from a fixed palette, so that H3 can tell the subjects apart in the playblast. 17. As a filmmaker, I want the colours assigned in the Shot's subject order and kept stable while the subjects don't change, so that the prompt's colour mapping stays correct. 18. As a filmmaker, I want the Shot's Performance slice placed on the Blender timeline when a Performance drives the Shot, so that I can time the motion to the dialogue. 19. As a filmmaker, I want timeline markers at each Line's start (from Line marks when a Performance drives the Shot, otherwise from the script estimate), so that I know where each Line falls while I animate. 20. As a filmmaker, I want the Board's Panels available as camera background images in Blender, so that I can match the staging I already boarded. 21. As a filmmaker, I want the Setup's location angle available as a camera background image, so that I can place figures and the camera against the real Location. 22. As a filmmaker, I want a single "Playblast for AI Studio" action inside Blender, so that the output always has the right size, length, shading, format and file location. 23. As a filmmaker, I want the playblast to be flat-shaded and untextured, with the background references hidden, so that H3 reads only motion and camera from it and not look or identity. 24. As a filmmaker, I want the app to pick up a playblast as soon as Blender writes it, so that I don't have to import it by hand. 25. As a filmmaker, I want a playblast written while the Project was closed to be picked up when I next open it, so that previz done offline isn't lost. 26. As a filmmaker, I want each playblast kept as a new previz version, never overwriting the last one, so that Takes keep pointing at the exact video they were sent. 27. As a filmmaker, I want the newest playblast to be the Shot's current previz, so that rendering again in Blender is all it takes to update the reference. 28. As a filmmaker, I want to import a playblast file by hand as well, so that I can use a previz made in another tool or on another machine. 29. As a filmmaker, I want a playblast shorter than 2 seconds or longer than 15 seconds to be refused with a clear message, so that I never attach a video H3 can't take. 30. As a filmmaker, I want a playblast whose length or aspect ratio doesn't match the Shot to be kept but flagged, so that I can see the mismatch and fix it, as with an off-ratio Keyframe. 31. As a filmmaker, I want to preview the current playblast in the Shot's previz panel, so that I can check it before I queue Takes. 32. As a filmmaker, I want to see the Shot's previz versions with their times, so that I know which one is current. 33. As a filmmaker, I want the current playblast to appear in the Shot's Slot list as a video candidate, so that it is sent to H3 like any other reference. 34. As a filmmaker, I want the Slot list to show a separate video section with H3's three video slots, so that the video budget is clear and kept apart from the image and audio budgets. 35. As a filmmaker, I want to exclude the playblast from a Shot's Slot list, so that I can try a Take without it while keeping it attached. 36. As a filmmaker, I want the composed prompt to describe the playblast as a motion and camera reference only, so that H3 doesn't copy its flat grey look. 37. As a filmmaker, I want the composed prompt to map each figure colour to its subject, so that H3 moves the right Character along the right path. 38. As a filmmaker, I want my Prompt override to be able to use `<Video N>` slot tags, with the same broken-tag checks as picture and audio tags, so that hand-edited prompts stay safe to queue. 39. As a filmmaker, I want a Take queued on a complex Shot to send the playblast in an H3 video slot, so that the generation follows the previz motion. 40. As a filmmaker, I want each Take to record which previz version it was sent, so that its provenance is complete. 41. As a filmmaker, I want a Take to become stale when the Shot's current playblast changes, with a Stale reason like "Previz: v2 → v3", so that I know which Takes predate the latest previz. 42. As a filmmaker, I want to accept a previz Stale reason on a Take, so that a harmless previz tweak doesn't flag a Take I'm happy with. 43. As a filmmaker, I want "Re-roll stale circled Takes" to pick up previz changes, so that a whole Scene can be refreshed after previz is done. 44. As a filmmaker, I want the Animatic to play a complex Shot's current playblast in place of its Board until a Take is circled, so that the Animatic shows the real motion and timing. 45. As a filmmaker, I want unmarking a Shot complex to keep its previz versions and Blender file, so that marking it complex again brings everything back. 46. As a filmmaker, I want a Shot that isn't complex never to send a playblast, so that the flag is the one switch for the whole previz workflow. 47. As a filmmaker, I want splitting a complex Shot to keep the flag and the previz on the first part, as with Takes, so that splitting never throws away previz work. 48. As a filmmaker, I want the previz folder named by the Shot's stable identity, not its label, so that relabelling Shots (12B·1 → 12B·2) never breaks the link. 49. As a filmmaker, I want to set the Blender executable in the app's settings, with the usual install locations detected for me, so that "Open in Blender" works without setup on a normal install. 50. As a filmmaker, I want "Open in Blender" to explain what is missing when Blender can't be found, so that I know how to fix it. 51. As a filmmaker, I want previz versions and Blender files to appear in Storage with their sizes and users, so that I can reclaim space from old playblasts. 52. As a filmmaker, I want a previz version that a Take was sent to be protected the same way other provenance is, so that Purge never makes a Take's record unreadable. 53. As a filmmaker, I want deleted or Missing playblast files handled like Missing Renditions, so that a file moved outside the app doesn't crash anything. ## Implementation Decisions ### Domain language - New glossary terms for `CONTEXT.md` (via `/domain-modeling`): **Complex shot** (a Shot flagged for Blender previz), **Previz** (a complex Shot's Blender scene and its playblast versions) and **Playblast** (one rendered previz video, one previz version). The Animatic entry already reserves "previz" for Blender playblasts, so this matches the existing vocabulary. ### Data model (studio-core, new migration) - A Shot gains a `complex` flag, false by default. Setting and clearing it is an undoable edit. When a Shot is split, the first part keeps the flag and the previz. - A new append-only **previz version** record belongs to a Shot: its version number, the video's content hash, duration, frame count, pixel size, how it arrived (picked up from the folder or imported by hand), and its time. The Shot's current previz is its newest version that has its file. Versions are never edited, only added, like Reference versions. - The playblast video is stored in the Project's media folder, next to Renditions (videos are too big for the `.studio` file), as a content-hashed copy. A later write to the same path in the Blender folder becomes a new version and never touches an earlier one. - Each Shot has a previz working folder in the media folder, named by its stable Shot id. It holds the generated scene spec, the bootstrap script, the saved Blender file and the playblast output. The folder is a workspace; the stored versions are the record. - Unmarking a Shot complex keeps its previz versions and folder (ADR-0004, provenance-preserving deletion). - Take inputs gain a previz input that records the previz version sent and its slot. ### Shot read model - The Shot view gains `complex` and a previz status: `none`, `current`, or `mismatched` (length or effective aspect ratio differs from the Shot). Every Shot listing reads this for the dot, as the over-budget count is read today. ### Blender scene spec and bootstrap - A pure core function builds a **scene spec** for a Shot: the aspect ratio and a working resolution, the frame rate and frame count, the subjects in Shot subject order with their Character names and palette colours, the Line markers (from the Performance's Line marks when a Performance drives the Shot, otherwise the script estimate), the Performance slice audio path when there is one, the Board Panel images, the location angle image, and the playblast output path. - The palette is fixed and ordered. A subject keeps its colour for as long as the Shot's subject list is unchanged. - The app ships one Blender Python bootstrap script, in the same spirit as ADR-0002's shipped workflows: the app owns it and versions it. It reads the scene spec. On first run it builds the scene (ground plane, camera, proxy figures with flat object colours, the audio strip, markers and camera background images), saves the Blender file in the folder and registers a "Playblast for AI Studio" operator. On later runs it opens the saved file and registers the operator again. - The operator sets the output path, resolution, frame range, viewport shading (solid, flat lighting, object colour, no overlays, background images hidden) and H.264 MP4 output, then runs a viewport render of the animation. - "Open in Blender" writes or refreshes the spec and bootstrap, then launches Blender with the bootstrap. "Rebuild Blender scene" moves the saved Blender file aside within the folder before it builds the scene again. - The Blender executable is an app-level setting with auto-detection of the usual install locations, following the pattern of the ffmpeg locator. ### Playblast pickup - A core command ingests a playblast file for a Shot. It probes the file with ffmpeg, refuses anything shorter than 2 s or longer than 15 s, copies the file into storage, creates the version, and marks it `mismatched` when its frame count or aspect ratio differs from the Shot's. This is one undoable edit. - A core scan compares each complex Shot's folder output with its newest version and ingests what is new. It runs when a Project opens and whenever the app's folder watcher fires. The watcher only triggers the scan, so it holds no logic. - Manual import goes through the same ingest command. ### Slot budget - `SlotMedium` gains `Video`, with H3's 3 video slots. The only candidate today is the complex Shot's current previz. It follows the existing Slot list rules: default order, user edits, exclusion and over-budget. A Shot that isn't complex has no video candidates. - Video slot numbers produce `<Video N>` tags. ### Prompt composer - When a playblast is sent, the composer adds a sentence that names it a motion and camera reference only (ignore its colours, shading and the look of the figures) and maps each palette colour to its subject by name and slot tag. - Prompt-override slot-tag checks cover `<Video N>` in the same way as picture and audio tags. ### Workflows and jobs - The `h3.draft` and `h3.final` manifests gain video slot bindings (`ref_videos.ref_video_{n}`, count 3) and a video load node that is added for each filled slot. The workflow version goes up, with `changes_output: false`, because a Take with no video slot builds the same graph. Promotion reuses the draft's latent and sends no video. - The job builder uploads the previz file to ComfyUI with the job's other inputs. The Take records the version sent. - Preflight covers any node pack the video loader needs. ### Staleness - A previz added, dropped, moved to another slot or changed to another version is a Stale reason in the existing Board/Keyframes group, labelled "Previz: vN → vM", compared by version identity. Accepted reasons and stale re-rolls work on it unchanged. ### Animatic - A Shot block with no circled Take shows the Shot's current playblast when the Shot is complex and has one; otherwise it shows the Board as today. ### Storage - Storage lists previz versions and Blender working files with their sizes and users. A version that a Take was sent is kept as provenance, the same way as other Take inputs. Missing previz files are handled like Missing Renditions. ### Frontend - A small `ComplexShotDot` component sits beside `OverBudgetBadge` wherever Shots are listed. Its colour comes from the previz status. A pure helper maps the status to colour and tooltip. - The Shot's panel gains a previz section with the complex toggle, "Open in Blender", "Rebuild Blender scene", "Import playblast…", the current playblast player and the version list. The Slot list view gains a Video section. ## Testing Decisions - Good tests check behaviour that can be seen through the public `ProjectSession` commands, the reads and the jobs that reach ComfyUI. They never check tables, internal structs or the order of internal calls. - **The main seam is studio-core integration tests** (`crates/studio-core/tests/`), using `ProjectSession`, `RenderWorker` and `FakeComfy`. A new previz test file covers: - marking and unmarking a Shot complex, with undo, and the flag and previz staying on the first part when a Shot is split; - the scene spec for a Shot: aspect ratio, frame count, subjects and stable colours, Line markers with and without a Performance, Board and location angle images, and the output path; - ingesting a playblast: versions are append-only, the current one is the newest, files under 2 s or over 15 s are refused, length and ratio mismatches are flagged, and the scan picks up a file dropped into the Shot's folder, both on open and when called again; - the video Slot list: candidate present only when the Shot is complex, exclusion, and `<Video N>` numbering; - the composed prompt's motion-only sentence and colour mapping, and broken `<Video N>` tags in an override; - the job FakeComfy receives: the uploaded video and the `ref_videos` input wired up, and none for Shots that aren't complex or for Promotion; - staleness: a new previz version makes a Take stale with a Previz reason, accepting it, and stale re-rolls; - the Animatic: playblast in place of the Board until a Take is circled; - Storage: previz rows, and a version a Take was sent being protected. - Test playblasts are short videos generated with the bundled ffmpeg in a test helper. - Prior art: `tests/keyframes.rs` (Shot-attached media, undo, FakeComfy jobs), `tests/slot_budget.rs`, `tests/prompt_composer.rs`, `tests/prompt_override.rs`, `tests/staleness.rs`, `tests/animatic_takes.rs`, `tests/storage.rs`, `tests/shipped_workflows.rs` (manifest checks for the new video bindings). - **Frontend:** one vitest unit test for the status → colour/tooltip helper, as in `src/lib/scenes/*.test.ts`. - **Not tested automatically:** the Blender bootstrap script and the operating-system folder watcher. Both are thin shims over the tested core: the script only reads the scene spec, and the watcher only calls the scan. Check them by hand with a real Blender install before merging. ## Out of Scope - A blocking plan or blocking editor, and building the Blender scene from blocking (figure positions, a Location blockout). Figures start in a default line-up in front of the camera. - The MCP server, MCP prompt templates and driving Blender through a Blender MCP or an agent. - Prop proxies in the Blender scene. - Any video reference other than the previz playblast (e.g. a Take used as a video reference), and so more than one video candidate per Shot. - Detecting complex Shots automatically. - Exporting playblasts in the Edit package or its timelines. - Testing how closely H3 follows playblast camera moves and whether figure colours map reliably to subjects. That is an open question from the original plan, to settle by use. ## Further Notes - This is the "Blender previz" tier from the original production plan (`scratch/scratch-plan.md`, Previz section). It was deferred from the first slice (#24: "Video slots stay unused"). - H3's ComfyUI Reference-to-Video node already exposes three `ref_videos` inputs (seen in the hand-tuned seed-hunter graph), so no new model is needed. Only the shipped workflow manifests change, which ADR-0002 expects: improvements are ported by hand. - ADR-0003 holds: the scene spec, ingest, slots, prompt and staleness all live in studio-core. Tauri only launches Blender and forwards watcher events to the scan. - Glossary gap: add **Complex shot**, **Previz** and **Playblast** to `CONTEXT.md`.
Author
Owner

All ten slices (#158–#167) are merged (PRs #168–#178). Follow-ups from those PRs:

  • #179 Hand-check Blender previz end to end (ready-for-human)
  • #180 A missing playblast blacks out the Animatic and keeps the dot green (bug)
  • #181 Warn when a mismatched playblast or off-ratio Keyframe is sent
  • #182 More than 8 subjects reuse previz figure colours
  • #183 Guard against two Blender instances on one previz folder
  • #184 Export playblasts in the Edit package (was out of scope here)
  • #185 MCP tools for previz (blocked by #157)
  • #186 Reclaim space from previz working folders
  • #187 Evaluate how H3 follows playblast motion and colours (the open question above)
All ten slices (#158–#167) are merged (PRs #168–#178). Follow-ups from those PRs: - #179 Hand-check Blender previz end to end (ready-for-human) - #180 A missing playblast blacks out the Animatic and keeps the dot green (bug) - #181 Warn when a mismatched playblast or off-ratio Keyframe is sent - #182 More than 8 subjects reuse previz figure colours - #183 Guard against two Blender instances on one previz folder - #184 Export playblasts in the Edit package (was out of scope here) - #185 MCP tools for previz (blocked by #157) - #186 Reclaim space from previz working folders - #187 Evaluate how H3 follows playblast motion and colours (the open question above)
Author
Owner

Done: all slices merged. Follow-ups are #179–#187.

Done: all slices merged. Follow-ups are #179–#187.
Sign in to join this conversation.
No description provided.