Quick start
Five minimal scenes, each one a complete VideoFlow composition. Press play on any preview to see it run, switch to VideoJSON to inspect the compiled output, or open it in the playground to fork it. By the end you'll have seen a layer, an animation, a parallel timeline, a transition, and a multi-element scene — enough to start building.
const $ = new VideoFlow({...}), push layers via $.addText / $.addImage / $.addShape / …, and end with return $ so the sandbox can compile it. Positions are [x, y] as fractions of the project (0..1); sizes default to em, where 1em is 1% of the project width.1. A single layer
The smallest useful composition: one text layer that fades in. You never write keyframes by hand — .fadeIn() pushes them for you, and the flow pointer auto-advances by the duration.
const $ = new VideoFlow({
width: 1280, height: 720, fps: 30,
backgroundColor: '#0f0f23',
});
$.addText({
text: 'Hello, VideoFlow',
fontSize: 4,
fontWeight: 700,
color: '#ffffff',
textAlign: 'center',
}).fadeIn('600ms');
$.wait('1.2s');
return $;2. Animate any property
Every layer property is animatable. .animate(from, to, opts) pushes a pair of keyframes and advances the flow pointer by duration. Easings are strings — linear, easeIn, easeOut, easeInOut, or step. See the easing guide for details.
const $ = new VideoFlow({
width: 1280, height: 720, fps: 30,
backgroundColor: '#0a0a1a',
});
const title = $.addText({
text: 'Spring in',
fontSize: 5,
fontWeight: 800,
color: '#ffffff',
textAlign: 'center',
});
title.animate(
{ scale: 0.6, opacity: 0, position: [0.5, 0.55] },
{ scale: 1, opacity: 1, position: [0.5, 0.50] },
{ duration: '700ms', easing: 'easeOut' },
);
$.wait('800ms');
title.fadeOut('400ms');
return $;3. Run things in parallel
$.parallel([...]) takes an array of functions. Each one runs on its own branch from the current flow position; after the block, the pointer advances to the end of the longest branch.
const $ = new VideoFlow({
width: 1280, height: 720, fps: 30,
backgroundColor: '#11131a',
});
const left = $.addText({
text: 'Left',
fontSize: 4,
color: '#7dd3fc',
textAlign: 'center',
position: [0.30, 0.5],
opacity: 0,
});
const right = $.addText({
text: 'Right',
fontSize: 4,
color: '#fca5a5',
textAlign: 'center',
position: [0.70, 0.5],
opacity: 0,
});
$.parallel([
() => left.animate(
{ opacity: 0, position: [0.20, 0.5] },
{ opacity: 1, position: [0.30, 0.5] },
{ duration: '600ms', easing: 'easeOut' },
),
() => right.animate(
{ opacity: 0, position: [0.80, 0.5] },
{ opacity: 1, position: [0.70, 0.5] },
{ duration: '600ms', easing: 'easeOut' },
),
]);
$.wait('700ms');
return $;4. Transitions between layers
transitionIn and transitionOut live in a layer's settings (the second argument to addText) and reference a registered preset by name. The renderer ships fade, slideUp, slideLeft, zoom, overshootPop, blurResolve, and more — see Transitions.
const $ = new VideoFlow({
width: 1280, height: 720, fps: 30,
backgroundColor: '#0b1020',
});
const first = $.addText(
{ text: 'First', fontSize: 5, color: '#fef3c7', textAlign: 'center' },
{
transitionIn: { transition: 'fade', duration: '300ms' },
transitionOut: { transition: 'slideLeft', duration: '400ms' },
},
);
$.wait('900ms');
first.remove();
const second = $.addText(
{ text: 'Second', fontSize: 5, color: '#bae6fd', textAlign: 'center' },
{
transitionIn: { transition: 'zoom', duration: '400ms' },
transitionOut: { transition: 'fade', duration: '300ms' },
},
);
$.wait('900ms');
second.remove();
return $;5. A real scene
Putting it together: a coloured backdrop shape that scales in, a title that rides on top of it, then a punch-line that lands after the title settles. Both title and backdrop start on the same frame via $.parallel.
const $ = new VideoFlow({
width: 1280, height: 720, fps: 30,
backgroundColor: '#0f172a',
});
const bar = $.addShape(
{
fill: '#7c3aed',
width: 120, height: 18,
position: [0.5, 0.42],
rotation: -6,
opacity: 0,
scale: 0,
},
{ shapeType: 'rectangle' },
);
const title = $.addText({
text: 'Code',
fontSize: 6,
fontWeight: 800,
color: '#ffffff',
textAlign: 'center',
position: [0.5, 0.42],
opacity: 0,
});
$.parallel([
() => bar.animate(
{ scale: 0, opacity: 0 },
{ scale: 1, opacity: 0.9 },
{ duration: '500ms', easing: 'easeOut' },
),
() => title.animate(
{ opacity: 0, position: [0.5, 0.48] },
{ opacity: 1, position: [0.5, 0.42] },
{ duration: '600ms', easing: 'easeOut' },
),
]);
$.wait('300ms');
$.addText({
text: 'pixels.',
fontSize: 9,
fontWeight: 900,
color: '#facc15',
textAlign: 'center',
position: [0.5, 0.65],
opacity: 0,
scale: 0.7,
}).animate(
{ opacity: 0, scale: 0.7 },
{ opacity: 1, scale: 1 },
{ duration: '450ms', easing: 'easeOut' },
);
$.wait('1.2s');
return $;Where to next
- Core concepts — VideoJSON, layers, time, keyframes.
- Builder API — the full fluent surface.
- Animation & keyframes — every way to push keyframes.
- Browser renderer — encode MP4 from a browser tab.