Opus55Vid

HTML to video

HTML to video: four honest ways to get an MP4.

By Opus55Vid · Updated · 9 min read

Short answer

HTML to video means rendering a web animation into an MP4 file, and the reliable way is to capture it frame by frame instead of recording the screen. A screen recording is the fastest start; headless Chrome plus FFmpeg, Remotion (React) or HyperFrames (HTML) give frame-exact output.

HTML to video: the four routes at a glance

HTML to video is the job of turning an animation that runs in a browser into an MP4 that plays anywhere, and there are four practical routes: record the screen, capture frames from a headless browser and join them with FFmpeg, write the animation as a Remotion React component, or use a framework built around HTML timelines such as HyperFrames.

They differ on one question: does the video clock follow the real clock, or does your code decide what every frame looks like? Real-time routes are quick but can stutter or drift. Frame-by-frame routes need setup but produce the same frames every run. If you searched for html to mp4 or how to convert an HTML animation to video, that single distinction decides which section below you need.

  • Screen recording: no setup, real-time capture, quality depends on the machine.
  • Headless Chrome + FFmpeg: any HTML page, but you write the capture script and handle timing yourself.
  • Remotion: frame-exact, but you write React, not arbitrary HTML.
  • HyperFrames: frame-exact, starts from HTML, needs Node.js and FFmpeg.

A fifth option is not a converter at all: asking an AI model to write the animation in a video-ready format. That is covered near the end, along with where Opus55Vid fits and what it does not do.

Route 1: screen-record the browser

Screen recording works when you need an MP4 of an HTML animation today and exact frames do not matter: play the page full screen and record it with your operating system recorder or OBS. It converts an HTML5 animation to MP4 with zero code.

Browser automation tools can do the same without a human. Playwright records video from a browser context, and its documentation says the video size defaults to the viewport scaled down to fit 800x800 unless you set a size. Puppeteer documents a screen recorder (page.screencast()) that requires FFmpeg on your machine and writes WebM, VP9 at 30 FPS by default, and its docs point to a newer Page.record(). Either way you get a real-time recording, and you usually convert the WebM to MP4 afterwards.

The catch

The recorder samples whatever the browser managed to paint. If the machine is busy, frames are dropped or timing stretches, and the animation start is whenever you pressed record. Expect to trim the start and end, and expect slightly different results each run. For a one-off clip that is fine. For a video you will re-export or ship to customers, it is the weakest route.

Route 2: headless Chrome frame capture plus FFmpeg for HTML to MP4

Headless frame capture is the general-purpose answer for converting HTML to MP4: open the page in a headless browser, step it to frame N, save a screenshot, repeat for every frame, then let FFmpeg join the images into a video at your chosen frame rate.

Both Puppeteer and Playwright can screenshot a page. Puppeteer's page.screenshot() accepts a path, a type of png, jpeg or webp, and omitBackground for transparent captures. At 30 fps, a 10-second animation is 300 screenshots named in a numbered pattern. FFmpeg reads that pattern with its image2 demuxer; the documented form is the one below, where -framerate sets the input frame rate (the default is 25).

# numbered PNG frames -> video (adapted from the FFmpeg image2 docs)
ffmpeg -framerate 30 -i 'frame-%04d.png' out.mp4

The catch

The command is easy; the capture script is the work. You must freeze the page between screenshots, otherwise the animation keeps running while the screenshot is taken. You also own fonts loading, video and audio elements, resolution, and encoder settings. This route gives you the most control and the most to maintain. The next section explains the timing problem in detail, because it is where most DIY attempts go wrong.

Why a CSS animation to video capture drifts, and what render frame N means

A CSS animation drifts when captured because it is driven by the browser clock, not by your capture loop, so each screenshot lands at a slightly different moment in the animation. Deterministic rendering fixes this by making time a variable you set: for each output frame you tell the page exactly which moment it is, then capture.

Rendering "frame N" means the page shows what it would show at time N divided by fps, and nothing else. Frame 45 at 30 fps is the state at 1.5 seconds, every run, on every machine. In the browser you can approach this with the Web Animations API: document.getAnimations() returns the page's CSS Animations, CSS Transitions and Web Animations, and each returned Animation object can be paused and have its currentTime set.

// Sketch: freeze every CSS/Web animation at a chosen time (ms), then capture
function seek(ms) {
  document.getAnimations().forEach((a) => {
    a.pause();
    a.currentTime = ms;
  });
}
seek(1500); // the state at 1.5 s

This covers CSS animations and Web Animations. It does not control a setTimeout loop, a requestAnimationFrame game loop or a video element, which need their own seek logic. That gap is the reason frameworks exist: they define a timeline that every animation is required to follow.

Route 3: Remotion renders React, not arbitrary HTML

Remotion is a framework for making videos with React, so it is not a way to convert an existing HTML file; it is a way to write a video as components that are rendered frame by frame. Its docs describe it as providing a frame number and a canvas so you can "render anything you want using React".

You read the current frame with useCurrentFrame() and derive everything from it. A video has a width, a height, a durationInFrames and an fps, defined on a composition. Rendering is one CLI call, and H.264 is the default codec:

