Core concepts
VideoFlow has exactly four moving parts. Once you have these four, everything else is just API surface.
1. VideoJSON
The source of truth. Every video is a plain JSON object listing its layers, their properties, and their keyframes. The builder compiles to it; every renderer reads from it. You can save, version, diff, and lint it like any other config.
{
"name": "Hello",
"width": 1280, "height": 720, "fps": 30, "duration": 2,
"layers": [
{
"type": "text",
"text": "Hello",
"fontSize": 2.4,
"keyframes": {
"opacity": [
{ "time": 0, "value": 0 },
{ "time": 0.8, "value": 1 }
]
}
}
]
}2. Layers
Six built-in content types plus a group container. Every property on every layer is animatable.
| Type | Use for |
|---|---|
text | Titles, lower thirds, captions burned at author time. |
image | PNG/JPG/WebP/SVG. Auto-detected from URL. |
video | B-roll, clips. Trim start/end in source-media seconds. |
audio | Music bed, VO. Same trim model as video. |
captions | Subtitle tracks with word-level timing (WhisperX JSON, SRT, VTT). |
shape | Rectangles, ellipses, polygons, stars — vector primitives with fills, strokes, and corner radii. |
group | A composited sub-tree that transforms, transitions, and animates as one. Created with $.group(). |
See the layer guides under Layers in the sidebar for the full property tables.
3. Time
Every duration in the API passes through the same Time parser. Give it whatever form is clearest in context:
| Input | Meaning |
|---|---|
5 | 5 seconds (any plain number) |
'500ms' | 500 milliseconds |
'2s' | 2 seconds |
'3m' | 3 minutes |
'1h' | 1 hour |
'120f' | 120 frames (uses the project fps) |
'00:30' | mm:ss |
'01:20:05' | hh:mm:ss |
'01:20:05:12' | hh:mm:ss:ff (frames) |
4. Keyframes
Any property on any layer can be animated. A keyframe is simply { time, value, easing?: string }. The builder never asks you to write keyframes by hand — .animate(from, to, opts), .fadeIn(), and .fadeOut() push them for you.
video and audio layers are expressed in source-media seconds, not timeline seconds. Trimming or moving a clip doesn't change the keyframe times — that's how the React video editor can scrub without re-baking keyframes.