How to Unit Test Your Video Timelines with VideoFlow and TypeScript
August 12, 2026 · By VideoFlowStop guessing if your video timing is right. Learn how to use VideoFlow and TypeScript to unit test video timelines and catch regressions before you render.
How to Unit Test Your Video Timelines with VideoFlow and TypeScript
Building a programmatic video pipeline is a high-stakes engineering challenge. When you are generating thousands of personalized recap videos or automated social ads, a single regression in your timing logic can result in thousands of broken MP4s. If you are coming from the world of FFmpeg shell scripts or proprietary black-box APIs, you've likely accepted that "testing" means rendering a file and watching it manually.
But if you are treating video as code, you shouldn't have to wait for a render to know if your timeline is correct. Because VideoFlow represents every video as a portable, structured VideoJSON document, you can unit test your video timelines just like any other business logic.
In this guide, we'll look at how to use the @videoflow/core builder and standard TypeScript testing tools (like Vitest or Jest) to verify your video assets before they ever hit a GPU.
Why Unit Test a Video?
In a traditional video workflow, the "source of truth" is a binary project file. In a programmatic workflow using VideoFlow, the source of truth is code that produces JSON. This architectural shift unlocks several testing patterns:
- Timing Validation: Ensure that a title card never overlaps with a transition or that the background music fades out exactly when the video ends.
- Asset Presence: Verify that every dynamic image or video source is actually present in the final payload.
- Property Bounds: Assert that text overlays stay within safe margins or that effects aren't applied with invalid parameters.
- Regression Testing: When you update your video-generation logic, ensure that existing templates still produce the expected structure.

The Pattern: Compile and Assert
The core of testing VideoFlow is the $.compile() method. This method resolves all flow logic ($.wait, $.parallel, $.group), calculates absolute timestamps for every layer, and returns a plain JavaScript object.
You can read more about how this works in our guide to the builder API.
Here is a simple example of a test that verifies a transition duration:
import { describe, it, expect } from 'vitest';
import VideoFlow from '@videoflow/core';
describe('Marketing Template', () => {
it('should have a 500ms fade-in on the hero title', async () => {
const $ = new VideoFlow({ width: 1920, height: 1080 });
const title = $.addText(
{ text: 'Hello World' },
{ transitionIn: { transition: 'fade', duration: '500ms' } }
);
const json = await $.compile();
const layer = json.layers.find(l => l.id === title.id);
expect(layer?.settings.transitionIn?.duration).toBe(0.5);
});
});
Testing Complex Flows
One of the most common bugs in automated video is "timing drift"—where sequential layers slowly fall out of sync. By testing the startTime of layers in the compiled JSON, you can catch these errors in CI.
Imagine a function that generates a sequence of product features. We want to ensure each feature stays on screen for exactly 2 seconds:
async function createFeatureSequence(features: string[]) {
const $ = new VideoFlow();
for (const feature of features) {
$.addText({ text: feature });
$.wait('2s');
}
return $.compile();
}
it('should space features exactly 2 seconds apart', async () => {
const features = ['Fast', 'Secure', 'Open Source'];
const json = await createFeatureSequence(features);
// Assert that the third feature starts at exactly 4 seconds
expect(json.layers[2].settings.startTime).toBe(4);
});
This approach is significantly faster and cheaper than the "render-and-check" loop required by Remotion alternatives. You aren't spinning up a browser or a headless renderer; you are just validating a JSON schema.

Validating Effects and Transitions
VideoFlow ships with 27 transitions and 42 GLSL effects. Because these are referenced by string identifiers in the JSON, it's easy to accidentally type vhs instead of vhsDistortion.
While TypeScript helps catch these at the builder level, unit tests can verify that your dynamic logic is applying the correct effect based on input data:
it('should apply a bloom effect only for premium users', async () => {
const $ = new VideoFlow();
const isPremium = true;
$.addImage({
effects: isPremium ? [{ effect: 'bloom', params: { strength: 0.5 } }] : []
}, { source: '...' });
const json = await $.compile();
const effects = json.layers[0].properties.effects;
expect(effects).toContainEqual(expect.objectContaining({ effect: 'bloom' }));
});
Integrating with CI/CD
Because VideoFlow is pure TypeScript, these tests run in any standard Node.js environment. You don't need FFmpeg, Chrome, or any heavy binaries installed to run your timeline logic tests. This makes it trivial to block a deployment if a change to your video template breaks the layout.
Once your tests pass, you can confidently hand the VideoJSON to any of our three official renderers for final export.
Getting Started
Ready to build a more robust video pipeline?
- Try the Playground: Experiment with the builder API in your browser at the VideoFlow Playground.
- Read the Guides: Check out our Getting Started guide to set up your first project.
- Explore the Source: See how we've implemented the core timing logic on GitHub.
By treating your video timelines as testable data, you move away from fragile manual workflows and toward a truly professional automated video stack. If you found this useful, you might also enjoy our deep dive on JSON as the New MP4: Why Your Video Pipeline Should Be Diffable.