One prompt, one Claude Code session (about 19 hours of wall-clock, including two usage-limit stalls), and a pile of
Workflow scripts produced a 2:29, 1080p, 25 fps original episode in the style of TomSka's asdfmovie: 25 scripted
skits, a title card, credits and an end card; every frame drawn with Python + Skia, every voice, sound effect and
music cue generated with ElevenLabs. This gist has the prompt, how the workflows were used, the stats, the repo layout
and how to reproduce it. The six workflow scripts that actually ran are attached as wf*.js.
It is a fan tribute and is not affiliated with TomSka. No official footage or audio is in the output; the research corpus (downloaded official episodes) is for analysis only and is not part of this gist.
Tidied from the original (full text and the two follow-up messages are in prompt.md):
Use code-rendered motion graphics and ElevenLabs (the API key is already set up in .env) to generate a novel
episode of asdfmovie as a final MP4 that I can share.
Research (use workflows). Research asdfmovie deeply. Download the official episodes with yt-dlp (or similar scripts) and study them closely to understand the style, format, humor, audio and so on.
Quality bar. It should feel like the same style and the same level of polish and quality as the originals. Parity requires deep understanding of the source and constant referencing back to it.
Autonomy. You have full control. Install whatever packages you need.
Deliverable. The final MP4, ready to share.
Mid-run steering: "structure it as research -> story / video board -> art -> generation, with lots of review and
referencing at each step", and later, after hitting the usage limit twice, "wrap up more efficiently, we're low on
usage credits". Session settings: /effort max, ultracode on (Workflow tool by default).
| Video | 1920x1080, 25 fps, 3,733 frames = 2:29.32, H.264 High yuv420p, BT.709 |
| Audio | AAC-LC 48 kHz stereo, -12.1 LUFS integrated, -1.0 dBTP true peak, 23 static transitions with a fixed hiss clip, digital silence where the originals have it |
| Structure | cold open -> title card (letters assemble into "asdfmovieish") -> 22 skits separated by 14-frame TV static -> credits -> fake plug -> post-credits stinger -> "end" card |
| Content | 25 scripted skits (cold open, 19 regular, a 3-beat runner, a fake ad plug, a stinger) + 3 packaging slots = 28 timeline slots; 63 cast entries; 18 voice roles |
| Files | asdfmovieish.mp4 (1080p, 42 MiB, the share version),asdfmovieish_master_hq.mp4 (324 MiB),asdfmovieish_preview_720p.mp4 (17 MiB) |
The share file is bitrate-capped (-crf 22 -maxrate 5M): the TV-static bursts are incompressible noise and cost most
of the bits in a high-quality encode. Line art is visually identical between the two encodes.
- The main session was orchestrator and engineer. It did the deterministic work itself (yt-dlp downloads, shot
detection, Whisper transcripts, the renderer, mixer, mastering chain, ElevenLabs cache client, final assembly, QA)
and wrote
Workflowscripts for everything that needs judgement or heavy reading. - Workflow scripts are plain JavaScript run by Claude Code's
Workflowtool:agent(prompt, {schema, label, phase, effort})spawns a subagent (a JSONschemaforces a small structured return),parallel([...])is a barrier fan-out,pipeline(items, stage1, stage2, ...)runs each item through all stages with no barrier between them,phase()/log()drive the progress view. Subagents inherit the session model and effort unless overridden. - Files are the interface. Every stage reads and writes artifacts at agreed paths (JSON, Markdown, PNG, WAV), so
agents never need each other's context. Two documents act as shared sources of truth: thestyle bible (
bible/, written by the research workflow) and theepisode script (production/script/episode.json, written by the writers' room). Each script starts with one sharedCTXstring (goal, resource map, rules) that every agent in it receives. - Agents get measurements, not impressions. They can't listen, and looking at images is expensive, so the tooling gives them numbers (pixel line widths, fundamental frequency, formant centroid, LUFS, Whisper word accuracy, AudioSet tags) plus side-by-side comparison images against reference frames.
- Resume after interruptions.
Workflow({scriptPath, resumeFromRunId})replays cached agent results, so the two usage-limit stalls only cost the steps that were in flight.
prompt
|
+-- [main session] yt-dlp corpus (25 videos), shot detection, Whisper large-v3 word-timed transcripts,
| measurement / audio-analysis tools, 6 fps filmstrips an agent can "watch"
v
WF1 research ------------------> bible/ (format, visual, motion, audio, writing + 5 JSON specs, ~2,200 reference images/clips)
| |
| +------------------------+---------------------------+----------------------------+
| v v v |
| WF2 writers' room WF3 art core WF4 voices |
| -> episode.json -> engine/asdf -> casting, lines, SFX, |
| (25 skits) (character + FX music, radio plays |
| drawing system) (timed audio per skit) |
| | |
| v |
| WF5 art assets (10 groups: hair, wardrobe, poses, special |
| bodies, creatures, vehicles, props, sets, FX, cards) |
v |
[main session] animator kit + one verified worked example + deterministic radio-play builder <+
|
v
WF6 lean animation (7 agents x 4 slots) --> production/skits/*/skit.py
|
v
[main session] render -> static transitions -> stem mix -> -12 LUFS master -> H.264/AAC -> contact-sheet QA -> fixes
The stages overlapped: the writers' room started as soon as the writing and format specialist reports existed, the art and voice workflows started before the bible was fully verified, and so on.
Counts are from the subagent transcripts (distinct agents; output tokens summed per unique API message).
| # | Script | What it did | Shape | Agents | Output tokens | Tool calls | Wall-clock* |
|---|---|---|---|---|---|---|---|
| 1 | wf1-research.js |
Skit-by-skit breakdown of all 25 videos + adversarial fact-check; 6 specialist deep dives; synthesis of the style bible; refute and practitioner passes; completeness critic, gap fills, integration | per-episode pipeline; specialist fan-out; per-section synth -> refute -> practitioner; critic loop | 78 | 3.38 M | 12,976 | 4.9 h |
| 2 | wf2-writers-room.js |
10 writers with different comedic mechanisms pitched 108 skits; originality filter; 3-lens judge panel; punch-up; showrunner assembly; 4-reviewer panel + revision rounds | fan-out -> barrier filter -> judges -> punch-up -> review loop | 40 | 3.95 M | 922 | 5.9 h |
| 3 | wf3-art-core.js |
Reference packs, then a character system and an FX library built in code, reviewed side by side against reference frames, up to 3 fix rounds | two parallel build -> review -> fix tracks | 40 | 2.67 M | 8,480 | 11.2 h + 1.8 h resume |
| 4 | wf4-voices.js |
Casting plan; 18 role-casting agents; per-skit recording with multi-take QA; SFX + music; per-skit radio-play editing + review | pipeline per skit | 108 | 2.20 M | 8,364 | 5.3 h + 1.8 h resume |
| 5 | wf5-art-assets.js |
Asset list derived from the final script; 10 asset-group builders; bible-conformance + fan-test reviews; fixes | per-group pipeline | 94 | 8.09 M | 16,924 | 5.3 h + 1.8 h resume |
| 6 | wf6-animate-lean.js |
28 timeline slots animated by 7 agents from a worked example, a small kit and the radio-play beats | fan-out | 7 | 0.02 M | 284 | 7.7 min |
*Workflows overlapped and include usage-limit stalls, so wall-clock times don't add up to the session length.
Two further scripts (production.js: per-skit board -> animate -> 3-lens review, art_conform.js: bible-conformance
pass) were written but not run, because the usage limit forced a leaner path.
WF1 research in detail. 45 agents wrote the per-episode breakdowns and fact-checks (each "watches" 6 fps filmstrips, waveform/spectrogram strips and word-timed transcripts and writes a JSON + Markdown breakdown with timings, dialogue, camera, joke mechanism and punch-to-cut). 6 specialists (visual, motion, audio, writing incl. TomSka's own commentary, web research with citations, format/title-card/credits) each built a curated reference library and a spec. 5 section writers synthesized the bible; 10 verifiers (a skeptic that must re-derive 12+ load-bearing claims from raw data, then a "practitioner" playing the downstream engineer who resolves every ambiguity from the data); a completeness critic found 10 gaps, 10 agents filled them, one integrated.
WF2 writers' room in detail. Writers were split by joke mechanism (literalism and puns, sudden consequence, deflation, broken logic, picture punches, inversion, runners and catchphrases, format corruption, meta, sincere objects), not by topic. 108 pitches -> 75 survived an originality filter against a catalog of every official skit -> scored in 5 batches of 15 pitches by 3 judge lenses each (authenticity via a 12-item checklist derived from the research, laugh, producibility) -> 36 finalists punched up -> showrunner built the episode (mechanism mix, runner placement, running order) -> 4 reviewers (creator's eye, superfan, newcomer, editor) -> two revision rounds.
WF4 voices in detail. One casting agent per voice role auditioned 6-9 candidates (ElevenLabs Voice Design and premade voices; no cloning of real people) and picked by measured fundamental frequency, formant centroid, Whisper word accuracy and AudioSet tags against targets measured from the originals. Recording agents generated 3+ takes per line and kept the best by the same measurements. Radio-play editors then placed lines, SFX and music on a timeline (audio-first, like the originals): the picture is animated to the finished audio.
WF6 lean animation in detail. Cheap because everything before it was well specified: a skit module contract
(N_FRAMES, AUDIO, draw(canvas, f, t, surface)), a verified worked example ( production/skits/S03/skit.py), a
~150-line kit (production/kit.py: line-synced mouths, shot dispatch, cut frames from the radio-play beats) and the
asset helpers. 7 agents wrote 28 skit modules (~1,600 lines) in under 8 minutes with ~1M total tokens.
-
Spend the tokens on a verified spec, then make execution cheap. Research was the most expensive stage and made everything after it consistent: the last stage (28 slots animated) needed 23k output tokens.
-
Give every claim-maker an adversary. Fact-check each breakdown; refute-by-rederivation each bible section; a practitioner pass where the downstream consumer tries to use the document.
-
Orthogonal lenses beat repeated reviews. Writers by mechanism; judges by authenticity / laugh / producibility; art reviewers by construction / line work / acting / "fan test".
-
Originality as a hard filter. A machine-readable catalog of every official skit (
bible/skit_catalog.json) lets an agent drop anything that echoes an existing joke before anyone judges it. -
Numbers over adjectives. Every audio and drawing stage had measurable acceptance criteria (f0, formants, LUFS, line width in px at 1080p as a function of head size, hex colours, frame timings), so agents could self-check.
-
Deterministic code where it exists. Once the budget got tight, the main session wrote a ~250-line radio-play builder (re-anchor events when a take overruns, place SFX/beds/music, truncate at the slot end) and finished 11 missing radio plays with zero agent spend. The final assembly and mastering chain are plain Python + ffmpeg.
-
Worked example + kit beats a long brief. One verified example skit and a thin helper layer let 7 agents do the last stage in minutes.
-
QA from the delivered artifact. Contact sheets cut from the final MP4 (8 frames per slot) caught placeholder credits and an unintended blurred foreground that the per-skit checks had missed.
-
Usage limits. Hit twice; in-flight agents returned errors and had to be resumed. Cap review loops, set
effortexplicitly per agent (agents inheritmaxotherwise), and switch the model for the tail of the run (the first ~270 subagents ran on Opus 5.5, the last ~70 on Sonnet 5.5). -
Unbounded review loops. The art-core reviewers kept finding new nits (parity scores crept from about 5 to 7 over three rounds and 11 hours). Stop on score delta, not on "no issues".
-
Content filter. Three writers'-room agents were blocked on dark-comedy material; the run was designed so a missing agent just drops out of the pipeline.
-
Tooling gotchas. ElevenLabs raw PCM output needs the Pro tier (used MP3 -> WAV), SFX have a 0.5 s minimum, Whisper hallucinates on screams (use RMS envelopes), Windows needs
multiprocessingfrom real files not stdin,Workflowrejects scripts containing CRLF, and shell heredocs eat backslashes (write scripts with a file tool). -
Age-restricted uploads (asdfmovie7, 11) can't be downloaded without cookies; they were cut from the official 1-15 compilation instead.
| Wall-clock, first prompt -> final MP4 | ~19 h (includes two usage-limit stalls) | | Subagent transcripts | 367 (about 420 agent runs counting cached replays on resume) | | Subagent API calls / tool calls | 36,642 / 47,950 | | Subagent output tokens | 20.3 M (the Workflow tool's own "subagent tokens" counter reports ~135 M in total; its exact definition isn't documented) | | Main session | 259 API calls, 316 tool calls, 0.42 M output tokens | | Models | main session: Opus 5.5 (0.26 M output tokens) then Sonnet 5.5 (0.16 M); subagents: ~272 on Opus 5.5, ~67 on Sonnet 5.5, ~28 stubbed by usage-limit errors | | Hardware | Windows 11, RTX 5090 (32 GB), 32 logical CPUs; Whisper large-v3 on the GPU |
| Videos analysed | 25 (16 episodes, 4 deleted-scene reels, asdfmite, 3 micro-shorts, the credits), 42 min, 961 detected shots | | Transcripts | 25 Whisper large-v3 word-timed + 16 manual caption files, plus 3 commentary videos | | Per-episode breakdowns / specialist reports | 25 / 7 | | Style bible | 6 sections + 10 gap notes, ~162k words, 5 JSON specs | | Reference library | ~2,200 images/clips (visual 80, motion 32, audio 73, format 267, writing 62, gaps 70, art 1,581) |
| engine/ (render, timing, audio, ElevenLabs, QA) | ~1.0k lines + the engine/asdf drawing engine, ~17.9k lines |
| production/ | glue ~1.1k lines, asset modules ~37.8k lines (11 files), 28 skit modules ~1.6k lines |
| Agent-written analysis scripts ( research/scratch ) | 683 files, ~36k lines |
| Workflow scripts | 8 files, ~800 lines JavaScript (6 executed) |
| Audio | 83 TTS line files, 91 per-skit SFX + 59 library SFX, 20 music cue files, 28 radio plays |
| Art | 281 asset sheets, 33 engine model sheets |
| Disk | ~24 GB working tree (research scratch 13 GB, production caches and renders 6.4 GB, videos 2.1 GB) |
42,439 of 90,000 monthly credits used (TTS, sound effects and music share the pool); 8 of 10 custom-voice slots; voice
roles: 6 designed voices, 11 premade voices, 1 sung-jingle role via the Music API; TTS models eleven_v3, eleven_v4,
eleven_multilingual_v2; Music music_v2_5 with composition plans.
The project lived in C:\dev\video (not a git repo during the run). This is the layout to recreate; paths in the
workflow scripts are absolute under that root (a ROOT constant at the top of each), so change it if you move it.
video/
|-- .env # ELEVENLABS_API_KEY=... (never commit)
|-- engine/ # reusable code
| |-- core.py # skia raster surface -> raw RGBA -> ffmpeg; render(), still(), contact_sheet()
| |-- timeline.py # easing curves, keyframe tracks, camera shake, beat sheet
| |-- audio.py # , rubberband pitch/formant, stem mixer, EBU R128 master
| |-- eleven.py # cached ElevenLabs client: TTS with timestamps, SFX, Voice Design
| |-- music.py # ElevenLabs Music (composition plans, lossless output) + analysis
| |-- voice.py # per-line processing chain + QA (Whisper accuracy, f0, centroid, LUFS)
| |-- static.py # TV-static frames and hiss matched to measured statistics
| |-- review.py # filmstrips, side-by-side compares, audio reports
| |-- qa/ # voice / mix QA tools, AudioSet tagger
| `-- asdf/ # the asdfmovie drawing engine: characters, faces, hands, poses, lip-sync,
| # camera, FX, pen/ink composition, traced replacement drawings (data/)
|-- bible/ # the style bible written by WF1 (source of truth for every later stage)
| |-- 00_INDEX.md 01_format.md 02_visual.md 03_motion.md 04_audio.md 05_writing.md
| |-- *_spec.json skit_catalog.json
| `-- gaps/ # gap-pass research notes
|-- research/ # analysis corpus (large, copyrighted source material; do not publish)
| |-- README.md # data layout handed to every research agent
| |-- dl.sh subs_all.sh run_all.sh # yt-dlp download + batch analysis drivers
| |-- meta/episodes.tsv # video key -> YouTube id/source
| |-- tools/ # shots.py measure.py audio.py transcript.py whisper_all.py
| |-- videos/ frames/ audio/ subs/ # downloads, shot sheets + 6 fps filmstrips, waveforms, transcripts
| |-- analysis/{episodes,specialists}/ # WF1 outputs: 25 breakdowns, 7 specialist reports
| |-- refs/{visual,motion,audio,format,writing,gaps,art}/ # curated reference libraries
| `-- scratch/ # every research agent's working scripts and notes
|-- production/
| |-- workflows/ # research.js writers_room.js art_core.js art_assets_a.js voices.js animate.js
| | # (+ production.js, art_conform.js: written, not run)
| |-- script/ # episode.json / episode.md (the final script), credits.json
| |-- audio/ # casting/ lines/ sfx/ music/ radio/ (radio/<id>.wav + .beats.json per slot)
| |-- assets/ # 10 asset modules + ASSET_LIST.md (cast_*, creatures, vehicles, props, sets, ...)
| |-- skits/<id>/skit.py # one module per slot: S00..S24, TITLE, CREDITS, END
| |-- kit.py radio.py sfxlib.py render_skit.py check_skit.py assemble.py qa_sheets.py
| |-- art/ # model sheets, asset sheets, parity compares
| |-- build/ # assembled picture/master audio, timeline.json, QA contact sheets
| `-- cache/ # ElevenLabs request cache (never pay twice), processed audio
`-- output/ # asdfmovieish.mp4, _master_hq.mp4, _preview_720p.mp4
Suggested .gitignore: .env, research/videos/, research/frames/, research/audio/, research/scratch/,
production/cache/, production/build/, production/skits/*/render.mkv, production/skits/*/_parts/, output/.
Agents are non-deterministic, so you will get a different episode, but the structure reproduces.
- Environment. Python 3.10, Node 24, ffmpeg 8.x (libx264 + rubberband), an NVIDIA GPU for Whisper large-v3 (CPU
works but is slow).
pip install yt-dlp scenedetect librosa soundfile pyloudnorm skia-python pycairo opencv-python scikit-image scikit-learn matplotlib pillow requests openai-whisper transformersplus a CUDA build oftorch/torchaudio. PutELEVENLABS_API_KEYin.env(Starter is enough: v3/v4 TTS, sound effects, Music). - Corpus. Download the official episodes with
yt-dlp --js-runtimes node(list inresearch/meta/episodes.tsv; age-gated ones are cut from the official compilation), then run the analysis tools:research/run_all.sh(shots, measurements, audio) andpython research/tools/whisper_all.py. - Research ->
Workflow({scriptPath: "production/workflows/research.js"})buildsresearch/analysis,research/refsandbible/. - Script ->
writers_room.jswritesproduction/script/episode.json. Runart_core.js(drawing engine) alongside it; once the script exists runvoices.jsandart_assets_a.js. - Glue.
production/kit.py,production/radio.py(finishes any radio play the agents didn't) and a worked example skit (production/skits/S03/skit.py). - Animate ->
animate.js(7 agents x 4 slots), thenpython -m production.check_skit <ids...>. - Assemble and master ->
python -m production.assemble --force-render->output/asdfmovieish.mp4.python production/qa_sheets.pycuts per-slot contact sheets from the result for review. - Share encode (44 MB):
ffmpeg -i production/build/picture.mkv -i production/build/master.wav -map 0:v -map 1:a -vf "scale=out_color_matrix=bt709:out_range=tv,format=yuv420p" -c:v libx264 -preset slow -crf 22 -maxrate 5M -bufsize 10M -tune animation -c:a aac -b:a 192k -movflags +faststart out.mp4
If a workflow is interrupted (usage limit, crash), re-launch it with the same scriptPath and resumeFromRunId to
replay finished agents from cache. Credits text lives in production/script/credits.json.
- Review was thin at the end. After the usage limit hit twice, the remaining multi-round reviews were dropped: each skit was animated once with self-review from stills, followed by one pass over the assembled video. Expect small rough edges (a boulder that reads like a cupcake, an oversized ponytail).
- Nobody has listened to the audio. It was checked with measurements (levels, Whisper transcripts, tag classifiers), not by ear; comedic timing in the audio is unverified by a human.
- Some drawings derive from reference frames. The drawing engine includes a handful of replacement drawings (hands, a walk and a run cycle) traced from official frames as style references. Decide whether that suits your use before redistributing.
- Source material. The downloaded episodes and the 6 fps filmstrips cut from them are copyrighted; keep them out of any public repo.
- Not measured: the dollar cost of the run.