On this page
DocsGuides
Storyboards
Lay out frames at a fixed interval in a grid on one image, for scrubbing previews and review sheets.
POST /v1/storyboard takes a frame at a fixed interval and lays the frames out in a grid on one
image: a contact sheet, or a sprite for a player's scrubbing preview.
The request#
curl "$VIDEXO_API_URL/v1/storyboard" \
-H "Authorization: Bearer $VIDEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "https://example.com/talk.mp4",
"filename": "storyboard.jpg",
"interval": 10,
"columns": 5,
"rows": 4,
"tile_width": 320
}'Copy failed. The text is selected; copy it with your keyboard.
const response = await fetch(`${process.env.VIDEXO_API_URL}/v1/storyboard`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDEXO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"input": "https://example.com/talk.mp4",
"filename": "storyboard.jpg",
"interval": 10,
"columns": 5,
"rows": 4,
"tile_width": 320
}),
});
const job = await response.json();Copy failed. The text is selected; copy it with your keyboard.
ffmpeg \
-skip_frame nokey -t 200 -i https://example.com/talk.mp4 \
-map 0:v:0 \
-vf fps=1/10,scale=320:320:force_original_aspect_ratio=decrease:force_divisible_by=2,tile=5x4 \
-frames:v 1 -q:v 5 \
storyboard.jpgCopy failed. The text is selected; copy it with your keyboard.
storyboard.jpg: a key frame about every 10 seconds, up to 20 of them, in a grid 5 across and 4 down; exact_times takes the exact times.
The sheet covers columns times rows times interval seconds from its start, here 200 seconds.
Each tile fits in a square of tile_width pixels. trim.start starts the sheet later in the
video.
Exact times#
By default only key frames are decoded, so a tile shows the key frame at or before its time and
the job stays fast. exact_times: true decodes every frame for exact tile times, which costs the
seconds of the whole span.
curl "$VIDEXO_API_URL/v1/storyboard" \
-H "Authorization: Bearer $VIDEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "https://example.com/talk.mp4",
"interval": 5,
"columns": 4,
"rows": 3,
"exact_times": true,
"trim": {
"start": 600
}
}'Copy failed. The text is selected; copy it with your keyboard.
const response = await fetch(`${process.env.VIDEXO_API_URL}/v1/storyboard`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDEXO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"input": "https://example.com/talk.mp4",
"interval": 5,
"columns": 4,
"rows": 3,
"exact_times": true,
"trim": {
"start": 600
}
}),
});
const job = await response.json();Copy failed. The text is selected; copy it with your keyboard.
ffmpeg \
-ss 600 -t 60 -i https://example.com/talk.mp4 \
-map 0:v:0 \
-vf fps=1/5,scale=320:320:force_original_aspect_ratio=decrease:force_divisible_by=2,tile=4x3 \
-frames:v 1 -q:v 5 \
storyboard.jpgCopy failed. The text is selected; copy it with your keyboard.