compose renders a video from a JSON timeline. Start with one clip, then layer up: more clips, transitions, overlays, and effects. This page builds from the smallest render to the full model. Each step adds one idea.
Your simplest render
The smallest timeline is one track with one clip. This renders the first three seconds of a video to MP4. The whole API call:
import { createClient, outputUrl } from "@rendobar/sdk";
const client = createClient({ apiKey: "rb_YOUR_KEY" });
const job = await client.jobs.create({
type: "compose",
params: {
schemaVersion: 1,
output: {
format: "mp4",
resolution: { width: 1080, height: 1920 },
fps: 30,
},
timeline: {
tracks: [
{
clips: [
{
asset: {
type: "video",
src: "https://cdn.rendobar.com/assets/examples/sea.mp4",
},
start: 0,
length: 3,
},
],
},
],
},
},
});
const result = await client.jobs.wait(job.id);
console.log(outputUrl(result));
Assets: video, image, text, audio, composition · Output: mp4 / webm / gif / mp3 (audio only) / jpg / png (still frame)
Without trim, a clip plays its source from the start for length seconds. To use a specific segment instead, add trim: { from, to } (in source seconds) to the asset. length is always the timeline duration. trim only chooses which part of the source fills it.
That is the shape of every render. Everything below is one more clip, one more track, or one more field.
Join two clips
Put a second clip on the same track and a transition between them. The clips overlap by the transition’s duration, so the second clip starts a little before the first ends.
"clips": [
{ "asset": { "type": "video", "src": "https://cdn.rendobar.com/assets/examples/river.mp4" }, "start": 0, "length": 3 },
{ "type": "transition", "transition": "crossfade", "duration": 1 },
{ "asset": { "type": "video", "src": "https://cdn.rendobar.com/assets/examples/forest.mp4" }, "start": 2, "length": 3 }
]
slide also accepts direction: "left" | "right" | "up" | "down".
| Transition | Effect |
|---|
crossfade | A dissolves directly into B |
fade | A dips through black, then B fades up |
slide | B slides in over A from an edge (directional) |
zoom | B grows in from the center |
How the timeline works
The model is two ideas:
- Tracks stack. The first track is the background. Each later track composites on top of the ones below it: overlays, titles, picture-in-picture.
- Clips sit in time. Each clip has a
start and a length in seconds. Two clips on the same track are joined by a transition. A gap between them plays nothing.
So a multi-track timeline is layers (tracks) of sequences (clips). That is the whole structure.
Add a layer
A second track renders over the first. This lays an animated title over the video.
"tracks": [
{ "clips": [
{ "asset": { "type": "video", "src": "https://cdn.rendobar.com/assets/examples/sea.mp4" }, "start": 0, "length": 5 }
] },
{ "clips": [
{ "asset": { "type": "text", "text": "Coastal Escape", "style": { "size": 84 } },
"start": 0, "length": 5 }
] }
]
Effects on a clip
Effects are fields on a clip. Stack as many as you like on one clip. Each example below shows the source on the left and the rendered result on the right. Exact fields and ranges are in the Reference.
{
"asset": { "type": "video", "src": "https://cdn.rendobar.com/assets/examples/sea.mp4" },
"start": 0,
"length": 5,
"color": { "saturation": 1.2, "temperature": 6800 },
"speed": 0.8,
"transform": { "scale": 1.1, "animateTo": { "scale": 1.3 } }
}
Color and filters
color grades a clip with contrast, saturation, temperature, brightness, gamma, and hue. filter applies a one-shot look like greyscale or boost.
Motion and speed
transform positions, scales, and rotates a clip. Add animateTo for a Ken Burns move, or scale a clip down and place it on an overlay track for picture-in-picture. speed is a playback multiplier: below 1 for slow motion, above 1 for a timelapse.
Compositing
chromaKey keys out a solid background color so you can drop a presenter onto any scene. blendMode controls how an overlay blends with the track below. opacity (a number or keyframes) and blur handle fades and soft backdrops.
Text and titles
A text asset renders a styled title. Set the font, size, weight, color, position, and an animate entrance (fade, slideUp, slideDown, slideLeft, slideRight). Put one text clip on its own track for a title card, another low and left for a lower-third name tag.
"asset": {
"type": "text",
"text": "Coastal Escape",
"style": {
"font": "Inter",
"size": 84,
"weight": 800,
"color": "#FFFFFF",
"position": { "x": "50%", "y": "38%" },
"animate": { "type": "slideUp", "duration": 0.7 }
}
}
Set the canvas
output controls the resolution, frame rate, and format. A 9:16 canvas with a crop on the clip turns landscape footage into a vertical Reel that fills the frame, no black bars.
"output": { "format": "mp4", "resolution": { "width": 1080, "height": 1920 }, "fps": 30 }
Scene-first authoring
Tracks give you precise multi-track control. For a sequential edit, you can instead describe a list of scenes. Each scene is a self-contained segment with its own clips and an optional transition into the next. overlays is a flat list of clips that sit over the whole composition, like a persistent logo or watermark.
{
"scenes": [
{ "duration": 4, "transition": { "transition": "crossfade", "duration": 0.6 },
"clips": [{ "asset": { "type": "video", "src": "https://cdn.rendobar.com/assets/examples/river.mp4" } }] },
{ "duration": 4, "clips": [{ "asset": { "type": "video", "src": "https://cdn.rendobar.com/assets/examples/forest.mp4" } }] }
],
"overlays": [
{ "asset": { "type": "image", "src": "https://cdn.rendobar.com/assets/brand/logo-mark.png" }, "start": 0, "length": 8,
"transform": { "scale": 0.2, "position": { "x": "88%", "y": "12%" } } }
]
}
A scene’s clips can omit start and length to span the whole scene. Every clip field works the same as in tracks mode. scenes and tracks are mutually exclusive: a timeline uses one or the other.
Reference
Output
The output object controls the render target.
| Field | Values |
|---|
format | mp4 (default), webm, gif (no audio), mp3 (audio only), jpg, png (still frame) |
resolution | { width, height } (integer pixels) |
fps | number |
videoCodec | h264, vp9 (optional; per-format default otherwise) |
audioCodec | aac, opus, mp3 (optional) |
frameTime | second of the timeline to capture for jpg / png (default 0) |
Assets
A clip’s asset is one of:
type | Fields |
|---|
video | src, trim { from, to }, volume (default 1) |
image | src |
audio | src, trim, volume, fadeIn, fadeOut (seconds) |
text | text, style |
composition | timeline, a nested { tracks } rendered and composited as a single clip |
Clip fields
Every clip has asset, start, length, plus any of:
| Field | What it does |
|---|
opacity | 0..1, or keyframes [{ time, value, easing: step | linear | smooth }] |
transform | position {x,y}, scale, rotate, anchor (center | topLeft), fit (contain | fill), animateTo (Ken Burns end state) |
crop | top / right / bottom / left, each a percent string like "10%" |
speed | playback rate (0.5 = slow motion, 2 = fast, and pitch shifts with speed) |
color | brightness (-1..1), contrast (0..4), saturation (0..3), gamma (0.1..10), hue (-180..180), temperature (1000..40000 K) |
filter | greyscale, negative, boost, muted, lighten, darken, contrast (mutually exclusive with color) |
blur / sharpen | gaussian blur strength / unsharp amount |
chromaKey | color (hex), similarity (0..1) |
blendMode | normal, multiply, screen, overlay, darken, lighten, add, difference |
pan | stereo balance, -1 (left) to 1 (right) |
flip | { horizontal, vertical } |
Transitions
Place between two clips on a track: { "type": "transition", "transition": <kind>, "duration": <seconds>, "direction"?: <dir> }.
| Transition | Effect |
|---|
crossfade | A dissolves directly into B |
fade | A dips through black, then B fades up |
slide | B slides in from an edge (direction: left, right, up, down) |
zoom | B grows in from the center |
none | Hard cut, no blend |
Text style
Fields on a text asset’s style:
| Field | Notes |
|---|
font | Font family name |
size | Point size |
weight | 100..1000 (default 400) |
color | Hex fill |
align | left, center, right |
position | { x, y } as percent strings |
stroke | { color, width } outline |
background | Hex fill behind the text |
shadow | { color, opacity, offsetX, offsetY } |
animate | { type, duration } (type: fade, slideUp, slideDown, slideLeft, slideRight) |