npx remotion render <entry-point> <composition-id> <output-location>

The catch

Your CSS animations will not carry over cleanly. Remotion's docs warn about flickering when animations are not driven by useCurrentFrame(), with CSS transitions named as an example, so you rewrite motion in terms of the frame number. If your source is a finished HTML animation, expect a port. If you are starting fresh, or letting an AI model write the code, Remotion is a solid target. We cover that workflow in the Remotion AI guide and the Remotion with Claude Code tutorial.

Route 4: HyperFrames, HTML in and MP4 out

HyperFrames is an open-source framework from HeyGen that turns HTML, CSS, media and seekable animations into MP4, which makes it the closest match to what people mean by HTML to video. Its README describes the tagline "Write HTML. Render video. Built for agents." and the code is Apache 2.0 licensed at github.com/heygen-com/hyperframes, with a site at hyperframes.heygen.com.

The documented flow is three commands: npx hyperframes init my-video scaffolds a project, npx hyperframes preview opens a live-reload browser preview, and npx hyperframes render encodes the MP4. Under the hood, the README says the renderer seeks each frame in headless Chrome and encodes with FFmpeg, so it is the deterministic version of Route 2 packaged as a tool. It requires Node.js 22 or newer and FFmpeg.

The catch

Animations must be seekable, meaning they follow the framework timeline, which the README lists as GSAP, CSS, Lottie, Three.js and similar. A page that runs on its own timers still needs adapting. Compositions also carry HyperFrames-specific timing attributes, so an arbitrary HTML file is a starting point, not a drop-in input. We have not benchmarked it, so we make no claims about speed or output quality compared with the other routes.

Let AI write the animation, and where Opus55Vid fits

An AI model can write the animation code for you, which removes the hardest part of every route above: authoring the motion. Both Remotion and HyperFrames present themselves as workable with AI coding agents, because their output is plain code that a model can generate and you can edit.

Opus55Vid takes that idea to its simplest form. You describe a video in one sentence, Claude Opus 5.5 writes Remotion code for it, and we render an MP4 with sound effects timed to the animation, no background music, with nothing to install. See Opus 5.5 video for how that works and Remotion AI for the developer route to the same result.

To be plain about the limit: Opus55Vid does not convert an existing HTML file or CSS animation to video. If you already have that file, use Route 2, Route 3 or Route 4. If you have an idea and no animation yet, describing it is faster than building a capture pipeline. Opus55Vid is independent and not affiliated with Anthropic or Remotion.

Quick chooser: if you have X, use Y

The right HTML to video route depends on what you already have, and this list maps each situation to one answer.

  • A finished HTML animation and you need a clip once: screen-record it (Route 1).
  • A finished HTML page you must export repeatedly or at fixed quality: headless Chrome plus FFmpeg with seeking (Route 2), or port it to HyperFrames (Route 4).
  • A CSS or HTML5 animation made with GSAP, Lottie or Three.js: check HyperFrames first (Route 4), since those are listed as seekable.
  • A React codebase, or you want an AI agent to write the video code: Remotion (Route 3).
  • No animation yet and no wish to set up Node.js: describe it in one sentence with Opus55Vid.
  • Anything with sound that must stay in sync: avoid real-time recording, and choose a route that renders frame by frame.

For output settings, pick the frame rate and resolution your destination expects, and keep it constant from capture to encode. See the FAQ below for the usual defaults.

Questions, answered

How do I convert an HTML animation to MP4?

Capture it frame by frame and encode the frames with FFmpeg, or use a framework that does this for you. Headless Chrome with FFmpeg, Remotion and HyperFrames all work this way. Screen recording is the quick alternative when exact frames are not required.

Can I record a web page as a video?

Yes. Use your operating system screen recorder or OBS, or automate it: Playwright can record video from a browser context, and Puppeteer documents a screen recorder that needs FFmpeg. These record in real time, so quality depends on your machine.

Can CSS animations be exported to video?

Yes, but they must be captured at controlled times, not in real time. document.getAnimations() lets a script pause CSS animations and set their time before each screenshot. Frameworks such as HyperFrames handle this for seekable animations.

Is Remotion HTML to video?

Not exactly. Remotion renders React components frame by frame into video, so you write React rather than hand it an HTML file. Motion should be driven by the frame number; its docs warn that CSS transitions can flicker.

What resolution and frame rate should I use for an HTML animation video?

Use 1080p at 30 fps as a common default, and keep the same frame rate for capture and encoding. Match the aspect ratio to the destination: 16:9 for landscape, 9:16 for vertical, 1:1 for square.

Can AI write the HTML animation for me?

Yes. An AI model can write animation code in HTML or React that you then render to MP4. Opus55Vid does this from one sentence using Claude Opus 5.5 and Remotion, but it does not convert an HTML file you already have. Independent; not affiliated with Anthropic or Remotion.

No HTML animation yet? Describe it in one sentence.

Opus55Vid has Claude Opus 5.5 write the animation and renders the MP4 for you. Your first 15-second video is on us. Independent service, not affiliated with Anthropic or Remotion.

Opus55Vid is an independent product and is not affiliated with, sponsored or endorsed by Anthropic.