Skip to content

Blender shot specs (experimental, optional): 3D films, clips and product shots from a JSON spec - #214

Merged
ConalMullan merged 6 commits into
mainfrom
feat/blender-shot-spec
Nov 12, 2026
Merged

ConalMullan merged 6 commits into
mainfrom
feat/blender-shot-spec

Conversation

@ConalMullan

Copy link
Copy Markdown
Collaborator

What this adds

Blender as an optional tool in the toolkit, marked experimental. A JSON shot spec becomes 3D footage: a whole film, one clip per shot for another build, or both from the same spec. Nothing else in the toolkit needs Blender, and nothing changes for anyone who doesn't have it.

  • tools/blender_render.py (doctor, check, render, open) runs Blender headless on lib/blender/.
  • The spec says what happens, the library decides where things go. Shots are types (wide, closeup, over_shoulder, pull_out, orbit, reveal), acting is verbs (expression, pose, shake_head), and a beat's time is seconds, a shot-relative time or a narration word (cue:disk is full).
  • check verifies every camera before a render (about 5 s): subject in frame, nothing in the way, a moving lens clear of the cast. A failing camera is moved by a solver, and a labelled contact sheet is written. It builds at the film's own shape, so a 9:16 spec is judged in 9:16.
  • A cast described in JSON: build, face, hair, clothes, accessories and a seed, all on one rig. A character can live in kits/<name>/cast/ and be re-costumed per video.
  • Three sets: a desk in a room, a desk alone for transparent clips, and a studio stage with a phone, a floating card or an imported model (glTF, OBJ, FBX, STL).
  • BlenderClip in lib/components plays the clips in Remotion, transparent if asked, with each shot's own sound and the frame of every acting event. A Remotion render can also go on the laptop, phone or card in the scene, so a flat scene cuts to itself in 3D.
  • Three examples: blender-disk-panic (a character film), blender-product-shot (a studio stage), blender-in-remotion (clips inside a Remotion video).
  • Planning: /video suggests a Blender shot where one fits when Blender is installed and says nothing when it isn't. /setup, /versions and verify_setup.py report it as optional.
  • Docs: the blender skill, docs/blender.md, CLAUDE.md, README.md, the agent skill, the registry and ten roadmap items for the next round.

How it was checked

  • 231 Python tests pass (5 skipped), 32 of them for Blender: the parts with no Blender in them run everywhere, and the rest skip without Blender 4.2 or later. CI has no Blender, so those skip there.
  • 12 JS tests, both type checks, the Python lint, the Remotion version gate and copy lint on the diff and the commit subjects.
  • All four example specs pass check on macOS (Blender 5.3, EEVEE and Cycles) and on Linux x64 in a container with no GPU (Blender 4.2.3, Cycles).
  • Clips from two specs at different frame rates and shapes were rendered into one folder and the shared clips.json read back.
  • An independent code review of the diff; its findings are fixed and tested.

Known limits

  • Windows has not been run. The code finds Blender under Program Files and reads and writes UTF-8.
  • Transparent WebM clips have been played in Remotion on macOS only.
  • The three example films were rendered before the last round of fixes and not rendered again; the fixes don't touch the picture.
  • One character per set, seated; studio props don't move; no cast shadow on a transparent clip. These are the first roadmap items.
  • qc.py --render warns once on blender-in-remotion ("motion stops dead" at 17.8 s): the character holds still for a second and a half before a cut. The example's README says so.

🤖 Generated with Claude Code

ConalMullan and others added 6 commits November 11, 2026 15:12
…turns a JSON spec into 3D footage, with a rigged cartoon cast described in JSON, a desk set and a product stage, acting on narration cues, and every camera checked by geometry before a render

tools/blender_render.py (doctor, check, render, open) runs Blender headless on lib/blender/. check builds the
scene at the film's own shape, verifies each camera (subject in frame, nothing in the way, a moving lens clear of
the cast), moves a failing camera, and writes a labelled contact sheet. render makes a film with sound placed on
the keyed motion, or one clip per shot (transparent WebM with --alpha) and a clips.json that several specs can
share. A mistake in a spec is a named error that lists the choices. Nothing else in the toolkit needs Blender.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… per shot, transparent if asked, with the shot's own sound and the frame of each acting event

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ct stage with a phone, a card and a 3D model, and Blender clips inside a Remotion video

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…p and /versions report it as optional, and the roadmap has the next round

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…as well as EEVEE: its backdrop is a step darker, since Cycles measures about 0.01 brighter and one shot sat on the exposure limit

Found by running the examples on Linux x64 with Blender 4.2.3 and no GPU: all four specs now pass check there.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… a laptop, phone or card) no longer fails check as blown out

Found making a release-notes video: three cards showing text files failed every shot at 14 to 23% near-white,
which was the pages themselves. The check still runs for sets whose screens show no picture.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@ConalMullan
ConalMullan merged commit c6c1a69 into main Nov 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant