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

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 EditorPlayground

Learn

DocsAPI referenceExamplesvs. Remotionvs. FFmpeg

Project

GitHubLicenseContactTermsPrivacy

From the blog

All posts →Automating Social Media Captions: A Developer's Guide to Frame-Perfect SubtitlesMastering Programmatic Video Transitions: A Developer's GuideThe Video Markdown Pattern: Turning Static Content into Automated MP4sZero-Cost Video Rendering: How to Export MP4s Directly in the BrowserBuilding an AI Video Agent: How to Generate MP4s from LLM Prompts with VideoJSONAutomating E-commerce: How to Generate 1,000 Product Videos with TypeScriptThe Blueprint for Automated Video: Building a Reusable Component LibraryBuilding a Video-First SaaS: Embed a Multi-Track Editor in 10 Lines
© 2026 VideoFlow. Apache-2.0 core.