Skip to main content

Make videos with Claude

Code-rendered video Opus 5.5

Claude has no video model. It writes code that draws every frame, and that turns out to be a very good way to make motion graphics, explainers and launch videos. Here is the whole workflow, with a render script you can run today.

Updated •703 creator prompts studied•Free MP4 render script

How Claude makes a video

Claude Opus 5.5 reads text and images and writes text. So when people post "videos made with Opus 5.5", what Claude actually wrote is code: a web page that can draw any moment of the animation on request.

A browser then steps through time one frame at a time and saves each picture. ffmpeg stitches the pictures into an MP4. The animation on the right works exactly this way. Drag the slider: every frame comes from one function of t.

Pick your path
Live code, not a video file
frame 000/360 · t=0.00s
The whole "video": one function of time
// drawFrame(ctx, t): same t in, same pixels out.
// A recorder steps t by 1/60 and saves each frame.
const ease = (x) => 1 - Math.pow(1 - Math.min(Math.max(x, 0), 1), 3)
const span = (t, a, b) => ease((t - a) / (b - a))

function drawFrame(ctx, t) {
  const W = 1280, H = 720
  ctx.fillStyle = '#fff7ed'
  ctx.fillRect(0, 0, W, H)

  const out = span(t, 5.2, 5.9)
  ctx.save()
  ctx.translate(0, -out * H)

  const r = span(t, 0, 0.8) * 230
  ctx.fillStyle = '#f97316'
  ctx.beginPath()
  ctx.arc(W - 250, H / 2, r, 0, Math.PI * 2)
  ctx.fill()

  const words = ['CODE', 'IS THE', 'CAMERA']
  ctx.font = '900 104px Inter, sans-serif'
  words.forEach((word, i) => {
    const k = span(t, 0.6 + i * 0.45, 1.1 + i * 0.45)
    ctx.globalAlpha = k
    ctx.fillStyle = i === 2 ? '#f97316' : '#000'
    ctx.fillText(word, 90 - (1 - k) * 120, 230 + i * 120)
  })
  ctx.globalAlpha = 1

  const bars = [0.35, 0.6, 0.45, 0.85, 0.7, 1]
  bars.forEach((v, i) => {
    const h = v * 300 * span(t, 1.9 + i * 0.12, 2.7 + i * 0.12)
    if (h < 1) return
    ctx.fillStyle = i === bars.length - 1 ? '#000' : '#fff'
    ctx.fillRect(W - 420 + i * 55, H / 2 + 150 - h, 40, h)
    ctx.strokeStyle = '#000'
    ctx.lineWidth = 4
    ctx.strokeRect(W - 420 + i * 55, H / 2 + 150 - h, 40, h)
  })

  const line = span(t, 3.1, 4.1)
  ctx.fillStyle = '#000'
  ctx.fillRect(90, 600, 560 * line, 10)
  ctx.font = '700 30px Inter, sans-serif'
  ctx.globalAlpha = span(t, 3.6, 4.2)
  ctx.fillText('360 frames. 0 video models.', 90, 660)
  ctx.restore()
}

The workflow in five steps

  1. 1

    Write the brief

    Say what the viewer should understand, how long it runs, and where it will play. Duration is the one spec nearly everyone gives. Aspect ratio is the one most people forget, and it decides the whole layout.

  2. 2

    Get a storyboard first

    Ask for a shot list with timestamps before any code. Fixing a line in a storyboard costs one message. Fixing a finished scene costs a rewrite.

  3. 3

    Claude writes the scene as code

    Usually one HTML file with Canvas, SVG, Three.js or shaders. The rule that makes export work: every frame is a pure function of time, so render(t) always draws the same picture for the same t.

  4. 4

    Review stills, not the live preview

    Have Claude render a contact sheet, one frame per beat or per second, and look at it. In Claude Code it can read the PNGs itself and fix what it sees before you spend minutes on a full render.

  5. 5

    Render frame by frame to MP4

    A headless browser steps time one frame at a time, screenshots each frame and pipes it to ffmpeg. No dropped frames, any resolution, and the audio track is muxed in at the end instead of recorded.

Step 1 is where most videos are won or lost. The prompt builder walks you through it.

Where to make it: chat, Claude Code, or a skill

claude.ai chat

Fastest way to see something move
  1. 1.Paste a prompt and ask for a single HTML file
  2. 2.It plays in the chat as an artifact
  3. 3.Screen-record it, or download the HTML and render it with the script below

Screen recording drops frames and caps you at your screen resolution. No audio muxing, no self-review.

Claude Code

Real MP4s, audio, multi-scene projects
  1. 1.Empty folder, Opus 5.5, effort high or xhigh
  2. 2.Claude writes the scene, the render script and runs both
  3. 3.It reads its own contact sheets and fixes problems before the final render

Needs Node.js, Chrome and ffmpeg on your machine. Long films can take a big share of a weekly allowance.

A style skill

Same look every time, less prompting
  1. 1.Drop a SKILL.md with your style rules into .claude/skills/
  2. 2.Say "make a 15s launch video in the swiss grid style"
  3. 3.Claude loads the style, asks for missing facts, then builds

Only as good as the rules in it. Start from ours on the motion graphics page.

topFDEjobs
Forward Deployed Engineer roles

Building with Claude? Get paid for it.

Forward Deployed Engineers ship AI agents inside real customer systems. Open roles at Anthropic, OpenAI, Cognizant and more.

Up to $325k Anthropic, OpenAI, more Updated daily
Browse FDE jobs
Browse FDE jobs on topFDEjobs

Which code stack fits which video

You rarely need to choose. In the creator prompts we studied, only 38% named a library, and Claude picked a sensible one for the rest. Name one when you want a specific look. Share = how often each stack appeared in the 703 published results.

StackShareBest forRender note
Canvas 2D
38%
Motion graphics, kinetic type, particles, charts, explainersThe default Claude reaches for. Easy to make deterministic because you redraw the whole frame from t.
SVG + GSAP
26%
Logo reveals, UI animation, line drawing, icon systemsGSAP timelines can be seeked: build the timeline paused and call timeline.seek(t) per frame.
Three.js / WebGL
19%
3D worlds, product turntables, flythroughs, gamesNeeds a GPU-backed headless browser for speed. Read pixels back after each render, not from a realtime loop.
GLSL shaders
13%
Abstract loops, backgrounds, fluid and light effectsAlready a function of a time uniform. Pass t in and it exports cleanly.
p5.js + p5.brush-Hand-painted cartoons, watercolour, storybook shortsSlow without a GPU (seconds per frame). Plain p5 shapes look like 2000s Flash; paint everything with brushes.
Remotion / HyperFrames-Long promos, multi-scene films, React teamsFrameworks that already give you frame-based time and a renderer. Worth it past about a minute of video.

Render to MP4, frame by frame

Screen recording drops frames and is stuck at your screen size. This script loads the animation in headless Chrome and swaps the clock out, so time moves exactly one frame at a time and the rest of the code doesn't notice. It works for requestAnimationFrame loops, GSAP and CSS animations without changing them.

Six rules that make it work

  • Read time, never count frames
    Position = f(t). A variable that increments every frame breaks the moment frames render out of order or in parallel.
  • Seed every random number
    Math.random() gives different noise on every render. Use a hash of the index or a seeded generator so frame 212 is always frame 212.
  • No physics that integrates step by step
    Simulations that add velocity each tick drift. Precompute them once, or use closed-form motion.
  • Wait for fonts before frame 0
    await document.fonts.ready, or the first frames render in a fallback font.
  • Let ffmpeg add the audio
    Never record sound from the browser. Mux the original track into the MP4 at the end, so sync is exact.
  • Tag colour as BT.709
    Untagged HD video gets decoded with the wrong matrix on some players, shifting colours. Add the bt709 filter shown below.
claude-video-render.mjs
// Render any HTML animation to MP4, frame by frame, with a virtual clock.
// npm i playwright-core  (uses your installed Chrome; needs ffmpeg on PATH)
// node claude-video-render.mjs scene.html out.mp4 [seconds=6] [fps=60] [width=1920] [height=1080]
import { chromium } from 'playwright-core'
import { spawn } from 'node:child_process'
import { pathToFileURL } from 'node:url'
import { resolve } from 'node:path'

const [input, output = 'out.mp4', seconds = '6', fps = '60', width = '1920', height = '1080'] = process.argv.slice(2)
const frameCount = Math.round(Number(seconds) * Number(fps))
const frameMs = 1000 / Number(fps)

const virtualClock = () => {
  let now = 0
  let queue = []
  const startDate = Date.now()
  performance.now = () => now
  Date.now = () => startDate + now
  window.requestAnimationFrame = (cb) => queue.push(cb)
  window.cancelAnimationFrame = () => {}
  window.__advance = (ms) => {
    now += ms
    const callbacks = queue
    queue = []
    callbacks.forEach((cb) => cb(now))
    document.getAnimations().forEach((a) => { a.pause(); a.currentTime = now })
  }
}

const browser = await chromium.launch({ channel: 'chrome' })
const page = await browser.newPage({ viewport: { width: Number(width), height: Number(height) } })
await page.addInitScript(virtualClock)
const url = input.startsWith('http') ? input : pathToFileURL(resolve(input)).href
await page.goto(url, { waitUntil: 'networkidle' })
await page.evaluate(() => document.fonts.ready)

const ffmpeg = spawn('ffmpeg', ['-y', '-f', 'image2pipe', '-framerate', fps, '-i', '-',
  '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-crf', '18', '-movflags', '+faststart', output], { stdio: ['pipe', 'inherit', 'inherit'] })

for (let i = 0; i < frameCount; i++) {
  await page.evaluate((ms) => window.__advance(ms), i === 0 ? 0 : frameMs)
  ffmpeg.stdin.write(await page.screenshot({ type: 'png' }))
  if (i % Number(fps) === 0) console.log(`frame ${i}/${frameCount}`)
}
ffmpeg.stdin.end()
await new Promise((done) => ffmpeg.on('close', done))
await browser.close()
console.log(`wrote ${output}`)

