VideoFlowcodeGitHubStudioTry itCoreRenderersReact Video EditorPlaygroundExamplesDocscodeGitHubStudioTry 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

Live preview with the DOM renderer

@videoflow/renderer-dom paints a running composition into a DOM element you own. It's what the playground and the React video editor use internally. Seekable, no recompilation on each edit, and completely isolated in a shadow root.

Minimal example

import DomRenderer from '@videoflow/renderer-dom';

const host = document.getElementById('player');
const r = new DomRenderer(host);

await r.loadVideo(videoJSON);
await r.play();                   // auto-loops

// Or scrub precisely:
await r.seek(42);                 // frame 42
await r.renderFrame(0);           // paint a single frame
r.stop();
r.destroy();

Methods

MethodEffect
new DomRenderer(host)Attach to a DOM element. Creates a shadow root internally.
.loadVideo(json)Load or swap in a VideoJSON. Resolves when media is ready.
.play()Start a rAF loop. Auto-loops by default.
.stop()Pause at the current frame.
.seek(frame)Jump to a specific frame (integer).
.renderFrame(frame)Paint a single frame without starting a play loop.
.destroy()Tear down. Call on unmount.

Properties & events

NameNotes
onFrame: (frame) => voidFires on every painted frame during playback. Use for a scrub bar.
currentFrameRead-only. Last painted frame.
durationComposition duration in seconds.
fpsFrom the loaded video.

Granular updates

Calling loadVideo() reloads everything. For typing-speed edits, use the incremental patch API — it skips decode for unchanged layers:

await r.updateVideo({ duration: 4 });        // top-level patch
await r.addLayer(newLayer);                  // append a layer
await r.removeLayer(layerId);                // drop one
await r.reorderLayers([id3, id1, id2]);      // reorder

// Patch an existing layer. Each key is its own channel — `properties` and
// `animations` REPLACE wholesale, so pass the full post-edit object; only
// `settings` is shallow-merged.
await r.updateLayer(layerId, {
  properties: { ...layer.properties, scale: 1.2 },
  settings: { startTime: 1.5 },
});

Every mutation is queued internally, so they can be fired without awaiting each one, and each concludes by re-rendering the current frame.

Custom layer types

DomRenderer owns its own layer-type registry, so a preview can render layer types the library doesn't ship. Register between construction and the first loadVideo():

import DomRenderer, { RuntimeVisualLayer } from '@videoflow/renderer-dom';

const r = new DomRenderer(host);
r.registerLayerType('custom', {
  runtime: RuntimeCustomLayer,
  propertiesDefinition: CustomLayer.propertiesDefinition,
});
await r.loadVideo(videoJSON);

Registrations stay attached to that instance and survive reloads. Register the same type on the renderer you export with and preview and export agree. See the browser renderer guide for the full contract.

Use it as a headless player. Mount it in a hidden host, call renderFrame(n) to rasterise thumbnails, and read the canvas contents — no MP4 encode needed.

VideoFlow

Open-source toolkit for composing videos from code.

Product

CoreRenderersReact Video EditorPlaygroundStudio

Learn

DocsAPI referenceExamplesvs. Remotionvs. FFmpeg

Project

GitHubLicenseContactTermsPrivacy

From the blog

All posts →Building a "Canva for Video" with the @videoflow/react-video-editorAutomating Social Media Captions: A Developer's Guide to Frame-Perfect SubtitlesBeyond Node: How to Render Cinematic Videos from Python and GoBuilding a Video Rendering API with Node.js and VideoFlow (No FFmpeg Required)Mastering Programmatic Video Transitions: A Developer's GuideProgrammatic Video Storage: Why Your MP4s Should Live as Version-Controlled JSONThe Video Markdown Pattern: Turning Static Content into Automated MP4sZero-Cost Video Rendering: How to Export MP4s Directly in the Browser
© 2026 VideoFlow. Apache-2.0 core.