VideoFlowcodeGitHubTry itCoreRenderersReact Video EditorPlaygroundExamplesDocscodeGitHubTry it
← Back to Blog

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

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.

The three official renderers for VideoFlow

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.

Precise frame selection in VideoFlow

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.

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 →Browser-Side Video Export: Zero-Server Rendering with WebCodecsCinematic GLSL: Stacking Effects for a Retro VHS Look in VideoFlowHow to Generate Personalized Video Ads from a CSV with TypeScriptBeyond the Prompt: Why LLMs Need Portable VideoJSONFrom Markdown to MP4: Automate Your Documentation Video PipelineHow to Build a Frame-Accurate Video Preview in React with VideoFlowHow to Render MP4 Videos in Node.js without FFmpegBuilding Reusable Programmatic Video Components with Layer Groups
© 2026 VideoFlow. Apache-2.0 core.