DEV Community

Cover image for HTML/CSS Animation to Video (MP4): the Headless, Deterministic Way (incl. Claude)
dsplce.co
dsplce.co

Posted on • Originally published at dsplce.co

HTML/CSS Animation to Video (MP4): the Headless, Deterministic Way (incl. Claude)

So you asked Claude to animate something. Maybe a logo, a loading screen, a data viz. It spat out a neat HTML file with CSS keyframes, everything looks crisp in the browser — and now you need it as an MP4.

The obvious approach is screen recording. Open QuickTime or OBS, hit record, play the animation, stop, trim. Works, kind of. Except it's not frame-perfect. If your machine lags for half a second, that lag is baked into the video. The animation runs at whatever speed your CPU felt like that afternoon. Completely non-deterministic. And the moment you tweak something — wrong colour, timing off by 200ms — you're setting the whole thing up again, which is just tiring. Not to mention that every time you hit record you start at a slightly different frame, so swapping the asset in your video editor becomes a pain because nothing lines up the same way twice.

There's a better way.

You can use htmlrec — a CLI tool that renders HTML animations to video frame by frame, without touching your screen. It controls the browser clock directly, so every frame is captured at exactly the right moment regardless of your machine's load. Pixel-perfect, every single time.

Install it with:

brew install dsplce-co/tap/htmlrec ffmpeg
Enter fullscreen mode Exit fullscreen mode

How to convert an HTML animation to video

The reliable way to convert an HTML animation to video is to render it headlessly, frame by frame, instead of screen-recording it. Point a tool at your HTML file, let it drive the browser clock, and capture each frame at an exact timestamp:

hrec render animation.html -o out.mp4
Enter fullscreen mode Exit fullscreen mode

This works for any self-contained HTML/CSS animation — a logo reveal, a loading screen, a chart, or anything an LLM like Claude generated for you. The full step-by-step is below.


The workflow

1. Get your animation from Claude (skip if you already have an HTML animation)

Ask Claude for whatever you need. Something like:

"Create an HTML/CSS animation of a logo appearing with a fade and slight upward motion, black background, 3 seconds"

You'll get back a self-contained HTML file. Save it — let's call it animation.html.

2. Render it

hrec render animation.html -o out.mp4
Enter fullscreen mode Exit fullscreen mode

That's it. By default you get a 1280×720, 60fps, 5-second MP4.

3. Adjust if needed

Custom resolution and duration:

hrec render animation.html -o out.mp4 --width 1920 --height 1080 --duration 3 --fps 60
Enter fullscreen mode Exit fullscreen mode

Need transparency (for overlaying on other footage)?

hrec render animation.html -o out.webm --transparent
Enter fullscreen mode Exit fullscreen mode

WebM with VP9 preserves the alpha channel. Works with .mov (ProRes 4444) too if you're in a video editing pipeline.


Example

Here's a minimal animation Claude might generate:

<!DOCTYPE html>
<html>
<head>
    <style>
    body { margin: 0; background: #000; display: grid; place-items: center; height: 100vh; }
    .logo {
        font-family: sans-serif;
        font-size: 64px;
        color: #fff;
        opacity: 0;
        transform: translateY(20px);
        animation: appear 1s ease forwards;
    }
    @keyframes appear {
        to { opacity: 1; transform: translateY(0); }
    }
    </style>
</head>
<body>
    <div class="logo">dsplce</div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Render it:

hrec render animation.html -o logo.mp4 --duration 2
Enter fullscreen mode Exit fullscreen mode

Clean MP4, no screen recording, no lag, no manual trimming.


The whole point of htmlrec is to remove the friction between "Claude gave me an animation" and "I have a video file I can actually use." One command, done.

If you're generating HTML assets regularly — ad creatives, onboarding animations, motion graphics for social — this becomes part of your pipeline rather than a manual step every time.

Source and docs: github.com/dsplce-co/htmlrec


CSS animation to MP4

CSS keyframe animations render to MP4 exactly like everything else — there's nothing special to configure. As long as the motion is driven by CSS (@keyframes, transition, animation), a headless renderer captures it deterministically. Match the duration to your animation and you're done:

hrec render animation.html -o out.mp4 --duration 3
Enter fullscreen mode Exit fullscreen mode

The default is 60fps, which keeps fast motion smooth; pass --fps 30 if you'd rather a lighter file and your animation doesn't need the extra frames. Either way the frames come from the browser's own clock, so a 3-second animation is exactly 3 seconds of video — no drift, no dropped frames.


HTML to MP4, deterministically

"Deterministic" is the whole point: the same HTML always produces the same video, regardless of what your machine was doing while it rendered. A screen recorder can't promise that — it captures in real time, so any hiccup is baked into the file. A headless renderer steps the page forward one frame at a time and grabs each frame at a precise timestamp, then hands the sequence to FFmpeg:

hrec render animation.html -o out.mp4
Enter fullscreen mode Exit fullscreen mode

That determinism is what makes this practical in a real pipeline. Tweak a colour or a timing value, re-render, and only the parts you changed change — the rest of the frames are identical to last time. Swapping the clip into a video editor lines up perfectly every time because nothing is recorded "live."


Do you need a framework like HyperFrames?

Short answer: it depends on how much you're building.

There's a growing category of open-source tools that turn HTML into video. HeyGen recently open-sourced HyperFrames, a renderer that converts HTML to video and is positioned as "built for agents" — meant to be driven programmatically inside LLM workflows. Under the hood it's the same core idea as the approach here: a headless browser renders the page and FFmpeg encodes the frames, deterministically. It runs locally (Node 22+ and FFmpeg) — there's no hosted service or signup.

So the real question isn't "platform vs. local tool" — both run on your machine. It's scope. HyperFrames is a larger Node framework: it ships adapters for GSAP, Lottie, and Three.js plus a timeline model for composing more complex, programmatic animations. If that's the kind of thing you're building, a framework that size earns its keep.

But for the common case — you already have a self-contained HTML/CSS animation and you just want a clean MP4 — you don't need a framework at all. The job is two well-understood pieces:

  1. Headless Chrome renders the page and steps the animation clock forward frame by frame.
  2. FFmpeg stitches those frames into a video.

That's exactly what htmlrec is: a single-purpose Rust CLI wrapping those two. Point it at an HTML file, get a deterministic MP4 — one command, nothing to compose, frame-perfect.


How to convert a Claude animation to MP4

hrec render animation.html -o out.mp4
Enter fullscreen mode Exit fullscreen mode

MP4 is the safest choice for most use cases — universally supported, small file size, plays everywhere. No extra flags needed.


How to convert a Claude animation to WebM

hrec render animation.html -o out.webm
Enter fullscreen mode Exit fullscreen mode

WebM is a good fit if you're embedding the animation on the web. Smaller than MP4 at comparable quality, and supported natively in Chrome, Firefox, and Edge (Safari's VP9 support is patchier, so test there).


How to convert a Claude animation to transparent video

hrec render animation.html -o out.mov --transparent
Enter fullscreen mode Exit fullscreen mode

MOV with ProRes 4444 is the most reliable format for transparency — virtually every video editor (Premiere, After Effects, Final Cut) handles it without issues.

WebM also supports an alpha channel:

hrec render animation.html -o out.webm --transparent
Enter fullscreen mode Exit fullscreen mode

But in practice, a lot of editing software either doesn't support WebM at all, or silently drops the alpha channel when importing it. If you're taking the file into a video editor, stick with MOV.

Still, if you're embedding the animation directly on a web page rather than taking it into an editor, transparent WebM is a strong option — Chrome and Firefox handle it natively and the file size is a fraction of MOV. Safari's support for alpha-channel WebM is unreliable, though, so don't count on it there.


FAQ

How do I convert an HTML animation to video?

Render it headlessly, frame by frame, instead of screen-recording it. Save the animation as a self-contained HTML file and run hrec render animation.html -o out.mp4. The renderer drives the browser clock, so every frame is captured at the exact right moment and the output is frame-perfect.

How to render CSS animations to MP4?

Exactly the same way as any HTML animation — CSS @keyframes and transitions are captured natively, with nothing extra to configure. Run hrec render animation.html -o out.mp4, adding --duration (or --fps) to match your animation. No screen recording, no manual trimming.

Is the output deterministic?

Yes. Because frames are captured by controlling the browser clock rather than recording in real time, the same HTML always produces the same video regardless of CPU load. Re-render after a tweak and only the parts you changed will change.

Top comments (0)