Turn web animation into video.

Render CSS, GSAP, Framer Motion, Three.js and canvas to MP4, frame by frame. There is no new animation API to learn.

new · experimental Need speed? A browser-free renderer that beat fframes in 6 of 7 measured lanes.
Get started
$ npx @helios-project/cli init
<helios-player> connectingsunrise.html · 1920×1080 · 30 fps · 240 frames
Frame 120 of sunrise.html: a sun rising along an arc, with outlined exposures labelled f 0 to f 96, above the title 'Video is light over time.'
00:04:00f 120/239
Live, not a recording: <helios-player> playing sunrise.html, plain CSS @keyframes. Step with ← →. Edit the title: it arrives as inputProps, the way you’d render one video per customer.
License
Free for commercial use (ELv2)
Write in
Any framework, or plain HTML
Renders
Headless Chromium, or no browser
Status
Beta · monthly releases

How it compares

Remotion is the incumbent, and a good one. Helios makes a different bet: let the browser animate, and only control the clock.

QuestionHeliosRemotionfframes
You writeAny web page: CSS, GSAP, Framer Motion, Three.js, canvas; any framework or noneReact componentsRust & SVG
Renders onHeadless Chromium (npm), or a browser-free native renderer on CPU or Apple GPU (experimental, from source)Your infrastructure; server- and client-side renderingGPU
Determinism checkhelios verify renders frames forwards and backwards and names any that differNot stated on its home pageNot stated on its home page
Coding agentsAgent skills, plus an MCP server with an in-chat playerAgent SkillsAgent skill
Cost for a 10-person companyFree (Elastic License 2.0)Company License: $25 per seat a month, or $0.01 per render with a $100 monthly minimumNo license or pricing on its home page
MaturityBetaEstablished: 62k GitHub stars, 300+ customersNot stated on its home page

Remotion and fframes columns use only what their home pages said on 7 October 2026. Where Remotion leads today: maturity, a large ecosystem (5M+ installs a month, per its home page) and rendering on AWS Lambda.

Write it the way you already animate.

A Helios video is a web page. Helios owns the clock and the browser does the animating. Each tab is the real source of a film on this page.

warming.js (excerpt)
const rows = d3.csvParse(await (await fetch('./data/global-temp.csv')).text(), d3.autoType);const bars = svg.selectAll('rect').data(rows).join('rect').attr('x', (d) => x(d.year)).attr('width', x.bandwidth()).attr('fill', (d) => colour(d.temp)); helios.subscribe(({ currentFrame, fps }) => {const shown = progress(currentFrame / fps) * rows.length;bars.each(function (d, i) {const v = d.temp * d3.easeCubicOut(clamp(shown - i));d3.select(this).attr('y', Math.min(y(0), y(v))).attr('height', Math.abs(y(v) - y(0)));});});
Global temperature, 1880–2023D3 · NASA GISS data9 s · 270 frames · rendered in 13 ssourcemp4

Drive the browser. Don’t simulate it.

Browsers already have a superb animation engine. Helios tells it what time it is, one frame at a time, so the frame you preview is the frame in the MP4.

  1. f 24 t = 0.800 s
  2. f 60 t = 2.000 s
  3. f 96 t = 3.200 s
  4. f 135 t = 4.500 s
  5. f 180 t = 6.000 s
  6. f 222 t = 7.400 s
Real frames from sunrise.mp4. Each is the page seeked to its exact time; none depends on the frame before it, which is what helios verify checks. Download the 1080p MP4.
  1. t = n ÷ fps

    Set the clock

    Inside headless Chromium, performance.now(), Date.now() and requestAnimationFrame read virtual time. Math.random() is seeded.

  2. seek(t)

    Seek everything

    CSS and Web Animations, GSAP timelines, <video> and <audio> move to exactly t, after fonts and media load.

  3. capture

    Capture the frame

    DOM mode screenshots the page, so anything the browser draws works. Canvas mode reads the <canvas> directly.

  4. ffmpeg

    Encode

    Frames pipe in memory to FFmpeg (bundled with the CLI) and come out as H.264 MP4, audio mixed in.

Rendering guideArchitecture

Portable renderer · experimental · build from source, not on npm

Or skip the browser entirely.

Helios also has a native renderer with no Chromium in the loop. Hand it a Canvas module or a JSON scene plan and it draws each frame with Skia, encodes, and verifies the MP4. Same frame-exact model, much less overhead.

