A square, music-only cartoon in an indie-animation style. Every sprite boils on threes (three mesh-warped redraws), characters hop and squash, the camera shakes on hits, and the score is synthesised in code with the cuts on its beat grid. Example: examples/obsidian-wiki/ is the obsidian-wiki 3.5k-stars film (44.9 s) with Mo, a pink brain mascot.
Workflow
- Start:
python3 scripts/main.py init my-film, which copies the example. - Copy: edit
brief.json. Every on-screen string lives there: terminal lines and slash menu, captions, note names, agents, the browser article, popup and form, the answer note, gauge numbers, star count and end card. Run the copy throughskills/no-ai-slopfirst. Don't put trailing periods on captions. - Cast: restyle
style,mascot,posesandpropsinassets.json, then runpython3 scripts/main.py assets --brief my-film/brief.json(orassets mo_waveto regenerate one). The mascot base is generated first, and every pose is a reference-guided edit of it, so the character stays on-model. - Real marks: put the agent logos and your product or extension icon in
assets/icons/as PNGs. They're named by theagentsslugs andbrowser.icon. Never generate logos. - Check: run
check --brief …. It samples the whole cut and fails on missing assets or on any copy that had to shrink below 80% of its designed size. The fix is shorter copy. - Review: run
sheet --brief …(a frame every 1.5 s) andstill --brief … 22.8 30.6. - Render: run
render --brief …, which renders the frames, synthesisesout/mix.m4awithscripts/audio.pyand muxes the result. On slow machines, render halves in parallel withrender --from 0 --to 674and--from 674 --to 1347, then concat them and muxout/mix.m4a.
Slots
| asset | used in | framing |
|---|---|---|
mo + poses mo_sad, mo_gulp, mo_chomp, mo_read, mo_point, mo_cheer, mo_wave, mo_card, mo_run |
everywhere | full-body mascot, transparent, no ground or shadow |
notebook |
title slam, end gag | closed notebook straight on, blank label (the label is typeset) |
paper, chat, shot, card |
ingest, graph, answer | single prop, transparent; chat has three dots that get painted out for the question |
monitor, gauge, burst, smoke, star, sun |
grid, gauge, transitions, stars | single prop, transparent, no text |
icons/<slug>.png |
agent grid, browser toolbar and popup | the real logo, any size |
Notes
- Draw connector lines before the sprites and cards so they always pass behind them. Popups open over a sidebar, never over body text.
- Pillow's
ImageDrawon an RGBA layer replaces pixels instead of blending them. Translucent lines or fading text on an opaque card punch holes in it, so usemixc()(colour toward the card fill) instead of alpha. - gpt-image cut-outs carry a soft halo;
clean_alphathresholds it. Boil variants are cached inout/boil/and cleared byassets. - Timings are on a 120 BPM grid (
B(k)= beat k after the burst at 4.2 s). The browser and answer beats are inserted atB(32), and everything after them playsSHs later.audio.pyuses the same map, so if you retime a scene, move its cues in both files. - Roughly 1350 frames take about 5 min on 2 idle cores, and longer when the machine is loaded.