Skip to content

Motion Canvas and Revideo: animation written in TypeScript

Updated 2026-11-06

Motion Canvas is a free TypeScript library for code animation with a live browser editor; you render from that editor. Revideo grew out of it and adds headless rendering, so a script can make the MP4. Both clips below are real renders we made on 2026-11-06.

Real: 6 seconds at 1920x1080 and 30 fps, rendered with Motion Canvas 3.17.2 and its FFmpeg exporter in about 6 seconds, driven from a headless browser (100 KB). Made by Glidezo, not by the Motion Canvas team.
Real: 6 seconds at 1920x1080 and 30 fps, rendered headlessly with Revideo 0.11.0 in 4 to 5 seconds (107 KB for the web). Made by Glidezo, not by the Revideo team.

Glidezo isn't connected to either project, and we don't run them on this site. Our own skills use HyperFrames, which competes with both.

The two at a glance

Motion CanvasRevideo
Latest stable3.17.2, December 14, 20240.11.0, July 10, 2026
Last code changeJuly 2, 2026 (docs moved to a new domain)July 15, 2026
Render fromThe browser editor's RENDER buttonrenderVideo() in a script, or its CLI
MP4 outputWith the @motion-canvas/ffmpeg plugin; otherwise an image sequenceBuilt in
GitHub starsAbout 19,700About 4,200
LicenceMITMIT

Neither project is archived. Motion Canvas has had no stable release in almost two years, and Revideo had a gap of about 17 months before its July 2026 release, so check their activity before you build anything long-lived on either.

Motion Canvas: the scene we rendered

Start a project with the official command (it asks a few questions; pick "Video (FFmpeg)" as the exporter if you want an MP4), then npm start opens the editor at localhost:9000:

npm init @motion-canvas@latest
cd my-animation
npm install
npm start

Our scene: a title, a line drawing in, and a circle and a square swapping places. A scene is a generator function, and each yield* waits for an animation to finish:

import {Circle, Line, Rect, Txt, makeScene2D} from '@motion-canvas/2d';
import {
  all,
  createRef,
  easeInOutCubic,
  easeOutBack,
  easeOutCubic,
  sequence,
  waitFor,
} from '@motion-canvas/core';

const BG = '#0a0a0b';
const FG = '#f4f4f5';
const ACCENT = '#8b7bff';
const MUTED = '#3f3f46';

// A title and three shapes driven by tweens: about 6 seconds at 30 fps.
export default makeScene2D(function* (view) {
  view.fill(BG);

  const title = createRef<Txt>();
  const subtitle = createRef<Txt>();
  const circle = createRef<Circle>();
  const square = createRef<Rect>();
  const line = createRef<Line>();

  view.add(
    <>
      <Txt
        ref={title}
        text="Motion Canvas"
        fontFamily="sans-serif"
        fontWeight={700}
        fontSize={110}
        fill={FG}
        y={-300}
        opacity={0}
      />
      <Txt
        ref={subtitle}
        text="animations written in TypeScript"
        fontFamily="sans-serif"
        fontSize={44}
        fill={FG}
        opacity={0}
        y={-150}
      />
      <Line
        ref={line}
        points={[
          [-600, 220],
          [600, 220],
        ]}
        stroke={MUTED}
        lineWidth={6}
        end={0}
      />
      <Circle ref={circle} x={-600} y={100} size={0} fill={ACCENT} />
      <Rect
        ref={square}
        x={600}
        y={100}
        size={0}
        radius={24}
        stroke={FG}
        lineWidth={8}
      />
    </>,
  );

  yield* all(
    title().opacity(1, 0.6),
    title().y(-260, 0.6, easeOutCubic),
  );
  yield* subtitle().opacity(0.7, 0.4);
  yield* all(
    line().end(1, 0.8, easeInOutCubic),
    sequence(
      0.15,
      circle().size(160, 0.6, easeOutBack),
      square().size(160, 0.6, easeOutBack),
    ),
  );
  yield* all(
    circle().x(600, 1.4, easeInOutCubic),
    square().x(-600, 1.4, easeInOutCubic),
    square().rotation(180, 1.4, easeInOutCubic),
  );
  yield* all(
    circle().fill(FG, 0.6),
    square().stroke(ACCENT, 0.6),
    circle().scale(1.2, 0.3).to(1, 0.3),
  );
  yield* waitFor(2.2);
});