npm · beta

Browser renderer

Any web page: CSS, GSAP, Framer Motion, Three.js, React. Headless Chromium captures each frame.

22.7 s for the CSS sunrise in the hero

source · experimental

Portable renderer

Canvas 2D modules or portable-v1 scene plans. Native Skia on CPU, or Metal + VideoToolbox on Apple-silicon Macs. No Chromium, no system fonts, no network.

7.0 s for the same 8 s, 1080p sunrise in Canvas

Sunrise, no browserCanvas 2D · portable renderer8 s · 240 frames · rendered in 7 ssourcemp4
sunrise-native.mjs + render.mjs (excerpt)
// sunrise-native.mjs: no DOM, no CSS, no browser.export default {width: 1920, height: 1080, fps: { num: 30, den: 1 }, frameCount: 240,fonts: { display: jostBytes, mono: plexMonoBytes },   // explicit font bytesdraw(ctx, frame) {                                      // a pure function of the frameconst [x, y] = arc(frame.index / 239);ctx.beginPath(); ctx.arc(x, y, 70, 0, Math.PI * 2);ctx.fillStyle = sun; ctx.fill();},}; // render.mjsimport { renderCanvasModule } from '@helios-project/portable';await renderCanvasModule('./sunrise-native.mjs', 'out.mp4', { concurrency: 2 });

Timed on a no-GPU Linux VM pinned to 2 vCPUs: median of three alternating rounds, whole command to a verified MP4, both with x264 ultrafast (3.2× for this one scene). The two versions draw the scene differently (CSS animations vs Canvas 2D), so they look alike but aren’t pixel-identical. Native source.

What it doesn’t do

No DOM or CSS layout, no JavaScript inside plans, no springs or browser animation APIs, and existing HTML or React compositions aren’t converted: they keep the browser renderer. It’s an unpublished workspace package: build it from the Helios repo. The GPU lane is macOS arm64 only.

Portable renderer · experimental · measured, with receipts

Ahead of fframes in 6 of 7 lanes. Ahead of Remotion in all 5.

The browser-free portable renderer against fframes and Remotion: CPU on an M3 Pro and on a small Linux VM, GPU on an M3 Pro. Method, raw receipts and failed attempts are all published.

1.75×fframes’ speed · M3 Pro CPU, 1080p
1.90×fframes’ speed · 2-CPU Linux VM, 1080p
3.87×fframes on its own 4K scene · GPU task adapters

GPU · Apple M3 Pro

GPU · Apple M3 Pro studies: median seconds for Helios portable, fframes and Remotion, lower is faster
M3 Pro GPU4K circles, fframes’ showcase scene · task adaptersSerial adapters into a common 300 Mbps H.264 converter. Not fframes’ own concurrent product pipeline (whose outputs failed the quality floors), and not comparable with its published M5 Max 7.2 s.21.1 s81.7 sRemotion not in this lane3.87× fframesstudy
M3 Pro GPUGPU raster + matched software x26426.6 s31.1 s47.1 s1.17× fframes1.77× Remotionstudy
M3 Pro GPUHardware-encode pipelines (VideoToolbox)fframes exported faster in all four pairs. Different bitrate (100 vs 180 Mbps), colour and concurrency; the 0.46% delivered difference names no winner.6.29 s5.72 sRemotion not in this lanefframes ahead on exportstudy

CPU · M3 Pro and a 2-CPU Linux VM

CPU · M3 Pro and a 2-CPU Linux VM studies: median seconds for Helios portable, fframes and Remotion, lower is faster
M3 Pro CPUTextGrid 1080p · x264 ultrafast4.21 s7.36 s18.2 s1.75× fframes4.31× Remotionstudy
M3 Pro CPUTextGrid 1080p · x264 medium12.0 s15.2 s24.0 s1.27× fframes2.00× Remotionstudy
Linux VM, 2 logical CPUsTextGrid 1080p · x264 ultrafast20.7 s39.3 s60.0 s1.90× fframes2.90× Remotionstudy
Linux VM, 2 logical CPUsTextGrid 1080p · x264 medium69.2 s92.0 s152 s1.33× fframes2.20× Remotionstudy

CPU, 1080p TextGrid: 1.75× / 1.27× fframes’ speed on an M3 Pro (ultrafast / medium), 1.90× / 1.33× on a 2-CPU Linux VM; Remotion 4.31× to 2.20× slower. Full table

