VideoFlowcodeGitHubTry itCoreRenderersReact Video EditorPlaygroundExamplesDocscodeGitHubTry it
@videoflow/core · Apache-2.0

The JSON at the heart of every video.

A fluent, sequential TypeScript builder. Add layers, group them, chain animations, run branches in parallel, attach transition presets and GLSL effects — then compile the whole flow into a portable VideoJSON that any VideoFlow renderer can play.$ npm install @videoflow/corecode Source on GitHubAPI reference →
import VideoFlow from '@videoflow/core';

const $ = new VideoFlow({
  name: 'Demo',
  width: 1920,
  height: 1080,
  fps: 30,
});

const bg = $.addImage(
  { fit: 'cover', effects: [{ effect: 'bloom', params: { intensity: 0.6 } }] },
  { source: 'https://videoflow.dev/samples/sample.jpg' },
);
bg.animate({ filterBlur: 0 }, { filterBlur: 10 }, { duration: '5s', wait: false });

const title = $.addText({
  text: 'Hello!',
  fontSize: 2.5, fontWeight: 800, color: '#fff',
}, {
  transitionIn:  { transition: 'overshootPop',  duration: '500ms' },
  transitionOut: { transition: 'blurResolve',   duration: '400ms' },
});

$.wait('3s');

const json = await $.compile();
Layer types

Six building blocks.

TypeMethodKey properties
text$.addText()text, fontSize, fontWeight, color, letterSpacing, position
image$.addImage()source, fit, position, filterBlur, filterBrightness
video$.addVideo()source, sourceStart, speed, volume, fit
audio$.addAudio()source, volume, sourceStart, fadeIn, fadeOut
captions$.addCaptions()captions[], fontSize, color, position
shape$.addShape()shapeType, width, height, fill, strokeColor, cornerRadius
Layer groups

Composite a sub-tree as one.

$.group() nests layers inside a container that has its own transform, transitions, and effects. Inside the callback the flow's time pointer resets to 0, so children's timing is authored relative to the group. The group itself is a visual layer — animate scale or rotation on the group and the entire composited tree comes along.

Auto-derived timing: startTime defaults to the current flow time and sourceDuration defaults to the latest child's end. Nest groups inside groups for badges, cards, and scene units.

// Composite a sub-tree as one — transform, transition, animate together.
$.group(
  { position: [0.5, 0.5], scale: 1 },
  {
    transitionIn:  { transition: 'slideLeft', duration: '600ms' },
    transitionOut: { transition: 'zoom',           duration: '600ms' },
  },
  (card) => {
    card.animate({ scale: 1 }, { scale: 1.04 }, { duration: '2.5s', wait: false });

    $.addImage({ fit: 'cover', opacity: 0.55 }, { source: 'https://videoflow.dev/samples/sample.jpg' });
    $.addText({ text: 'Composite as one', fontSize: 4, color: '#fff' });
  },
);
Two card scenes with a nested badge group.
27 transition presets

Enter and leave with character.

Eight presets, back-to-back, on the same layer.

Attach a transition to any layer with one line. The preset library spans CSS-only transforms (fade, slideUp, overshootPop, rotate3dY) and WebGL passes (blurResolve, glitchResolve, radialZoom, lightSweepReveal, noiseDissolve) — all rendered identically across the three backends.

// 27 presets — fade, slideUp, zoom, overshootPop, blurResolve,
// glitchResolve, rotate3dY, lightSweepReveal, sliceAssemble, and more.
$.addText(
  { text: 'Hello', fontSize: 4 },
  {
    transitionIn:  { transition: 'overshootPop', duration: '500ms' },
    transitionOut: { transition: 'blurResolve',  duration: '400ms' },
  },
);
All transitions →
42 GLSL effects

Cinema-grade looks, declared as data.

Stack effects on any layer's effects array and animate their parameters with the dot-path notation (effects.bloom.intensity). The presets cover bloom, glow, motion blur, color grading, frosted glass, prism split, VHS, halftone, light leaks, shockwave, and more — 42 in total.

Set enabled: false to keep an effect's configuration while skipping its pass — useful when iterating in the editor or A/B-ing looks.

// 42 GLSL effects — bloom, glow, motionBlur, chromaticAberration, vignette,
// lightSweep, frostedGlass, vhsDistortion, prismSplit, halftone, lightLeak…
$.addImage(
  {
    fit: 'cover',
    effects: [
      { effect: 'colorGrade', params: { saturation: 0.4, temperature: 0.4 } },
      { effect: 'bloom',      params: { threshold: 0.6, intensity: 0.9 } },
      { effect: 'vignette',   params: { intensity: 0.6, radius: 0.85 } },
    ],
  },
  { source: 'https://videoflow.dev/samples/sample.jpg' },
);
All effects →
Bloom, glitch, and frosted-glass passes — three panels back-to-back.
Time formats

Say time however feels natural.

InputMeaning
55 seconds
"5s"5 seconds
"500ms"500 milliseconds
"2m"2 minutes
"120f"120 frames
"01:30"1 min 30 sec
"01:02:30:15"hh:mm:ss:ff

Explore the full API.

Layer methods, keyframe semantics, parallel branches, group composition, transition + effect registries — all documented with types you can trust.

API referenceTry it live
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 →How to Automate Loom-style Product Demos with TypeScriptAutomated Podcast Audiogram Generator: Turning Audio into Viral Video with TypeScriptHow to Turn Markdown Changelogs into Automated Product Update VideosAutomating Personalized Onboarding Videos with VideoFlow and TypeScriptAutomating YouTube Shorts: Build a Vertical Video Factory in 30 Lines of TypeScriptCinematic 3D Video with TypeScript: A Guide to Perspective and RotationCinematic GLSL Effect Stacking: Building High-End Visuals with CodeDiffable Video: Versioning Your Media Pipeline with VideoJSON
© 2026 VideoFlow. Apache-2.0 core.