kritikmodi/product-video-as-code

Build product videos from your IDE instead of a video editor

7

stars

11

commits

Python

primary language

Aug 31, 2026

updated

claude-code
claude-skill
developer-marketing
devrel
ffmpeg
playwright
screen-recording
text-to-speech
video
video-as-code
Browse cluster: Video editing and automation tools

README

Product video as Code

Build product videos from code instead of a video editor: an animated HTML deck, an AI voiceover, real screen recordings, and a mastered audio mix, rendered deterministically to MP4 with ffmpeg.

Product demos, feature launches, explainers, walkthroughs, tutorials, release notes, onboarding, title stings, social cuts - one pipeline, different shapes.

script.json ──► TTS ──► measure ──► timings.json ──► render ──► composite ──► mux ──► MP4

The bundled starter deck, rendered by the pipeline

The clip above is templates/deck.html rendered straight through scripts/render.py with no narration, no API keys and no editing - exactly what a clean clone produces in about a minute. Full quality MP4 (1080p, 30fps).

Why this exists

Video is usually the one asset an AI assistant cannot iterate on. Every revision means reopening an editor and redoing the work by hand - so software videos go stale the moment the product moves.

Treating video as code changes that. The deck is HTML, the timeline is a pure function of t, and the audio is measured rather than guessed. "Reword scene 4, add banks to the segment list, and cut it under a minute" becomes a two-minute change instead of an afternoon. Re-shooting a demo after a UI change is a script run, not a reshoot.

The core idea

Audio first, then timing, then picture.

Generate the narration before deciding how long anything is on screen. Measure each clip, derive scene durations from those measurements, then render. Guessing durations - or writing narration to fit a fixed storyboard - produces visuals that drift out of sync and forces a rebuild every time a line changes.

Install

git clone https://github.com/kritikmodi/product-video-as-code.git

Any agent. AGENTS.md at the repo root is read natively by Codex, Cursor, Copilot, Gemini CLI, Aider, Windsurf, Zed and others, so cloning it into your project is enough.

Claude Code / claude.ai. Install it as a skill so it loads on demand:

cp -r product-video-as-code ~/.claude/skills/product-video

No agent at all. The scripts are plain Python calling ffmpeg and Playwright. Nothing here imports a vendor SDK or calls a model API, so you can run the whole pipeline by hand.

Requirements: Python 3.9+, ffmpeg/ffprobe on PATH, Playwright with Chromium (pip install playwright && playwright install chromium), and any text-to-speech provider.

Try it in a minute

No narration, no API keys, no accounts. This renders the bundled starter deck to a real 23s 1080p MP4:

pip install -r requirements.txt && playwright install chromium
cp templates/deck.html .
python3 scripts/render.py            # -> out/silent.mp4

Stills are faster still, if you just want to see the deck:

python3 scripts/render.py --preview 2 8 18

Full pipeline, with narration

cp templates/script.example.json script.json
# edit script.json, then generate audio/vo_01.mp3 ... one clip per scene with the
# text-to-speech provider of your choice
python3 scripts/assemble.py                    # timings.json + out/voice.wav
python3 scripts/render.py                      # out/silent.mp4
python3 scripts/mux.py --final out/final.mp4   # + music if audio/bed.mp3 exists

assemble.py is the only stage that needs audio. Without it, render.py falls back to the durations declared in the deck, so silent videos need no extra work.

Kinds of video

The pipeline is the same; structure, pacing and how much of the frame is real product are what change.

KindLengthShapeFootage
Product explainer1-3 minproblem → turn → how → proof → closea little, as proof
Feature launch30-90swhat changed → why → see it → get itmedium
Demo / walkthrough2-5 minone real task, start to finishdominant
Tutorial3-10 minstep by step, chaptered, room to followdominant
Release notes30-90sone item per beat, denseclips or stills
Onboarding1-3 minthe first-run pathdominant
Title sting / loop5-20sone idea, often silentnone
Social cutunder 60shook first, derived from a longer cutshort

Demos and tutorials are footage-first - the deck is chrome around the product. Explainers and launches are narration-first, with footage as evidence for the claim just made. SKILL.md has the full guidance.

What's here

Path
SKILL.mdthe skill itself - what Claude reads
scripts/assemble.pymeasure narration → scene timings + voice track
scripts/render.pydeterministic, resumable frame renderer
scripts/composite.pyoverlay screen recordings into a measured DOM rect
scripts/mux.pyducked music bed + broadcast-level master
scripts/detect_brand.pyread colours, fonts, icons and logos out of a codebase
scripts/capture/log in by hand, then record the product with a synthetic cursor
templates/deck.htmlstarter deck with the animation engine
references/pipeline, audio, screen capture, and pitfalls

