agentleFS
jblxojblxo/programmatic-video-skill/skills/programmatic-video/SKILL.md

programmatic-video

Skill0 starsChanged 20 days agoMITView on GitHub

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".

2 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions2 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 2

    1. badgids/Story-Film-Skills★ 4same name
    2. AlleninTaipei/my-codex-skills★ 0same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repositoryOne other file it gives its agents.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 2 are distinctive, and 8 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 8

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Never use real-time browser screen recording (MediaRecorder, requestAnimationFrame wall-clock capture, or CSS transitions running in real …

    line 34
  2. Distinctive:

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

    line 39
  3. Very specific:

    Rule 2 — Multimodal Contact-Sheet QA Before Full Render: Before encoding the full 60fps MP4, capture 8–12 key timestamps (render.mjs …

    line 41
  4. Very specific:

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

    line 61
  5. Very specific:

    Always include a seeded PRNG (mulberry32(seed)) for stars, particles, confetti, or noise so frame f is bit-identical across runs.

    line 74
  6. Very specific:

    Wait for document.fonts.ready (handled automatically by render.mjs).

    line 75
  7. Distinctive:

    Never run a full 60fps render first.

    line 80
  8. Very specific:

    Call your image Read / View tool on ./contact-sheet.png (and any individual ./qa-frames/t-*.png that looks dense).

    line 100
  9. Very specific:

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

    line 105
  10. Very specific:

    Verify the output container with ffprobe:

    line 137

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.