Communitygithub.com

jblxo/programmatic-video-skill

>- Build and render deterministic 60fps 1080p MP4 animated videos, motion graphics, release recaps, product demos, and data-driven "Wrapped" videos using HTML5 Canvas, SVG, Playwright frame-stepping (window.__setFrame), multimodal contact-sheet visual self-review, procedural Python/NumPy audio synthesis, WAV SFX cue mixing, and FFmpeg. Use whenever the user asks to "make an animated video", "generate an MP4 video from code", "build a release recap / Wrapped video", "render HTML/Canvas/SVG to MP4", "create a programmatic video without Remotion boilerplate", "make a demo or farewell video with sound effects", or "animate metrics/charts into a 60fps video".

What is programmatic-video-skill?

programmatic-video-skill is a Claude Code agent skill that >- Build and render deterministic 60fps 1080p MP4 animated videos, motion graphics, release recaps, product demos, and data-driven "Wrapped" videos using HTML5 Canvas, SVG, Playwright frame-stepping (window.__setFrame), multimodal contact-sheet visual self-review, procedural Python/NumPy audio synthesis, WAV SFX cue mixing, and FFmpeg. Use whenever the user asks to "make an animated video", "generate an MP4 video from code", "build a release recap / Wrapped video", "render HTML/Canvas/SVG to MP4", "create a programmatic video without Remotion boilerplate", "make a demo or farewell video with sound effects", or "animate metrics/charts into a 60fps video".

Works with✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI✓OpenCode
npx skills add https://github.com/jblxo/programmatic-video-skill/tree/HEAD/skills/programmatic-video

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Programmatic Video Generation Skill

A deterministic, zero-boilerplate workflow for AI coding agents to design, visually QA, score, and render 60fps 1080p MP4 animated videos directly from a single HTML5 Canvas/SVG file, a Python procedural audio script, and a headless Playwright → FFmpeg pipe.

Paths. ${CLAUDE_SKILL_DIR} is the directory containing this SKILL.md. In Claude Code it expands automatically; in Cursor, Codex, OpenCode, or other agents, replace ${CLAUDE_SKILL_DIR} with the resolved path to skills/programmatic-video/.


Why Deterministic Frame-Stepping?

Never use real-time browser screen recording (MediaRecorder, requestAnimationFrame wall-clock capture, or CSS transitions running in real time) to produce videos with an AI agent:

  1. Wall-clock capture drops frames whenever CPU load spikes, causing audio/video drift and stutter.
  2. CSS animations run on wall-clock time, making it impossible to seek to t = 14.20s for instant visual QA.
  3. Blind rendering wastes minutes: rendering 5,000 frames before checking if a title overflows its card guarantees wasted work.

Instead, every video built with this skill obeys three rules:

  • Rule 1 — Pure Function of Frame Index: The entire scene is driven by window.__setFrame(frameIndex, timeSeconds, fps) where t = frameIndex / fps. Every position, opacity, counter, and particle is a deterministic math function of t (using a seeded PRNG like mulberry32, never Math.random()).
  • Rule 2 — Multimodal Contact-Sheet QA Before Full Render: Before encoding the full 60fps MP4, capture 8–12 key timestamps (render.mjs --timestamps ...), stitch them into a single contact-sheet.png (contact-sheet.py), and inspect that image using your multimodal Read/View tool to fix text clipping, overlap, or low contrast.
  • Rule 3 — Sample-Accurate Audio + Zero-Disk-Bloat FFmpeg Pipe: Generate a multi-segment stereo WAV soundtrack + timestamped SFX cues (synth-audio.py), then stream PNG buffers from Playwright directly into ffmpeg -f image2pipe (render.mjs).

End-to-End Agent Workflow (6 Steps)

Step 1: Storyboard & Scene Budget

Design a concrete timeline table before writing code. Group the video into 4–8 second scenes with explicit transition timestamps (T_cut) that both scene.html and synth-audio.py share:

SceneTime (t)Frames (60fps)Visual FocusAudio / SFX Cue
01 — Hook / Alert0.0s – 7.0s0 – 420CRT terminal boot, typewriter logs, CTA button click at 2.7sSub pulse + UI click/unlock cue at 2.7s, riser into 3.4s
02 — Hero Metrics7.0s – 15.0s420 – 9003D perspective synthwave grid + 3 spring-physics counter cardsFull 124 BPM synthwave bass + stereo arpeggiator drop at 7.0s
03 — Deep Telemetry15.0s – 23.0s900 – 1380Split-screen progress bars + animated semi-circular gaugeFilter sweep + high-hat drive, sub impact at 15.0s
04 — Roll Call & Finale23.0s – 30.0s1380 – 1800Bento grid of contributor cards + "JOB'S DONE!" banner & confettiFinale chord + voice/SFX cue at 25.2s, master fade-out 28.5–30.0s

Step 2: Author scene.html with window.__setFrame(f, t, fps)

Write a self-contained 1920x1080 HTML file using HTML5 <canvas> (and/or inline <svg> + DOM overlays) that exposes:

window.__setFrame = function(frameIndex, timeSeconds, fps = 60) {
  if (window.__rafId) {
    cancelAnimationFrame(window.__rafId);
    window.__rafId = null;
  }
  const t = typeof timeSeconds === 'number' ? timeSeconds : frameIndex / fps;
  renderSceneAtTime(frameIndex, t);
};
  • Always include a seeded PRNG (mulberry32(seed)) for stars, particles, confetti, or noise so frame f is bit-identical across runs.
  • Wait for document.fonts.ready (handled automatically by render.mjs).
  • See references/visual-patterns.md for copy-pasteable recipes (3D perspective grid, spring counters, CRT terminal, gauges, bento cards, confetti physics).

Step 3: Run Fast Timestamp Snapshots & Build contact-sheet.png

Never run a full 60fps render first. Sample 1–2 timestamps per scene (plus transition midpoints) and build a single contact sheet:

# 1. Capture 9 keyframe PNGs in ~3 seconds
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --timestamps 1.8,3.0,5.2,8.5,12.5,16.5,20.5,24.5,28.0 \
  --out-dir ./qa-frames

# 2. Stitch them into a labeled grid image
python3 "${CLAUDE_SKILL_DIR}/scripts/contact-sheet.py" \
  --dir ./qa-frames \
  --cols 3 \
  --thumb-width 560 \
  --title "VISUAL QA CONTACT SHEET" \
  --out ./contact-sheet.png

Step 4: Multimodal Self-Review Loop (Mandatory!)

Call your image Read / View tool on ./contact-sheet.png (and any individual ./qa-frames/t-*.png that looks dense). Check every tile against the checklist in references/visual-qa-loop.md:

  • Does any text overflow or collide with card borders, badges, or progress bars?
  • Are all numbers, labels, and HUD headers high-contrast and legible at 1080p?
  • Did every scene transition land cleanly without an unintended empty/black frame?

If you spot any issue in contact-sheet.png, fix scene.html and re-run Step 3 before moving on.

Step 5: Synthesize Procedural Soundtrack & Mix WAV SFX Cues

Generate a stereo 44.1 kHz WAV soundtrack whose transition risers and SFX cues match the exact timestamps in scene.html:

python3 "${CLAUDE_SKILL_DIR}/scripts/synth-audio.py" \
  --duration 30.0 \
  --bpm 124 \
  --style synthwave \
  --transitions 3.4,7.0,15.0,23.0,25.2 \
  --cue "25.2:./sfx/jobs-done.wav:+1.5" \
  --out ./soundtrack.wav

For custom multi-segment compositions or integrating themed sound packs (such as jblxo/claude-code-sound-packs), read references/audio-synthesis.md.

Step 6: Render Final 60fps H.264 MP4 via FFmpeg Pipe

Once visual QA and audio synthesis pass, run render.mjs in full pipe mode:

node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --duration 30 \
  --fps 60 \
  --audio ./soundtrack.wav \
  --crf 18 \
  --out ./final-video.mp4

Verify the output container with ffprobe:

ffprobe -v error -show_entries format=duration,size:stream=codec_name,width,height,r_frame_rate -of default=noprint_wrappers=1 ./final-video.mp4

Reference Playbooks (Loaded on Demand)

TopicReference File
Canvas/SVG visual primitives, easing functions, seeded PRNG, 3D synthwave grid, gauges, bento cardsreferences/visual-patterns.md
Multimodal contact-sheet QA loop, common layout defects, timestamp selection strategyreferences/visual-qa-loop.md
Procedural Python/NumPy audio synthesis, chord progressions, risers, ducking, WAV SFX cue mixingreferences/audio-synthesis.md

Related Skills