Techniques

Deterministic rendering. The renderer seeks to an explicit t and screenshots. No wall-clock, no requestAnimationFrame - a slow machine produces the same file as a fast one.

Resumable chunks. Frames render in parts; a stall costs one chunk, not the pass.

Beat-matched animation. Elements land on the words that describe them. This is most of the difference between a directed video and a slideshow.

One source, many cuts. A long demo and a social cut share a deck and are selected with ?cut=short, so they cannot drift apart.

Screen recordings that read as real. Playwright captures no cursor, so one is injected. Record at the exact pixel size of the frame it will occupy - scaling a 1920 capture into a smaller frame destroys UI text.

Audio that is actually audible. Normalise the music bed to a loudness target before ducking. A fixed dB attenuation on a quiet generated bed produces a track that is present in the file and inaudible in the room.

Brand detected, not guessed. detect_brand.py reads the palette, fonts, icon library and logos out of the product's own codebase, skips build output, and rejects colours that do not cohere rather than silently producing a white card on a black frame.

Verify, don't assume. Detect blank frames by ink coverage, not variance. Confirm pronunciation by transcribing the generated audio back. Measure levels on the file you are about to ship.

references/PITFALLS.md documents the failures behind each of these, including a keyframe-engine bug that makes elements appear from frame zero, and why a double-escaped apostrophe silently breaks a whole deck.

Composing with other skills

Pairs well with Anthropic's frontend-design for visual direction - the deck is plain HTML/CSS, so design guidance applies directly.

If you want React composition and faster renders, the claude-code-video-toolkit covers Remotion and generative assets. This skill deliberately stays dependency-light: plain HTML means anyone can open the deck and edit copy without a toolchain, which matters for brand work where exact assets and colours are non-negotiable.

The same idea applied to slides: Deckloom builds pitch decks, one-pagers and sales decks from a JSON content file and one HTML design file, rendered to PDF and PPTX.

License

MIT (c) 2026 Kritik Modi - see LICENSE.

Contributors

kritikmodi

11 commits

kritikmodi/product-video-as-code

Build product videos from your IDE instead of a video editor

7

stars

11

commits

Python

primary language

Aug 31, 2026

updated

claude-code
claude-skill
developer-marketing
devrel
ffmpeg
playwright
screen-recording
text-to-speech
video
video-as-code
Browse cluster: Video editing and automation tools

README

Product video as Code

Build product videos from code instead of a video editor: an animated HTML deck, an AI voiceover, real screen recordings, and a mastered audio mix, rendered deterministically to MP4 with ffmpeg.

Product demos, feature launches, explainers, walkthroughs, tutorials, release notes, onboarding, title stings, social cuts - one pipeline, different shapes.

script.json ──► TTS ──► measure ──► timings.json ──► render ──► composite ──► mux ──► MP4

The bundled starter deck, rendered by the pipeline

The clip above is templates/deck.html rendered straight through scripts/render.py with no narration, no API keys and no editing - exactly what a clean clone produces in about a minute. Full quality MP4 (1080p, 30fps).

Why this exists

Video is usually the one asset an AI assistant cannot iterate on. Every revision means reopening an editor and redoing the work by hand - so software videos go stale the moment the product moves.

Treating video as code changes that. The deck is HTML, the timeline is a pure function of t, and the audio is measured rather than guessed. "Reword scene 4, add banks to the segment list, and cut it under a minute" becomes a two-minute change instead of an afternoon. Re-shooting a demo after a UI change is a script run, not a reshoot.

The core idea

Audio first, then timing, then picture.

Generate the narration before deciding how long anything is on screen. Measure each clip, derive scene durations from those measurements, then render. Guessing durations - or writing narration to fit a fixed storyboard - produces visuals that drift out of sync and forces a rebuild every time a line changes.

Install

git clone https://github.com/kritikmodi/product-video-as-code.git

Any agent. AGENTS.md at the repo root is read natively by Codex, Cursor, Copilot, Gemini CLI, Aider, Windsurf, Zed and others, so cloning it into your project is enough.

Claude Code / claude.ai. Install it as a skill so it loads on demand:

cp -r product-video-as-code ~/.claude/skills/product-video

No agent at all. The scripts are plain Python calling ffmpeg and Playwright. Nothing here imports a vendor SDK or calls a model API, so you can run the whole pipeline by hand.