Tested on Linux with Chrome and ffmpeg 7: a 2 second, 30fps clip renders in about 6 seconds, and frame 45 lands on exactly t = 1.500.

ffmpeg one-liners you will need next

What the best Claude videos have in common

We read 496 full prompts from 616 creators, plus the source code and production notes of the most-starred Opus 5.5 video projects. These patterns kept coming up.

01

Short prompts work

Almost half of the 496 full prompts we analysed are under 200 characters. Claude picks the stack itself: only 38% name a library.

02

Ask for a storyboard before code

The best-produced pieces all start with a shot list on a beat grid. Edit single shots after, one change per message.

03

Count the reads, not the seconds

Claude knows what happens because it wrote the code. The viewer does not. List each thing the viewer must understand and give each one its own time slot.

04

Ban the template look

Particle bursts, lens flares, neon glow, RGB split and bouncy easing are what make AI motion look like AI motion. Name them as off-limits.

05

Let it watch its own work

Only 7% of prompts ask Claude to check frames, but nearly every high-end result did. Contact sheets catch overlapping text and dead time.

06

Bring the music and the facts

Generated music gets the most complaints. Supply a licensed track and its BPM. For explainers, check every number yourself.

07

Effort level shows on screen

Creators report that higher reasoning effort makes scenes more detailed and more extravagant. Use high or xhigh for a final piece.

08

Budget for rounds

A "one-shot" result usually took two or more rounds. Plan for a draft at half resolution, notes, then the final render.

How long it takes and what it costs

Numbers creators reported publicly. They are single data points, not benchmarks, but they show the range: a short clip is cheap, a polished music video is not.

VideoTimeCost
15s launch spot from a one-line prompt~1 min~$2 API
Promo built with Remotion~10 minnot stated
5 min explainer with TTS and subtitles26 min"very low tokens"
3 min history film, ~7,400 lines~1 h7% of a weekly quota
Hand-painted music video, 156s, two generationsnot stated10% of a Max 5x week
Lyric music video at xhigh effort45 min first cut~$200 API
Full song as 4K60 three.js MV, render only~57 min on an M5 Prolocal
Ready to make one?

Frequently asked questions

Can Claude generate video?

Not directly. Claude Opus 5.5 takes text and images in and writes text out, so it has no video model. What it does very well is write code that draws every frame (Canvas, SVG, Three.js, shaders). A headless browser renders that code frame by frame and ffmpeg turns the frames into an MP4.

How do I export an MP4 from a Claude animation?

Two ways. Quick: play the HTML in a browser and screen-record it. Proper: render it frame by frame. Our free script on this page loads the HTML in headless Chrome, replaces the clock so time advances exactly 1/60 s per frame, screenshots every frame and pipes them into ffmpeg. You need Node.js, Chrome and ffmpeg.

Do I need Claude Code, or does claude.ai work?

claude.ai works for previews: ask for a single HTML file and it plays in the chat. Claude Code is better for finished videos because it can run the renderer, add audio, read its own contact sheets and fix what it sees.

Is making videos with Opus 5.5 free?

The rendering is free and runs on your machine. The model time is not. Creators report anything from about $2 of API usage for a 15 second clip to around $200 for a full music video, or 5 to 10% of a weekly Pro or Max allowance.

What kind of video is Claude good at?

Motion graphics, product launch spots, explainers, kinetic typography, data stories, logo reveals, hand-drawn style cartoons, 3D scenes and game-like pieces. It is weak at photoreal footage of people and places. Creators who need that combine it with a video model.

Which aspect ratio and frame rate should I ask for?

Match the platform: 1920x1080 for YouTube and landing pages, 1080x1920 for Reels, Shorts and TikTok, 1080x1080 or 1080x1350 for feeds. 60fps for motion graphics and UI, 24fps for a hand-drawn or filmic look. Only 8% of creator prompts state the aspect ratio, which is why so many clips end up letterboxed.

Can Claude add music and voiceover?

Yes, through code. It can synthesize music with Web Audio or Python, and call a TTS service for narration. In practice a licensed track you choose sounds better. Give Claude its BPM so cuts land on the beat, and let ffmpeg mux it in.

Should I use Opus or Sonnet for video?

Opus 5.5 for the final piece. Single creator tests found Sonnet close on charts, cards and simple 3D at roughly a quarter to half the cost, and weaker on hand-drawn and ink styles. A common pattern is Opus for the storyboard and review, cheaper models for individual scenes.

Why does my exported video flicker or jump?

The animation keeps state between frames: a counter, Math.random(), CSS transitions, or physics that steps forward each tick. When frames render out of order or in parallel that state is wrong. Make every frame a pure function of time and seed all randomness.

How long does it take?

A 15 second motion graphic can be a single prompt and a few minutes. A polished one minute piece is usually several rounds over an hour or two. Rendering 4K60 of a full song took one creator about an hour on a fast laptop.

Written by Awesome Claude from public creator prompts and the source of open video projects, including pdoom-video, ClaudeAnimationBase and lemo-opuscar. Last updated 2026-10-21.
WebMCP Developers