Read within each configuration. All timings are Helios’s experimental portable renderer (not the npm browser renderer) on one TextGrid workload (3,334 animated labels, 300 frames) unless named. GPU lanes are Apple M3 Pro, macOS arm64 only. Each engine is checked every frame against its own lossless reference; cross-engine pixel identity isn’t claimed. No general “fastest renderer” or end-to-end zero-copy claim is made.

Your agent writes it. Helios renders it.

Agents already write HTML and CSS well, which is all a Helios video is. The skills teach the rest: draw every frame from its time, check the frames, render. Six guided video types, from launch announcement to social cut, plus 24 visual styles, cartoons, music videos and genre recipes. See what agents made with them.

  1. 01

    Add the skills

    $ npx skills add BintzGavin/helios
  2. 02

    Ask for one of six kinds of video

    • Launch announcement
    • Promo
    • Explainer
    • Product demo
    • Testimonial
    • Social cut
  3. 03

    Preview, then render, in the chat

    helios mcp runs locally. In Claude, ChatGPT and other MCP Apps hosts the agent opens a player beside its reply. Claude Desktop has a one-file extension on the latest release.

helios mcp · in-chat player

Make a 15-second launch video for this project

Here’s a first cut. Scrub it, or click anything you want changed.› preview_video

Make the title slower

Slowed to 1.2 s and re-checked the frames.› get_frames · verify_video

Use this momentRender MP4launch.mp4 ✓
In hosts that support MCP Apps: scrub and step, click an element to point at it, and render the MP4 next to the page. Needs Node.js 20+ and a desktop app or coding agent. Setup guide
connect the MCP server
# Claude Code$ claude mcp add helios -- npx -y @helios-project/cli@latest mcp # Codex and ChatGPT desktop$ codex mcp add helios -- npx -y @helios-project/cli@latest mcp

Helios is a deterministic renderer: it calls no generative model. Tools: preview_video, get_frames, verify_video, render_video.

Free for commercial use. Here’s the whole deal.

Source-available under the Elastic License 2.0. No seats, no per-render fees, at any team size. The one thing you can’t do is sell Helios itself as a hosted service.

What the Elastic License 2.0 lets you do with Helios
Can I…AnswerDetails
Use it at a company of any sizeYesNo seats, no per-render fees, no render limits.
Sell products and videos made with itYesClient work, ads, launch videos, anything you render.
Build a SaaS that renders videos for your customersYesVideo editors, generation tools, white-label platforms, Helios embedded in your app.
Fork it, modify it, redistribute itYesKeep the license and copyright notices.
Offer Helios itself as a hosted or managed serviceNoReselling Helios rendering as infrastructure. Ask about a commercial license.

Read the license. Questions, or a license to offer Helios as a service: me@gavinbintz.com, the maintainer.

Start in one command.

Scaffold React, Vue, Svelte, Solid or vanilla TypeScript, or add Helios to a page you already have. Node.js 18+. The first render downloads a matching headless Chromium; FFmpeg comes with the CLI.

New project

terminal
$ npx @helios-project/cli init my-video$ cd my-video && npm install$ npm run dev        # opens Helios Studio$ npx @helios-project/cli render ./index.html -o out.mp4

Preview in your app

any page, any framework
<helios-playersrc="/videos/welcome.html"input-props='{"title":"Welcome, Ada"}'controls autoplay muted></helios-player>

A web component with a <video>-like API: play(), currentFrame, and in-browser export to MP4 or WebM.

One video per customer

render.mjs
import { Renderer } from '@helios-project/renderer'; for (const user of users) {const renderer = new Renderer({width: 1920, height: 1080, fps: 30, durationInSeconds: 8,inputProps: { title: `Welcome, ${user.name}` },});await renderer.render(url, `out/${user.id}.mp4`);}

Long renders split into chunks that run in parallel and join without re-encoding. Cloud adapters (Lambda, Cloud Run and more) are experimental.

Output
H.264 MP4 at any size and frame rate; MP4 or WebM from the in-browser player
Audio
A soundtrack, several tracks with volume, or the page’s own <audio> and <video>
Runs on
Node.js, headless Chromium and FFmpeg, locally or in Docker
Limits
The npm renderer needs Chromium; the browser-free renderer is experimental and source-only. Beta APIs can change.