How we got the MP4. Motion Canvas has no render command, so pressing RENDER in the editor is the normal way. To do it without clicking, we opened the editor at localhost:9000/?render, which starts a render as soon as the page loads, in a headless browser. Render settings (30 fps, 1920x1080, the FFmpeg exporter) come from the project's project.meta file, which the editor writes. The 6-second clip took about 6 seconds, or 7 with the browser starting and closing (3 runs, 4-core Linux, no GPU). The install took 17 seconds and 274 MB.

Revideo: the same scene, rendered by a script

Revideo projects look almost the same: imports come from @revideo/*, a scene takes a name, and settings live in code. Create one with npm init @revideo@latest. Then a short script renders it, with no editor open:

import {renderVideo} from '@revideo/renderer';

// Headless render: renderVideo starts Vite, opens the project in headless Chrome (Puppeteer)
// and writes the MP4. CHROME_PATH lets you reuse an installed Chrome/Chromium when Puppeteer's
// own download was skipped (npm 11 blocks install scripts by default).
async function render(): Promise<void> {
  const file = await renderVideo({
    projectFile: './src/project.tsx',
    settings: {
      outFile: 'revideo-demo.mp4',
      outDir: './output',
      logProgress: true,
      ...(process.env['CHROME_PATH']
        ? {puppeteer: {executablePath: process.env['CHROME_PATH']}}
        : {}),
    },
  });
  console.log(`Rendered video to ${file}`);
}

render().catch((error: unknown) => {
  console.error('Render failed:', error);
  process.exitCode = 1;
});

Run it with DISABLE_TELEMETRY=true if you don't want Revideo's renderer to send usage events, which it does by default. The 6-second clip took 4.3 to 5.2 seconds (3 runs); the very first run took 6.3. The install took 34 seconds and 403 MB, and Puppeteer also downloaded its own Chrome, about 680 MB more, outside the project. We had to add @types/node before the starter's TypeScript would compile.

With Claude Code or Codex

Both are plain TypeScript, so a coding agent such as Claude Code or Codex can write a scene. Revideo suits an agent better, because the agent can run the render itself; with Motion Canvas, someone presses RENDER, or you script the editor as we did. Claude wrote both of our scenes from a short brief, and they needed one fix (the title and subtitle overlapped at first). That's one small test, not a measure of how well agents write these libraries.

What they can't do

  • Neither makes footage or people. They draw shapes, text, images and video clips you give them.
  • Motion Canvas can't render headlessly without a workaround like ours, and its MP4 exporter is described in its own docs as "still relatively new".
  • Revideo's docs now live under Midrender's site, and we couldn't find an official word on how much the company invests in the open-source engine.
  • Both need Node.js and a browser to render: Revideo downloads its own.

Comparing tools? HyperFrames renders web pages to video and runs our free skills; Remotion uses React, with a paid licence above three people; Manim uses Python, for maths.

Questions

What is Motion Canvas?
A free, MIT-licensed TypeScript library for animations written as code, with a browser editor that previews them live. You describe a scene with generator functions and tweens, and render it to frames or an MP4 from the editor.
Is Motion Canvas still maintained?
Lightly. Its latest stable release, 3.17.2, came out on December 14, 2024, with an alpha in February 2025. The repo's last change, in July 2026, moved its docs to a new domain. It isn't archived, and it still works: we rendered with it on November 6, 2026.
Can Motion Canvas render without the editor?
Not with a built-in command. Rendering starts from the editor's RENDER button. Headless rendering is an open request on GitHub, and its pull request was still a draft on November 6, 2026. A ?render address flag starts a render when the editor opens, which we drove from a headless browser.
What is Revideo?
An MIT-licensed video engine that grew out of Motion Canvas (its licence still carries Motion Canvas's copyright). It adds a headless renderVideo() function, so a script or a server can render with no editor. It's the engine behind a company called Midrender.
Motion Canvas or Revideo?
Motion Canvas if you want to animate by hand with a live preview. Revideo if a script, an agent or a server should render videos on its own. The scene code is very similar, so you can move between them.
Does Revideo send data anywhere?
Yes, by default its renderer sends usage events to PostHog. We set DISABLE_TELEMETRY=true for our renders, which turns that off.

Sources