VideoFlowcodeGitHubTry itCoreRenderersReact Video EditorPlaygroundExamplesDocscodeGitHubTry it
Getting started
InstallationQuick startCore conceptsYour first video
Builder
Builder APITime formatsParallel & wait
Layers
TextImageVideoAudioCaptionsShapeGroups
Animation
Animate & keyframesEasing functionsTransitionsEffects
Renderers
Browser rendererServer rendererDOM preview
React Video Editor
QuickstartThemingUploadsCustom panelsHooks & commandsKeyboard shortcuts
API reference
Overview@videoflow/core@videoflow/renderer-browser@videoflow/renderer-server@videoflow/renderer-dom@videoflow/react-video-editor

Rendering in the browser

@videoflow/renderer-browser encodes frames with WebCodecs and muxes into MP4 inside a Web Worker. It runs in any recent Chrome, Edge, Firefox, or Safari and returns a Blob you can download, upload, or play back.

Minimal example

import BrowserRenderer from '@videoflow/renderer-browser';
import VideoFlow from '@videoflow/core';

const $ = new VideoFlow({ width: 1920, height: 1080, fps: 30 });
$.addText({ text: 'Exported from the browser' }).fadeIn('500ms');
$.wait('2s');

const json = await $.compile();
const blob = await BrowserRenderer.render(json);

// Download
const url = URL.createObjectURL(blob);
Object.assign(document.createElement('a'), { href: url, download: 'out.mp4' }).click();

Options

OptionDefaultNotes
signalAbortSignal — abort() cancels cleanly.
onProgress(p: number) => void. p is the fraction of frames done (0..1).
workertrueSet false to run on the main thread (debugging only).
verbosefalseLog frame-level timing to the console.
bitrateautoBits per second. Auto scales with resolution.
codec'avc'avc | vp9 | hevc where the browser supports it.

Progress UI

const ctrl = new AbortController();

const blob = await BrowserRenderer.render(json, {
  signal: ctrl.signal,
  onProgress: (p) => {
    // p is 0..1 (fraction of frames done)
    progressBar.style.width = (p * 100).toFixed(1) + '%';
  },
});

// Cancel from a UI button:
cancelBtn.addEventListener('click', () => ctrl.abort());
Memory. A 1080p60 30-second render at AVC ~8 Mbps fits comfortably. For longer clips or 4K, keep an eye on the Worker's memory — prefer chunked muxing (the renderer does this by default) over holding all encoded frames in RAM.

One-shot helper

If you're already in a VideoFlow instance and don't need to hold the JSON, call $.renderVideo() — it compiles and picks a renderer for you.

const blob = await $.renderVideo({ onProgress: (p) => console.log(`${Math.round(p * 100)}%`) });
VideoFlow

Open-source toolkit for composing videos from code.

Product

CoreRenderersReact Video EditorPlayground

Learn

DocsAPI referenceExamplesvs. Remotionvs. FFmpeg

Project

GitHubLicenseContact

Legal

TermsPrivacy
© 2026 VideoFlow. Apache-2.0 core.