HTML to video: 5 ways to turn HTML into an MP4
Turn HTML into an MP4: render it frame by frame in headless Chrome with FFmpeg, use HyperFrames or Remotion, record the screen, or record a canvas.
- For
- Developers who need an MP4 from a web page or animation
- Written for
- Claude CodeCodexCursorGitHub CopilotGemini CLIOpenCodeAny agent that reads SKILL.md folders
- Time
- 10 min read · updated Nov 13, 2026
The short answer
- To turn HTML into a video, open the page in a browser and either record it while it plays or render it frame by frame: pause the animation, move it to each frame’s exact time, take a screenshot, and encode the screenshots into an MP4 with FFmpeg. Recording is quicker to set up; rendering frame by frame gives a smooth file on any machine, because how fast the computer draws no longer matters.
- You can script the frame-by-frame route yourself with Playwright and FFmpeg, or use a framework that does it: HyperFrames renders plain HTML under Apache 2.0, and Remotion renders React components under its own license. For an animation drawn on a
<canvas>,captureStream()andMediaRecorderrecord it inside the browser.
Pick a method
Why frame-by-frame rendering matters
A recording captures the page while real time runs. Whatever the browser has drawn when a frame is sampled is what ends up in the file, so a moment that is slow to draw shows up as a stutter.
Rendering frame by frame takes real time out of it. The renderer stops the page’s clock, moves the animation to exactly 0, 1/30 and 2/30 of a second and so on, and takes a screenshot of each moment. A slow frame only takes longer to capture; it doesn’t change the video. The README of timesnap, an open-source tool built on this idea, explains it: time runs on a virtual timeline, so the page finishes its work before each screenshot, and capture can run slower than real time.
There are two clocks to control. CSS animations, CSS transitions and the Web Animations API can be paused and set to any time through document.getAnimations(). JavaScript that reads Date, timers or requestAnimationFrame needs those replaced with fakes that move only when the renderer says so.
Method 1: render frame by frame with Playwright and FFmpeg
This script needs Node.js, Playwright (npm install playwright, then npx playwright install chromium) and FFmpeg. Put it next to your index.html. It renders 5 seconds at 30 frames a second into a frames folder.
Run node render.mjs, then join the frames into an MP4:
-framerate 30gives the frame rate you rendered at. FFmpeg’s image sequence reader assumes 25 without it, so 150 frames would play for 6 seconds instead of 5.frames/%04d.pngmatches0000.png,0001.pngand so on.-pix_fmt yuv420pkeeps 4:2:0 color, which most H.264 profiles use. In our test, FFmpeg picked 4:4:4 and the High 4:4:4 Predictive profile when the flag was left out.-movflags +faststartmoves the file’s index to the start, which FFmpeg’s documentation describes as better for playback.
In our test (Playwright 1.63 with Chromium 153, FFmpeg 9.0.2), a page with a CSS animation and a requestAnimationFrame animation on a <canvas> rendered to a 5-second 1920×1080 H.264 MP4. The CSS animation came out byte for byte the same in every run. The canvas animation moved smoothly, but at a given frame it sat up to about 10 milliseconds off the target time, and not by the same amount in every run. For exact JavaScript animation, use a library timeline you can seek, which is what HyperFrames does.
- The script sets every CSS animation to the same time, which is right for animations that start when the page loads. One that starts later, on a click or a timer, needs its own start time added.
- It waits for
document.fonts.ready, which resolves once fonts have loaded and layout is done, so no frame is taken with a fallback font. - Neither
getAnimations()nor Playwright’s clock covers a playing<video>element. timecut, a BSD-3-Clause tool built on timesnap and Puppeteer, steps video playback too, but its README warns that CSS transitions and animations will likely not render as intended.
Method 2: HyperFrames
HyperFrames is HeyGen’s open-source framework for this route, under Apache 2.0. Its README sums it up as “Write HTML. Render video. Built for agents.” You write the video as an HTML page the size of the frame, mark when each element is on screen, and register a paused animation timeline. The renderer seeks each frame in headless Chrome and encodes the result with FFmpeg, so you never write the capture loop above.
- It needs Node.js 22 or newer and FFmpeg.
- Animation can come from GSAP, CSS, Lottie, Three.js, Anime.js, the Web Animations API or your own frame adapter, as long as it can be seeked.
- In version 0.8.192,
renderwrites MP4 by default, and also WebM, MOV, GIF, HLS or a PNG sequence. MOV and WebM keep transparency. The frame rate is--fps, else the composition’sdata-fps, else 30. npx hyperframes skills updateinstalls its agent skills, so a coding agent can write compositions for you.
The HyperFrames tutorial builds, checks and renders a full composition step by step.
Method 3: Remotion
Remotion renders frame by frame too, from React. A component reads the current frame number and draws that moment, and a composition pairs the component with its width, height, durationInFrames and fps. npx remotion render renders it, using a Chrome Headless Shell that Remotion downloads into node_modules.
Check the license before you use it at work. Remotion’s license page says it is “free to use for individuals and companies up to three people,” and that a Company License is “required only for entities ineligible for the Free License.” Its LICENSE.md makes you eligible for free use as an individual, a for-profit organization with up to 3 employees or a non-profit or not-for-profit organization, or while you are “evaluating whether Remotion is a good fit, and are not yet using it in a commercial way.” HyperFrames vs Remotion compares the two.
Method 4: record the screen
When the animation is light and you need a clip now, record it. The first two options need nothing installed.
- Mac: press Shift-Command-5 and choose to record the entire screen or a portion of it. Recordings are saved as .mov files.
- Windows: open Snipping Tool, select Record, then New, select the area to record, then Start. Select Stop when you are done.
- Playwright: pass
recordVideowhen you create a browser context. The video is saved when the context closes.
Playwright records at 25 frames a second unless you set fps. In our test it wrote a WebM file, and the recording began when the page opened, so it ran about a second longer than the wait. Trim the start when you convert it:
Puppeteer has page.record({ path: 'recording.mp4' }), which its docs say outputs MP4. They mark the older page.screencast() as obsolete.
Method 5: record a canvas with MediaRecorder
If the animation is drawn on a <canvas>, the browser can record it without screenshots. canvas.captureStream(30) returns a media stream of the canvas, and MediaRecorder writes the stream to a file. It runs in the page itself, so it suits an export button in a web app.
- Only the canvas is recorded: the stream holds a single canvas track, and the HTML around it isn’t in the file.
- It records in real time, for as long as you let it run. In our tests the frame rate averaged a little over 30, not exactly 30.
MediaRecorder.isTypeSupported()tells you which formats the browser can write. In our test in Chromium 153, plainvideo/mp4gave an MP4 with VP9 video inside, andvideo/mp4;codecs=avc1gave H.264, so the snippet asks for that first.
If the HTML came from Google Web Designer
Google Web Designer converts its own documents. In Design view, choose File > Convert document type > Video..., then publish the document to get the MP4. Its help pages list the export as MP4 with H.264 video and 48 kHz audio, at 30 frames a second by default, and video ads publish only to your own file system. Video isn’t offered on Linux, and HTML documents without pages, AMPHTML ads, video ads, image ads and animated GIFs can’t be converted.
Let an agent make the video
A coding agent such as Claude Code, Codex or Cursor can write the HTML, check it and run the render. Lookbk’s video skills give the agent a finished design to fill in: a HyperFrames template, a brief whose fields a script checks, and scripts that render the MP4 on your machine.
- Kinetic Title Drop (free): a six-second 1920×1080 type-only title video from three short lines, a chip, a footer and three colors.
- Pixel Quest Promo (free): a 20-second 8-bit promo that plays like a platform game, drawn in code, with a cue sheet for adding chiptune music.
- Cursor Walkthrough: a 9 to 15 second walkthrough of an app interface drawn in HTML and CSS, where a cursor clicks, types and drags, cut to an original beat-synced soundtrack.
- Zoom Cam Walkthrough: a 40 to 60 second walkthrough that looks like a polished screen recording but is rendered from a step script, using a live HTML mock of your app or screenshots of it.
Every video skill is under video skills, and How to make videos with Claude Code walks through a first render.
Common problems
The MP4 stutters, but the page looks smooth in the browser
It was recorded in real time and some moments took too long to draw. Render it frame by frame instead.
Something still jumps in a frame-by-frame render
It moves on a clock the renderer doesn’t control, such as a playing
<video>. Drive it from the animation timeline, or step it the way timecut steps video playback.The first frames show a fallback font
Take the first screenshot after
document.fonts.readyresolves, and load the fonts from files in the project so every render uses the same ones.The video won’t play in some players
Encode with
-pix_fmt yuv420p. Without it, FFmpeg can keep 4:4:4 color from PNG frames, which only the High 4:4:4 Predictive H.264 profile supports.The Playwright recording is small or blurry
Set
recordVideo.sizeto your viewport size. Without it, Playwright scales the video down to fit 800×800.
Common questions
- Can I convert an HTML file to MP4 by renaming it?
- No. An HTML file is text that a browser draws, and renaming it doesn’t change what is inside. Open it in a browser, then record or render it as shown above.
- My HTML page plays a video. How do I get that video out?
- The video is a separate file. Find the
<video>element in the HTML: itssrcattribute, or thesrcof a<source>element inside it, is the address of the file. - Can the video have a transparent background?
- Use a format that keeps it. HyperFrames 0.8.192 renders MOV and WebM with transparency (
--format movor--format webm), and--format png-sequencewrites RGBA frames. - What frame rate should I render at?
- Pick one and use it in both places: the
FPSconstant in the script and-frameratein the FFmpeg command. HyperFrames takes--fps, else the composition’sdata-fps, else 30.
Sources
What this guide says about other companies’ tools comes from their own documentation, checked on Nov 13, 2026.
- MDN: Document.getAnimations() (opens in a new tab)
- MDN: Animation.currentTime (opens in a new tab)
- MDN: FontFaceSet.ready (opens in a new tab)
- Playwright docs: Clock (opens in a new tab)
- Playwright docs: Library (installing browsers) (opens in a new tab)
- Playwright docs: Videos (opens in a new tab)
- Playwright API: browser.newContext() recordVideo (opens in a new tab)
- Puppeteer API: Page.record() (opens in a new tab)
- Puppeteer API: Page.screencast() (opens in a new tab)
- FFmpeg formats documentation (image2 demuxer, mp4 faststart) (opens in a new tab)
- MDN: Web video codec guide (AVC profiles) (opens in a new tab)
- timesnap on GitHub (README, BSD-3-Clause) (opens in a new tab)
- timecut on GitHub (README, BSD-3-Clause) (opens in a new tab)
- HyperFrames on GitHub (README and Apache 2.0 license) (opens in a new tab)
- Remotion docs: The fundamentals (opens in a new tab)
- Remotion docs: Render your video (opens in a new tab)
- Remotion docs: Chrome Headless Shell (opens in a new tab)
- Remotion license page (opens in a new tab)
- Remotion license file (opens in a new tab)
- Apple Mac User Guide: Take a screenshot or screen recording (opens in a new tab)
- Microsoft Support: Use Snipping Tool (opens in a new tab)
- MDN: HTMLCanvasElement.captureStream() (opens in a new tab)
- MDN: MediaRecorder (opens in a new tab)
- Google Web Designer Help: Convert HTML documents to video or image ads (opens in a new tab)
- Google Web Designer Help: About video ads (opens in a new tab)
- MDN: The <video> element (opens in a new tab)
Did this guide help?
Read next
All guidesHyperFrames tutorial: render an HTML page to MP4
Turn HTML into an MP4 without screen recording: set up HyperFrames, write the video as an HTML page with GSAP, check it, render it, or hand it to an agent.
Remotion skill vs HyperFrames skills for Claude Code
Remotion’s official agent skills and HyperFrames’ skills both let Claude Code turn code into video. What each installs, what the agent writes, and the license.
How to make videos with Claude Code
Three ways to make MP4 videos with Claude Code: Remotion’s skills, HyperFrames, or a ready-made video skill. Setup, a first render and fixes.
Remotion alternatives for agent-made video (2026)
HyperFrames, Motion Canvas, Revideo and a browser plus FFmpeg, compared with Remotion: what your agent writes, the license, and when to stay put.
See a skill’s result before you install it.
Every skill page shows what it makes, what it needs and which agents can run it.



