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 →Cinematic Code: How to Stack and Animate GLSL Effects in VideoFlowHeadless Video as a Service: Building a Scalable Rendering API with Node.jsProgrammatic Video Localization: Scaling Multilingual Content with VideoFlowFrom JSON to MP4 in the Browser: Zero-Server Video ExportAnimated Infographics as Code: Building a Reusable Data-Viz LibraryCI/CD for Video: Building a Diffable Asset Pipeline with VideoFlowBeyond Static Images: Generating Dynamic Social Share Videos from MetadataHow to Embed a Full-Featured Video Editor in Your React App
© 2026 VideoFlow. Apache-2.0 core.