walid@portfolio:~/lab/motion-as-code$
cd../lab
06ideaOct 2026

Motion graphics as code, timed to a voiceover

A starter kit for explainer animation with no After Effects: every scene a TypeScript function of time, word-level timings from forced alignment, a headless-Chrome renderer and a scripted sound mix. The kit’s full workflow guide, its demo prompt, and the 92-second video it renders, with sound. Built on the open-source pdoom-video engine, and checked against its code

An explainer video in which nothing is keyframed by hand. Each scene, called a plate, is a TypeScript file that draws every frame from the clock; word-level timings of a voiceover tell each plate when to move, so the picture stays locked to the voice; a script drives headless Chrome to render the frames and ffmpeg turns them into an MP4. Because it is all code, you change the animation by asking Claude to change the code. This is the kit’s whole workflow guide and the 92-second video it renders, sound included. The kit’s own files weren’t part of what was shared, but its engine is public, so the preview and render half works from the open-source pdoom-video today. The checks found the engine matches the guide closely, and fixed two example commands that point at the wrong moment.

Motion graphicsClaude Codethree.jsTypeScriptbunVideopdoom-video (the engine) ↗pdoom-video’s own music video ↗bun ↗three.js ↗Vite ↗Playwright browser channels ↗FFmpeg ↗uv ↗ElevenLabs sound effects API ↗ElevenLabs: publishing what you generate ↗wav2vec2-base-960h ↗Claude Opus 5.5 ↗The AI production studio, in the Lab ↗
i
What this is

A workflow guide for a starter kit called Motion as Code, and the video the kit produces: a 92.6-second, 1920x1080, 60 fps explainer whose opening line is “What if I told you you can create motion graphics like this without even opening After Effects?”. The kit is built on pdoom-video, an MIT-licensed engine for code-rendered video, which its author says he built with Claude Opus 5.5 in Claude Code. The kit’s own files (its nine plates, voiceover, sound effects and analysis scripts) weren’t included and don’t appear to be public; the engine underneath is, and the commands below are marked where they work on it as well.

The 92-second explainer the kit renders, filmed playing on a laptop (a phone capture, so not the render’s full quality). Play it for the voiceover; every word of it is in the table below.
Checked, not copied

What held up, on 9 October 2026

Checked against pdoom-video’s code and full public history (14 commits, 24 September to 5 October 2026), read rather than run; the video’s soundtrack and frames; and the uv, Playwright, ElevenLabs, Hugging Face and Anthropic pages. Claims about the kit’s own files can’t be checked, and say so.

