{"slug": "html-css-animation-to-video-mp4-the-headless-deterministic-way-incl-claude", "title": "HTML/CSS Animation to Video (MP4): the Headless, Deterministic Way (incl. Claude)", "summary": "A developer has created htmlrec, a CLI tool that renders HTML/CSS animations to MP4 video frame by frame without screen recording. The tool controls the browser clock directly to capture each frame at an exact timestamp, eliminating the lag and non-deterministic results of screen recording. It works with any self-contained HTML/CSS animation, including those generated by AI tools like Claude, and supports custom resolution, duration, frame rate, and transparency.", "body_md": "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.\n\nThe 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.\n\nThere's a better way.\n\nYou can use [htmlrec](https://crates.io/crates/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.\n\nInstall it with:\n\n```\nbrew install dsplce-co/tap/htmlrec ffmpeg\n```\n\nThe 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:\n\n```\nhrec render animation.html -o out.mp4\n```\n\nThis 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.\n\n**1. Get your animation from Claude** *(skip if you already have an HTML animation)*\n\nAsk Claude for whatever you need. Something like:\n\n\"Create an HTML/CSS animation of a logo appearing with a fade and slight upward motion, black background, 3 seconds\"\n\nYou'll get back a self-contained HTML file. Save it — let's call it `animation.html`\n\n.\n\n**2. Render it**\n\n```\nhrec render animation.html -o out.mp4\n```\n\nThat's it. By default you get a 1280×720, 60fps, 5-second MP4.\n\n**3. Adjust if needed**\n\nCustom resolution and duration:\n\n```\nhrec render animation.html -o out.mp4 --width 1920 --height 1080 --duration 3 --fps 60\n```\n\nNeed transparency (for overlaying on other footage)?\n\n```\nhrec render animation.html -o out.webm --transparent\n```\n\nWebM with VP9 preserves the alpha channel. Works with `.mov`\n\n(ProRes 4444) too if you're in a video editing pipeline.\n\nHere's a minimal animation Claude might generate:\n\n```\n<!DOCTYPE html>\n<html>\n<head>\n    <style>\n    body { margin: 0; background: #000; display: grid; place-items: center; height: 100vh; }\n    .logo {\n        font-family: sans-serif;\n        font-size: 64px;\n        color: #fff;\n        opacity: 0;\n        transform: translateY(20px);\n        animation: appear 1s ease forwards;\n    }\n    @keyframes appear {\n        to { opacity: 1; transform: translateY(0); }\n    }\n    </style>\n</head>\n<body>\n    <div class=\"logo\">dsplce</div>\n</body>\n</html>\n```\n\nRender it:\n\n```\nhrec render animation.html -o logo.mp4 --duration 2\n```\n\nClean MP4, no screen recording, no lag, no manual trimming.\n\nThe 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.\n\nIf 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.\n\nSource and docs: [github.com/dsplce-co/htmlrec](https://github.com/dsplce-co/htmlrec)\n\nCSS 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`\n\n, `transition`\n\n, `animation`\n\n), a headless renderer captures it deterministically. Match the duration to your animation and you're done:\n\n```\nhrec render animation.html -o out.mp4 --duration 3\n```\n\nThe default is 60fps, which keeps fast motion smooth; pass `--fps 30`\n\nif 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.\n\n\"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:\n\n```\nhrec render animation.html -o out.mp4\n```\n\nThat 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.\"\n\nShort answer: it depends on how much you're building.\n\nThere'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.\n\nSo 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.\n\nBut 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:\n\nThat's exactly what [htmlrec](https://crates.io/crates/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.\n\n```\nhrec render animation.html -o out.mp4\n```\n\nMP4 is the safest choice for most use cases — universally supported, small file size, plays everywhere. No extra flags needed.\n\n```\nhrec render animation.html -o out.webm\n```\n\nWebM 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).\n\n```\nhrec render animation.html -o out.mov --transparent\n```\n\nMOV with ProRes 4444 is the most reliable format for transparency — virtually every video editor (Premiere, After Effects, Final Cut) handles it without issues.\n\nWebM also supports an alpha channel:\n\n```\nhrec render animation.html -o out.webm --transparent\n```\n\nBut 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.\n\nStill, 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.\n\n**How do I convert an HTML animation to video?**\n\nRender 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`\n\n. The renderer drives the browser clock, so every frame is captured at the exact right moment and the output is frame-perfect.\n\n**How to render CSS animations to MP4?**\n\nExactly the same way as any HTML animation — CSS `@keyframes`\n\nand transitions are captured natively, with nothing extra to configure. Run `hrec render animation.html -o out.mp4`\n\n, adding `--duration`\n\n(or `--fps`\n\n) to match your animation. No screen recording, no manual trimming.\n\n**Is the output deterministic?**\n\nYes. 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.", "url": "https://wpnews.pro/news/html-css-animation-to-video-mp4-the-headless-deterministic-way-incl-claude", "canonical_source": "https://dev.to/dsplce-co/htmlcss-animation-to-video-mp4-the-headless-deterministic-way-incl-claude-4a2", "published_at": "2026-06-12 06:30:03+00:00", "updated_at": "2026-06-12 06:41:53.766259+00:00", "lang": "en", "topics": ["ai-tools"], "entities": ["htmlrec", "Claude", "QuickTime", "OBS", "ffmpeg"], "alternates": {"html": "https://wpnews.pro/news/html-css-animation-to-video-mp4-the-headless-deterministic-way-incl-claude", "markdown": "https://wpnews.pro/news/html-css-animation-to-video-mp4-the-headless-deterministic-way-incl-claude.md", "text": "https://wpnews.pro/news/html-css-animation-to-video-mp4-the-headless-deterministic-way-incl-claude.txt", "jsonld": "https://wpnews.pro/news/html-css-animation-to-video-mp4-the-headless-deterministic-way-incl-claude.jsonld"}}