Story Shorts: any idea in, a finished cartoon Short out
This skill is a film engine plus a workflow. The engine (engine/) renders three.js frame by frame in headless Chrome:
2D canvas puppet characters in a toon-shaded, ink-outlined 3D world, camera moves and dissolves, a 2D overlay for
explainer graphics, burned-in captions, and a timed-event sound mix. Each film writes only its story layer: who
is in it, where it happens, the shots, the graphics and the sound plan. A new film starts from the blank starter
(starter/: two placeholder characters, two places, four shots). examples/floating-scale/ is one finished film,
for reference only. Never reuse its characters or story.
Read these as you need them:
reference/rules.md: the story and picture rules. Read it first.reference/story-templates.md: six story shapes. Pick one per film.reference/engine-api.md: how to write a film on the engine (characters, poses, worlds, props, shots, graphics, cues).reference/transitions.md: rule 11 in practice (camera moves, staging for continuity, kept cuts).reference/sound.md: voice, music and effects, with Epidemic Sound or the free tools.reference/lessons.md: bugs already hit, and their fixes. Check it before debugging anything.
Before you start: ask two questions
- The idea. One sentence is enough: "a lighthouse keeper who is afraid of the dark", "the 1904 Olympic marathon", "what if gravity halved for a day". Ask for it if the user has not given it. Ask about length only if it matters to them (default about 60 s).
- Sound tools. Ask: "Do you have Epidemic Sound (with its Claude connector), or should I use the free tools?"
- Epidemic Sound (recommended): Epidemic voiceover for the narrator and characters, one Epidemic music track cut to the story, Epidemic effects and ambience. It needs the Epidemic Sound MCP connector in Claude Code.
- Free: Kokoro TTS for the voices (
scripts/kokoro_voice.py), a score and effects synthesized in code. - Don't mix the two in one film without saying so in the film's README.
Then run python scripts/check_setup.py and fix anything marked MISSING before writing any film code.
The workflow (no approvals needed unless the user asks for them)
- New project.
python scripts/new_film.py <folder> "Title"copies the engine and the blank starter, writes a placeholder timeline and installsfilm/node_modulesfresh. Work only inside that folder. - Story (
docs/STORY.md,script/lines.json).- Pick the story template that fits the idea (
reference/story-templates.md), and say which one you picked and why. - Write the script: one entry per spoken line (id, speaker, start, text). Narration plus a few character lines; about 150 words a minute of film.
- Write the shot list with a silent read per shot: what a muted viewer understands from the picture alone.
- Name the places. A change of place is the only reason for a dissolve; inside a place the camera moves.
- Facts must be true, with real numbers. Characters, story and world are original.
- Pick the story template that fits the idea (
- Cast (
film/src/story/cast.js).- One key per character (the same as their speaker id). Start each from a preset and override colours, proportions
and features until they are this film's own (
reference/engine-api.md, "Characters"). Add a new look incharacter.jsbehind a newfeatflag when the story needs one. - Render
node film/tools/charsheet.mjsand look at every sheet before building any shot.
- One key per character (the same as their speaker id). Start each from a preset and override colours, proportions
and features until they are this film's own (
- World and props (
story/world.js,story/set.js, optionalstory/props.js).- Build each place from
worldkit.jsplus its own landmarks. Put every mark inSET. Give hero props the states the story needs.
- Build each place from
- Block the picture (
story/shots.js,story/overlay.js).- Replace the starter's four shots with the film's shots. Time beats from the timeline (
K.wordAt,K.lineAt), never from hard-coded seconds. Until the voice exists,python tools/build_timeline.py --placeholder. - Stage for continuity from the start (rule 11): one performance per character per place, props on their marks.
- Explain with 2D diagrams (rule 4). List every visible action in
CUES.
- Replace the starter's four shots with the film's shots. Time beats from the timeline (
- Voice.
- Generate each line as its own clip into
audio/vo/raw/<id>.mp3|wav(Epidemic, orscripts/kokoro_voice.py). python <repo>/scripts/prepare_voice.py(add--atempo-offfor Kokoro) trims the silent ends and sets the pace.python tools/build_timeline.py,python tools/captions.py, thencd film && node tools/cues.mjs.- Never cut a clip at whisper word times. Re-check the framing: the beats moved with the real voice.
- Generate each line as its own clip into
- Review the picture before any full render:
node framecheck.mjs --step 4must print "framing OK".node tools/poptest.mjs --out ../render/popchecks every boundary for pops;bash tools/movesheet.shchecks moves.bash tools/sheet.sh <name> "<times>"makes contact sheets. Look at them, and check each shot against its silent read. Do at least two full rounds.
- Sound (
audio/sound_plan.json,reference/sound.md).- Epidemic: download the track and effects into
audio/epidemic/, fill inmusic,effectsandambience, thencd audio/epidemic_mix && python mix_film.py && python autolevel.py && python qc.py && python sync_check.py. - Free: fill in
synth, thencd audio/synth && python music.py && python build_fx.py && python mix.py && python cue_presence.py. - Targets: −14 LUFS, true peak ≤ −1.3 dBTP, voice at least 6 dB clear on every line, no silent gaps, every effect within one frame.
- Epidemic: download the track and effects into
- Render, assemble, hand off.
cd film && node render.mjs --from 0 --to <frames-1> --scale 1.5 --workers 2 --jpg --out ../render/frames.bash tools/assemble.shwritesout/<Title>.mp4andout/contact_sheet.jpg, and measures the result. It refuses to run if a crashed worker left an empty frame.- If earshot is installed:
bash audio/tools/es.sh critique out/<Title>.mp4, aiming for "launch-grade". - Write the film's
README.md: logline, measurements, every kept cut and why, the sounds used, and honest weak spots. Never claim the film is good: you cannot watch or hear it at full speed. List what the user should check by eye and ear, then stop and wait for their review.
Non-negotiables (details in reference/rules.md)
- It reads with the sound off. Show the problem before the solution. Show every line on screen while it is said.
- No literal metaphors; explain with a clear 2D diagram.
- Props read at a glance. Use medium and wide shots with whole figures, keep the caption band (62–78 % of the height) clear, and nobody is cut off at the end.
- Same place means a camera move, a new place means a dissolve, and a cut stays only with a stated reason.
- Every visible action has an audible sound, and the narration stays clear the whole way through.
- Original characters, stories and worlds only. Never copy an existing show's characters or look, and never reuse the example film's.
- Work only inside the film's own folder. Install everything fresh there; never link to another project.