Requirements: Python 3.9+, ffmpeg/ffprobe on PATH, Playwright with Chromium (pip install playwright && playwright install chromium), and any text-to-speech provider.

Try it in a minute

No narration, no API keys, no accounts. This renders the bundled starter deck to a real 23s 1080p MP4:

pip install -r requirements.txt && playwright install chromium
cp templates/deck.html .
python3 scripts/render.py            # -> out/silent.mp4

Stills are faster still, if you just want to see the deck:

python3 scripts/render.py --preview 2 8 18

Full pipeline, with narration

cp templates/script.example.json script.json
# edit script.json, then generate audio/vo_01.mp3 ... one clip per scene with the
# text-to-speech provider of your choice
python3 scripts/assemble.py                    # timings.json + out/voice.wav
python3 scripts/render.py                      # out/silent.mp4
python3 scripts/mux.py --final out/final.mp4   # + music if audio/bed.mp3 exists

assemble.py is the only stage that needs audio. Without it, render.py falls back to the durations declared in the deck, so silent videos need no extra work.

Kinds of video

The pipeline is the same; structure, pacing and how much of the frame is real product are what change.

KindLengthShapeFootage
Product explainer1-3 minproblem → turn → how → proof → closea little, as proof
Feature launch30-90swhat changed → why → see it → get itmedium
Demo / walkthrough2-5 minone real task, start to finishdominant
Tutorial3-10 minstep by step, chaptered, room to followdominant
Release notes30-90sone item per beat, denseclips or stills
Onboarding1-3 minthe first-run pathdominant
Title sting / loop5-20sone idea, often silentnone
Social cutunder 60shook first, derived from a longer cutshort

Demos and tutorials are footage-first - the deck is chrome around the product. Explainers and launches are narration-first, with footage as evidence for the claim just made. SKILL.md has the full guidance.

What's here

Path
SKILL.mdthe skill itself - what Claude reads
scripts/assemble.pymeasure narration → scene timings + voice track
scripts/render.pydeterministic, resumable frame renderer
scripts/composite.pyoverlay screen recordings into a measured DOM rect
scripts/mux.pyducked music bed + broadcast-level master
scripts/detect_brand.pyread colours, fonts, icons and logos out of a codebase
scripts/capture/log in by hand, then record the product with a synthetic cursor
templates/deck.htmlstarter deck with the animation engine
references/pipeline, audio, screen capture, and pitfalls

Techniques

Deterministic rendering. The renderer seeks to an explicit t and screenshots. No wall-clock, no requestAnimationFrame - a slow machine produces the same file as a fast one.

Resumable chunks. Frames render in parts; a stall costs one chunk, not the pass.

Beat-matched animation. Elements land on the words that describe them. This is most of the difference between a directed video and a slideshow.

One source, many cuts. A long demo and a social cut share a deck and are selected with ?cut=short, so they cannot drift apart.

Screen recordings that read as real. Playwright captures no cursor, so one is injected. Record at the exact pixel size of the frame it will occupy - scaling a 1920 capture into a smaller frame destroys UI text.

Audio that is actually audible. Normalise the music bed to a loudness target before ducking. A fixed dB attenuation on a quiet generated bed produces a track that is present in the file and inaudible in the room.

Brand detected, not guessed. detect_brand.py reads the palette, fonts, icon library and logos out of the product's own codebase, skips build output, and rejects colours that do not cohere rather than silently producing a white card on a black frame.

Verify, don't assume. Detect blank frames by ink coverage, not variance. Confirm pronunciation by transcribing the generated audio back. Measure levels on the file you are about to ship.

references/PITFALLS.md documents the failures behind each of these, including a keyframe-engine bug that makes elements appear from frame zero, and why a double-escaped apostrophe silently breaks a whole deck.

Composing with other skills

Pairs well with Anthropic's frontend-design for visual direction - the deck is plain HTML/CSS, so design guidance applies directly.

If you want React composition and faster renders, the claude-code-video-toolkit covers Remotion and generative assets. This skill deliberately stays dependency-light: plain HTML means anyone can open the deck and edit copy without a toolchain, which matters for brand work where exact assets and colours are non-negotiable.

The same idea applied to slides: Deckloom builds pitch decks, one-pagers and sales decks from a JSON content file and one HTML design file, rendered to PDF and PPTX.

License

MIT (c) 2026 Kritik Modi - see LICENSE.

Contributors

kritikmodi

11 commits

Languages

Python

79.7%

HTML

20.3%