ClaimWhat the source says
The engineReal: github.com/mexicat/pdoom-video, MIT, about 2,500 stars. TypeScript and three.js run with bun and Vite, 1920x1080 logical pixels, 60 fps export. Its README says the whole music video it was made for was worked out with Claude Opus 5.5 in Claude Code.
Preview, keys and file layoutMatch the engine exactly: cd app, bun install, bunx vite on port 5173, every key in the table, ?t= to start at a time, the Scene class with render(f, out), the f.t, f.lt, f.p, f.a and f.seeked fields, and E() lines in timeline.ts.
The stills exampleFixed. The guide asks for “the code plate at 12.5 s and 40.2 s”, but its own table puts 12.5 s inside the model plate, and with --only the engine paints a placeholder there instead. Now 38.5 and 40.2 s, both inside the code plate.
The demo prompt’s stillFixed. It renders 89.5 s to show the final “pretty insane.” slam, which lands at about 91.9 s in the video; 89.5 s is two seconds earlier. Its rule “do not run the full 4K render without asking” also left a full 1080p render unguarded, against the guide’s “nothing is rendered in full without your say-so”. Both are changed: the stills are now at 92.2 s, once the slam has landed, and inside the added hold, where the edit shows.
“Automatic motion blur (4 to 12 sub-frames)”Can’t be checked, and not the engine’s default. Uncapped, its adaptive sampler gives every frame at least 12 sub-frames, up to 324 where motion is fast; caps can lower that (--max-samples for the whole render, or a maxSamples setting on a plate’s timeline entry, which can take that plate down to 4). So 4 to 12 means either the kit caps its render or the guide’s figure is off; its package.json and timeline.ts weren’t shared. Against an uncapped render, --samples 4 means at least 3x fewer sub-frames, and more wherever something moves, rather than the guide’s flat “about 4x”.
Kit-only piecesbun run render, BROWSER_CHANNEL, the _vo.ts toolkit, lineOf, the 0.18 s cut offset, align_vo.py, audio_vo.py, sfx_mix.py and .claude/ appear in no public commit of the engine; they are the kit’s additions. The soundtrack is consistent with the 0.18 s: at six of the eight cuts, the voice starts 0.18 s after the guide’s cut time, to within 0.05 s; the other two start under sound effects and can’t be timed as precisely.
The ~95 MB alignment modelThe guide says only “wav2vec2, quantized ONNX”, not which checkpoint. The size matches the public quantized ONNX export of wav2vec2-base-960h (Meta, Apache-2.0), so that is the likely one. The engine’s own aligner is far heavier: Demucs vocal separation, two PyTorch wav2vec2 models and a Whisper cross-check.
“python -m uv”Works only if uv was installed with pip into that Python, and on a Mac that Python is usually called python3, since macOS has no bare python command. Installed any other way (Astral’s installer, Homebrew, winget, pipx), type uv directly. The newest onnxruntime, for the align step, wants Python 3.11 or newer; on an older Python, uv falls back to an older release (1.23.2 on Python 3.10).
-14 LUFSA sound target, and Spotify’s documented one. YouTube publishes no figure, though it is widely measured at the same level. The engine itself has no sound-effects mixer; that step is the kit’s.
Fonts “covered by the MIT licence”No. MIT covers the engine’s code; Archivo, IBM Plex Mono and Cormorant Garamond are under the SIL Open Font License, and the single-stroke fonts are OFL or public domain.
ElevenLabsSound Effects v2 is real (model eleven_text_to_sound_v2). On the free plan nothing may be used commercially, and anything published must carry elevenlabs.io or 11.ai in its title; paid plans include a commercial licence.
The videoEvery spoken line falls inside its plate’s window; the cuts in the recording come about 0.2 s before the table’s times. It is a phone capture, 92.5 s, portrait, of the 1920x1080 render, and stops on the final slam, so the loop back to frame 0 isn’t shown. Claude Opus 5.5 is a real Anthropic model (claude-opus-5-5, released 22 September 2026), and After Effects MCP servers do exist, all community-made.
The nine plates

One frame from each, in order

Frames pulled from the video, each labelled with the plate’s window from the guide. The guide’s table times are good to about 0.2 s.

What the video says, plate by plate

The full voiceover, transcribed from the video. The guide’s own table abbreviates these lines.

PlateSecondsNarration
hookSeconds0.0 – 9.9Narration“What if I told you, you can create motion graphics like this without even opening After Effects? And no, I’m not talking about an After Effects MCP.”
modelSeconds9.9 – 19.2Narration“This is Claude Opus 5.5. Instead of controlling After Effects, you basically tell Claude what you want the animation to look like.”
promptSeconds19.2 – 29.7Narration“For example: create a 15-second cinematic motion graphics sequence with kinetic typography, smooth shape transitions, 3D elements and seamless camera movement.”
crazySeconds29.7 – 35.4Narration“And this is where it gets crazy. Claude doesn’t actually generate an MP4 directly.”
codeSeconds35.4 – 48.0Narration“It writes the animation itself as code. The text, shapes, positions, easing, transitions, particles. Basically every visual element is defined mathematically over time.”
framesSeconds48.0 – 52.1Narration“Then, that code is rendered frame by frame and turned into a video.”
pipelineSeconds52.1 – 62.6Narration“So instead of After Effects to layers, to keyframes, to graph editor, to render, you’re essentially doing prompt to code to render to video.”
editsSeconds62.6 – 80.6Narration“And because the animation is procedural, you can literally tell Claude: make this transition smoother, change the color, slow this section down, make the ending seamlessly loop into the beginning. And it can modify the underlying animation instead of you manually moving hundreds of keyframes.”
verdictSeconds80.6 – 92.6Narration“Does this replace After Effects? Not really. But for certain types of motion graphics, the fact that you can go from an idea to a working animation without touching a timeline is pretty insane.”

Two of those lines want a footnote. “Without touching a timeline” means without a timeline editor: the edit still lives in a timeline, a code file called timeline.ts. And “prompt to code to render to video” leaves out the voiceover, the word alignment and the sound pass, which the guide adds back below.

01 / Overview

What you are getting

The kit is a complete, working example of the prompt, code, render, video workflow. It produces the 92.6-second, 1920x1080, 60 fps explainer above.

