How to Build a Frame-Accurate Video Preview in React with VideoFlow
July 8, 2026 · By VideoFlowLearn how to build a high-performance, frame-accurate video preview in React using VideoFlow's DOM renderer for seamless scrubbing and live effects.
How to Build a Frame-Accurate Video Preview in React with VideoFlow
Building a video editor or a content automation dashboard requires more than just a simple <video> tag. When you are composing videos from code, you need a preview that is frame-accurate, capable of sub-second scrubbing, and perfectly synchronized with your underlying data model.
In this guide, we will explore how to use the @videoflow/renderer-dom package to build a high-performance, interactive video preview directly inside a React application.
The Challenge: Why Native Video Tags Fail for Editors
Standard HTML5 video elements are designed for linear playback. They handle buffering and streaming well, but they struggle with the precision required for video editing. If you try to jump to a specific frame or overlay complex GLSL effects dynamically, native elements often stutter or show blank frames.
VideoFlow solves this by treating the preview as a first-class citizen. Instead of playing a rendered MP4, the DomRenderer renders your VideoJSON schema directly into the DOM using a dedicated Shadow root. This ensures that what you see in the preview is byte-for-byte identical to what will eventually be rendered on the server.

Setting Up the DomRenderer in React
The @videoflow/renderer-dom package provides the DomRenderer class. To integrate it with React, we use a useRef to hold the renderer instance and a useEffect to manage its lifecycle.
import React, { useEffect, useRef } from 'react';
import VideoFlow from '@videoflow/core';
import DomRenderer from '@videoflow/renderer-dom';
export const VideoPreview = ({ videoJson }) => {
const containerRef = useRef<HTMLDivElement>(null);
const rendererRef = useRef<DomRenderer | null>(null);
useEffect(() => {
if (!containerRef.current) return;
// 1. Initialize the renderer
const renderer = new DomRenderer(containerRef.current);
rendererRef.current = renderer;
// 2. Load the compiled VideoJSON
renderer.loadVideo(videoJson);
return () => {
renderer.destroy();
};
}, [videoJson]);
return <div ref={containerRef} style={{ width: '100%', aspectRatio: '16/9' }} />;
};
Frame-Accurate Scrubbing
One of the most powerful features of VideoFlow is the ability to render specific frames on demand. This is essential for building timelines where the user can drag a playhead to see exact moments in time.

To implement scrubbing, you simply call renderer.renderFrame(frameIndex). Because VideoFlow uses a resolution-agnostic coordinate system (where 1em is 1% of the project width), the preview scales perfectly to any container size while maintaining its internal proportions.
// Example: Scrubbing to a specific timestamp
const handleSeek = (seconds: number) => {
const fps = 30;
const frame = Math.floor(seconds * fps);
rendererRef.current?.renderFrame(frame);
};
Adding Cinematic Effects and Transitions
Even in the live DOM preview, you have access to the full suite of VideoFlow transitions and GLSL effects. Whether you're using blurResolve for a smooth entrance or stacking vhsDistortion and bloom for a retro aesthetic, the DomRenderer handles the heavy lifting using WebGL.
const $ = new VideoFlow();
const title = $.addText(
{
text: 'Frame Accurate',
fontSize: 8,
color: '#FF5A1F',
effects: [{ effect: 'glow', params: { strength: 0.5 } }]
},
{
transitionIn: { transition: 'slideUp', duration: '500ms' }
}
);
$.wait('2s');
const json = await $.compile();
Why This Matters for Your Pipeline
By using the DomRenderer during development and the BrowserRenderer or ServerRenderer for export, you ensure a seamless "What You See Is What You Get" (WYSIWYG) experience. This eliminates the frustrating feedback loop of rendering a video just to check if an animation looks right.
If you want to see this in action without writing any code, head over to the VideoFlow Playground. It's built entirely on these principles, giving you a real-time, interactive environment to experiment with the Core builder API.
For teams building full-scale editing suites, we also offer the @videoflow/react-video-editor, a drop-in component that includes a multi-track timeline, inspector, and keyframe support out of the box.
Ready to start building? Check out our Getting Started guide or dive into the source on GitHub.