Skip to content

Live preview with the DOM renderer

@ilovevideoeditor/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

javascript
import DomRenderer from '@ilovevideoeditor/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:

javascript
r.updateVideo({ duration: 4 });          // top-level patch
r.addLayer(newLayer);                    // append a layer
r.removeLayer(layerId);                  // drop one
r.updateLayer(layerId, { scale: 1.2 });  // patch props on an existing layer
r.reorderLayers([id3, id1, id2]);        // reorder

NOTE

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.

Released under the MIT License.