Nothing in it is keyframed by hand. Each scene, called a plate, is a TypeScript file that draws every frame as a function of time. Word-level timings of the voiceover tell each plate when to animate, so the picture is locked to the voice.

Because it is all code, you can ask Claude to change the animation (a colour, a speed, a transition, a whole new plate) and re-render, instead of moving hundreds of keyframes.

The six stages

Stages 3 to 5 are the pdoom-video engine and work from its public repository. Stages 1, 2 and 6 are the kit’s additions for a spoken voiceover.

1

Voiceover

audio/voiceover.mp3, made with ElevenLabs.

2

Align

align_vo.py and audio_vo.py turn the voiceover into word-level timings and loudness data.

3

Scenes

scenes/*.ts, one file per plate, and timeline.ts, which says when each plays.

4

Preview

Vite, live in the browser at localhost:5173.

5

Render

render.ts drives headless Chrome to draw the frames and ffmpeg to encode them.

6

Sound

sfx_mix.py mixes the sound effects under the voice; ffmpeg puts the mix onto the picture.

i
Every frame is a function of time

The preview and the exported MP4 are drawn by the same code from the same time value, so what you scrub to is what renders. (The guide calls them identical; they aren’t quite, since the export averages motion-blur sub-frames and the preview doesn’t.) Re-timing works the same way: change the voiceover, re-run the alignment, and the plates find their words by content rather than by fixed times. Reload the page afterwards, since the timing data is read once at start-up. In pdoom-video, an anchor phrase in timeline.ts that is no longer in the script stops the whole preview from loading, with “lyric not found” shown in red, until you update the cut(...) phrase; the kit’s own cut() and lineOf weren’t available to check. Moves with a fixed length inside a plate keep that length.

02 / Setup

What goes in the zip

Include these folders and files. Leave out out/ (the renders; the guide puts them at over 2 GB) and app/node_modules (rebuilt by the install step).

IncludeWhy
app/The renderer: engine, scenes, timeline, fonts, render script.
audio/The voiceover and the 28 sound effects.
data/Pre-computed word timings and audio analysis, so you can preview straight away.
analysis/Alignment and sound-effect mix scripts. The 95 MB ONNX model in analysis/models is only needed to re-align a new voiceover.
README.md, LICENSE.pdoom-engine, .claude/Project guide, engine licence, one-click preview config.

Paste it into your project

The guide says to unzip, then copy the contents into the folder you work in (your Claude Code project folder, or add the folder to the project’s files), and to keep the folder structure exactly as it is, because the scripts use relative paths.

One change worth making: unzip it into a folder of its own and start Claude Code there, rather than copying it over an existing project. The zip’s README.md and .claude/ would replace yours, and the .claude/ folder (most likely a preview configuration for the Claude Code desktop app) is worth reading before you use it, since project settings there can run commands.

Requirements

✓bun (bun.com): installs packages and runs the scripts. The render script uses bun-only features, so Node won’t do.✓Google Chrome: the renderer drives it headlessly to draw frames.✓ffmpeg built with libx264: encodes the frames into an MP4 and adds the sound to it (the guide says it mixes the sound; the mixing is sfx_mix.py’s job). ffmpeg -hide_banner -encoders | grep libx264 should print a line (in Windows PowerShell, end it with | findstr libx264 instead).✓Python and uv, only to re-align a new voiceover or rebuild the sound-effect mix. The guide says to run uv as python -m uv, which works only if uv was installed with pip into that Python, and on a Mac that Python is usually python3; if you installed uv any other way, type uv instead. Python 3.11 or newer gets the current onnxruntime for the alignment step.

First run

From the project root. Open the address Vite prints, normally http://localhost:5173, and press space (or click the frame) to play; the voiceover plays with it. If a render later can’t find Chrome, see the troubleshooting table at the end.

first-run3 lines
cd app
bun install
bunx vite
No kit? Use the public engine

The same preview, from pdoom-video

The engine’s repository has the same layout, the same preview and the same keys, with its own music video as the example: seventeen plates timed to a song instead of nine timed to a voice. Not in the guide.

pdoom-video-preview4 lines
git clone https://github.com/mexicat/pdoom-video.git
cd pdoom-video/app
bun install
bunx vite

Its documented render, from the repository root. The engine has moved on since the kit was built: current versions decide motion blur for each 32x32 tile of the frame and run two renderers at once.

pdoom-video-render2 lines
cd app
bun scripts/render.ts video --samples auto --shutter 0.2 --out ../out/pdoom.mp4
03 / Workflow

1. Preview, live

The preview is the fast loop. Edit a scene file and the page hot-reloads; scrub back to the moment you changed. Add ?t=35 to the address to start at 35 s (it stays in the address, so each reload starts there too).

KeyAction
spaceplay / pause
left / rightseek 1 s (5 s with shift)
, and .step one frame
[ and ]previous / next plate
lloop the current plate
hhide the UI

2. Check stills while editing

Renders single frames, here two moments in the code plate, so you can inspect a detail without rendering the whole video. Changed from the guide, whose example asks for 12.5 s, which is in the model plate: with --only the engine draws a placeholder there. The quotes around the times keep PowerShell from splitting the list; they’re harmless elsewhere.

check-stills2 lines
cd app
bun scripts/render.ts stills --t "38.5,40.2" --only code --out ../out/wip

3. Render the video

The kit’s shortcut, from its package.json; written to out/motion-as-code.mp4. It runs render.ts with adaptive motion blur (the guide says 4 to 12 sub-frames a frame; uncapped, this engine gives 12 or more, more where motion is fast, so either the kit caps it or the figure is off, which can’t be checked), a shutter of 0.5 and CRF 17. A flag the shortcut already sets, such as --samples, is ignored if you add it after bun run render, because render.ts reads only the first copy of a flag; one it doesn’t set, such as --scale 2, can simply be added. To change one it sets, run render.ts yourself with the shortcut’s other settings and its output name, so you keep the motion blur and the sound step below still finds the file, for example: bun scripts/render.ts video --samples 4 --shutter 0.5 --crf 17 --out ../out/motion-as-code.mp4 (check the kit’s package.json for its exact flags).

render-video2 lines
cd app
bun run render

Useful flags

FlagEffect
--samples 4A quick draft: 4 sub-frames a frame. Against an uncapped --samples auto, which gives 12 or more, that is at least three times fewer, and more on moving frames; if the kit’s shortcut caps it, as the guide’s 4 to 12 suggests, the saving is at most three times, and none on plates it already holds to 4 (the guide says “about 4x faster”). Fast moves show stepped copies.
--samples autoMore sub-frames where motion is fast (the shortcut’s setting).
--scale 2A true 4K render, 3840x2160, not an upscale. Heavy: the engine’s own 156-second song takes about an hour on an M5 Pro Mac with the current engine.

4. Add sound effects

There are 28 sound effects in audio/sfx and a cue sheet of about 500 cues in analysis/sfx_mix.py, derived from the same word timings. Effects duck up to 7 dB under the voice and the mix is normalised to -14 LUFS, the loudness Spotify plays at and YouTube is widely measured at. No re-render is needed: rebuild the mix, then copy the picture and add the audio.

To make an effect louder or quieter, change its db value in the cue sheet. To move one, change its time expression. This mixer is the kit’s own; the engine has none.

Rebuild the mix, from the project root: the render step above left you in app/, so cd .. first. The guide runs uv as python -m uv, which works only if uv was installed with pip into that Python; on a Mac that Python is usually python3, since macOS and Homebrew don’t put a bare python on the PATH. If uv was installed any other way, drop the python -m and type uv directly.

sound-effects1 lines
python -m uv run --no-project --with numpy python analysis/sfx_mix.py

Then put the mix on the picture. mix.wav carries the voice as well as the effects, which is why the render’s own audio track is dropped. For a file you will host on the web, add -movflags +faststart. The backslash continues the line in macOS and Linux shells; in PowerShell, put it all on one line.

mux-sound3 lines
cd out
ffmpeg -i motion-as-code.mp4 -i mix.wav -map 0:v -map 1:a \
  -c:v copy -c:a aac -b:a 320k -shortest motion-as-code_sfx.mp4

5. Swap the voiceover

1

Replace audio/voiceover.mp3

With your own read of the script.

2

Edit SCRIPT, and SPOKEN for numbers and acronyms, in analysis/align_vo.py

SPOKEN gives letters-only spellings for anything the alignment model can’t read, such as Opus 5.5, MP4 or 3D, because it only knows letters and apostrophes. The engine does the same thing in its pron.py.

3

Re-run the alignment and audio analysis

The commands are below. The plates find their words by content (the kit’s lineOf and wordOf helpers), so if you keep the same script, every animation re-times itself to the new read, as the guide puts it; strictly, that is every cut and word-synced move, since fixed-length moves inside a plate keep their length.

From the project root: the sound step left you in out/, so cd .. first. The python -m uv note above applies here too: on a Mac use python3 (a bare python usually isn’t on the PATH), or type uv directly if uv wasn’t installed with pip.

realign-voiceover2 lines
python -m uv run --no-project --with onnxruntime --with numpy python analysis/align_vo.py
python -m uv run --no-project --with numpy python analysis/audio_vo.py
04 / Reference

How the project fits together

PathRole
audio/voiceover.mp3The voiceover (made with ElevenLabs).
data/lyrics.jsonWord-level timings, in the engine’s format. Made by align_vo.py with CTC forced alignment (wav2vec2, a quantized ONNX model), refined against the audio’s silences.
data/audio.jsonVoice loudness envelopes, word onsets and a nominal beat grid, which the engine expects even for speech. Made by audio_vo.py.
app/src/engine/The pdoom-video engine: WebGL, post-processing, type, strokes, timeline playback, motion blur. Leave this alone.
app/src/scenes/_vo.tsThe kit’s shared toolkit: 2D camera, the plotter pen, world-space karaoke words, graph paper.
app/src/scenes/*.tsThe nine plates.
app/src/timeline.tsWhen each plate plays. Cuts sit in the pause just before each line.
app/scripts/render.tsOffline renderer: headless Chrome draws raw frames, ffmpeg encodes them.

Writing or changing a plate

A plate is a class that extends Scene (app/src/engine/scene.ts), and its file exports it as the default. The rule that matters: everything must be a deterministic function of time: no Math.random() or clock readings (seeded random numbers from the engine’s mulberry32 or hash are fine). The engine calls render(f, out) for every frame, and in the export for every motion-blur sub-frame too, out of order (the guide says once per frame), so a plate must never count its calls. f carries:

✓f.t, the voiceover time; f.lt, the time since the plate started; f.p, progress from 0 to 1 through the plate.✓f.a, the audio features at that moment: the voice envelope (f.a.vocal) and hit pulses such as word onsets (f.a.vonset).✓f.seeked, true after a scrub. Stateful plates reset on it.

To add a plate, create app/src/scenes/yourplate.ts, then add one E('yourplate', 'yourplate', start, end) line to timeline.ts: the first argument is the plate’s id, the second its file name. Start times come from the script: in the kit, cut('This is Claude') cuts 0.18 s before that line’s first word. (The engine itself snaps cuts to a song’s beat instead.)

The example prompt shown inside the video, in the prompt plate, draws its token breakdowns from app/src/scenes/prompt-data.ts. Edit that file to change the words and the next-token candidates it displays. That panel, and the file’s format, come from the engine’s own prompt plate.

05 / Demo prompt

Copy this into Claude

After the folder is in place, open Claude Code in it and send this. It verifies the install, makes one visible edit, then walks you into using your own voiceover. Changed from the guide: the stills are at 92.2 s, once the slam has landed (it lands at about 91.9 s in the recording, whose cuts come about 0.2 s before the guide’s times, so 92.2 s is safe either way; the guide’s 89.5 s is about two seconds before the slam), and inside the added hold, where the edit actually shows, since a still at the slam alone looks the same before and after it; and the last rule covers any full render, not just 4K, so nothing renders in full without your say-so.

demo-prompt.txt24 lines
I've added the "Motion as Code" project to this folder. Read README.md first, then
app/src/timeline.ts and app/src/engine/scene.ts so you understand how plates and
timing work.

Step 1 - verify:
  cd app, run bun install, start the preview with bunx vite, and confirm the video
  plays at localhost:5173 with no console errors. Tell me what you see.

Step 2 - one small change to prove it works:
  In the 'verdict' plate (app/src/scenes/verdict.ts), change the final full-frame
  "pretty insane." slam so the words hold for 0.3 s longer before the implode.
  Keep it a pure function of time and keep the loop back to frame 0 intact.
  Render two stills, one at the slam and one inside the added 0.3 s (work that
  time out from verdict.ts), with:
  bun scripts/render.ts stills --t "92.2,<that time>" --only verdict --out ../out/wip
  and show them to me.

Step 3 - make it mine:
  Ask me for my voiceover (mp3) and script. Then update analysis/align_vo.py
  (SCRIPT and SPOKEN), re-run the alignment and audio analysis, and tell me which
  plate cuts in timeline.ts need new anchor phrases.

Rules: do not edit app/src/engine/. Do not run any full render (1080p or 4K)
without asking. Explain each change in one or two sentences before you make it.

Ideas for your own follow-up prompts

✓“Make the transition into the code plate smoother and slower.”✓“Change the accent colour from signal orange to electric blue everywhere.” This one needs an edit to app/src/engine/palette.ts, where the orange is defined, so tell Claude it may touch that file.✓“Slow the pipeline plate down by 20% without changing the voiceover timing.”✓“Add a new plate between frames and pipeline that shows a loading bar.”✓“Render the whole video with --samples 4 as a fast draft.”

The example prompt used in the video itself. You can paste it into Claude as a plain test of the idea; it asks for 15 seconds, so it isn’t the prompt that made the 92-second explainer.

example-prompt.txt3 lines
Create a 15-second cinematic motion graphics sequence with kinetic
typography, smooth shape transitions, 3D elements and seamless camera
movement.
06 / Help

Troubleshooting

ProblemTry this
Blank page at localhost:5173Run bun install inside app/ first, and check the terminal running vite for errors. A start-up failure also shows in red on the page.
No sound in the previewPress space to start playback; the voiceover is played by the page, and the browser may block it until you interact. Check the tab is not muted.
Render cannot find ChromeInstall Google Chrome. The renderer launches the 'chrome' channel through Playwright. The kit’s render.ts reads a BROWSER_CHANNEL environment variable (msedge, for example) to use another installed browser; in pdoom-video, change channel: 'chrome' in app/scripts/render.ts instead.
Render fails on Windows or Linuxpdoom-video was developed on a Mac, and every public version of its render.ts starts Chrome with a Mac-only graphics flag, --use-angle=metal; the kit’s render.ts wasn’t available to check but most likely does the same. Ask Claude to adjust the launch flags for your system.
ffmpeg not found / no libx264Install a full ffmpeg build and make sure ffmpeg -version works in a new terminal; ffmpeg -hide_banner -encoders | grep libx264 (| findstr libx264 in PowerShell) confirms the encoder.
Render is very slowUse --samples 4 for drafts. Check single frames with the stills command, or render one plate as a clip with video --from, --to and --only, giving it its own --out (such as ../out/wip/plate.mp4) so it doesn’t overwrite the full render. (The guide says to render single plates with the stills command; stills renders single frames.)
The render reloads halfwayrender.ts uses the preview already running on port 5173 if there is one, so saving a file mid-render reloads it. Don’t edit during a render, or stop the preview first.
Animation drifted after a new voiceoverRe-run both analysis scripts and reload the page. If the wording changed, update the phrases in the cut(...) calls in timeline.ts.
Scene module not foundThe file name in timeline.ts, the second argument of E(), must match a file in app/src/scenes/.

Credits and licence

The visual language is the engine and style of pdoom-video by mexicat (Giacomo Magnanini). Its code is MIT-licensed, included in the kit as LICENSE.pdoom-engine; keep that file with the project. That covers the palette (ink, bone, signal orange), the spark motif, the graph-paper construction sheets and the post-processing (bloom, halation, grain). The fonts that ship with it keep their own licences: Archivo, IBM Plex Mono and Cormorant Garamond under the SIL Open Font License, and the single-stroke plotter fonts under OFL or public domain. (The guide puts the fonts under the MIT licence too.)

The guide says the nine plates themselves are new and were written for this voiceover; the prompt plate’s next-token panel and its prompt-data.ts format come from pdoom-video’s own prompt plate. The voiceover is by ElevenLabs, and the sound effects were generated with ElevenLabs Sound Effects v2. Check the terms of your own ElevenLabs plan before publishing a video that uses your own generated audio: on the free plan it can’t be used commercially and its title must credit elevenlabs.io or 11.ai. The alignment model, wav2vec2 (most likely Meta’s wav2vec2-base-960h, Apache-2.0), isn’t credited in the guide.

i
Provenance

Built from the kit’s seven-page workflow guide and the 92-second video it renders, both kept in full, with the guide’s main corrections marked where they apply and summed up in the table at the top. The narration was transcribed from the video. Checked on 9 October 2026 by reading pdoom-video’s code at commit fa164b7 and its full public history, without running any of it; the kit predates the engine’s 5 October changes, so it is built on the version of 2 October or earlier. Commands that only exist in the kit say so.