DocsReference
Operations
The JSON request in full: inputs, output types, every option with its range and the types that take it, defaults, and the per-operation endpoints.
A JSON request describes the files you want; the API picks the ffmpeg arguments. It is one of two
bodies POST /v1/jobs takes:
- the operations body: named
inputsand a list ofoutputs, each with atypeand options, or a preset; - the command body:
input_files,output_filesand an ffmpegcommand(Command rules).
Both may carry webhook_url and metadata. A body with the fields of both, or of neither, is
400 invalid_request. Unknown fields return invalid_request, with the location of each invalid
field, so a typo never goes unnoticed.
The API validates the body, fills in presets and defaults (the job's spec) and compiles it to one
ffmpeg command within the command rules. The response includes the normalized
request, the compiled command with its file maps, and ffmpeg_command, one line that runs the
same thing with a local ffmpeg. POST /v1/jobs/compile returns the same without creating a job or
using credits.
curl "$VIDEXO_API_URL/v1/jobs" \
-H "Authorization: Bearer $VIDEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": {
"talk": "https://videxo.io/samples/talk.mp4"
},
"outputs": [
{
"name": "web",
"preset": "web-720p"
},
{
"name": "poster",
"preset": "poster"
}
],
"metadata": {
"order": "1234"
}
}'Copy failed. The text is selected; copy it with your keyboard.
const response = await fetch(`${process.env.VIDEXO_API_URL}/v1/jobs`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDEXO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"inputs": {
"talk": "https://videxo.io/samples/talk.mp4"
},
"outputs": [
{
"name": "web",
"preset": "web-720p"
},
{
"name": "poster",
"preset": "poster"
}
],
"metadata": {
"order": "1234"
}
}),
});
const job = await response.json();Copy failed. The text is selected; copy it with your keyboard.
ffmpeg \
-i https://videxo.io/samples/talk.mp4 \
-map 0:v:0 \
-vf "scale='min(iw,1280)':'min(ih,720)':force_original_aspect_ratio=decrease:force_divisible_by=2" \
-c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p \
-map "0:a:0?" \
-c:a aac -b:a 128k -movflags +faststart \
web.mp4 \
-map 0:v:0 \
-vf "thumbnail=300,scale='min(iw,1280)':'min(ih,720)':force_original_aspect_ratio=decrease:force_divisible_by=2" \
-frames:v 1 -q:v 2 \
poster.jpgCopy failed. The text is selected; copy it with your keyboard.
Times are seconds as a number (90, 12.5) or a string HH:MM:SS.fraction ("00:01:30"). Sizes
are pixels. Colours are "black", "white" or "#RRGGBB".
Inputs#
inputs maps 1 to 16 names to sources. A name is a lowercase letter, then up to 39 lowercase
letters, digits or underscores. A source is an http or https URL, videxo://uploads/<id> for a
completed upload, or the object form { "url": "..." } or { "upload_id": "..." }.
Every input must be used by an output. An upload that is missing, not completed or expired is
404 not_found (reason upload).
Outputs#
outputs lists 1 to 16 outputs. Each one has:
name: required when the job has several outputs,mainwhen it has one. Its alias isout_<name>and the job'soutputs[].nameis this name.type(video,audio,image,storyboard,gif,metadataorscenes), or apreset, or both when they agree.metadatareads an input with ffprobe and takes no options.input: the input it reads, required when the job has several, orconcatto play several in a row.filename: the stored file name,<name>.<format>by default; its extension must matchformat.
An image output with times writes one file per time: <name>_1, <name>_2, and so on. The 16
file limit counts these files.
Formats and codecs#
| Type | Format | Video codecs | Audio codecs |
|---|---|---|---|
| video | mp4 (default) | h264, h265, av1 | aac, mp3, opus, alac |
mov | h264, h265 | aac, alac, pcm | |
webm | vp9, av1 | opus, vorbis | |
mkv | h264, h265, vp9, av1 | aac, mp3, opus, vorbis, flac | |
ts | h264, h265 | aac, mp3 | |
| audio | mp3 (default) | none | mp3 |
m4a | none | aac, alac | |
aac | none | aac | |
wav | none | pcm | |
flac | none | flac | |
ogg | none | vorbis | |
opus | none | opus | |
| image | jpg (default) | none | none |
png | none | none | |
| storyboard | jpg (default) | none | none |
png | none | none | |
| gif | gif (default) | none | none |
| metadata | json (default) | none | none |
| scenes | json (default) | none | none |
Every field#
A field the output's type does not take is 400 invalid_request with its pointer, not ignored.
| Field | Type | Output types |
|---|---|---|
name | string. Required when the job has several outputs; main when it has one. The alias is out_<name>. | all |
type | one of video, audio, image, storyboard, gif, metadata, scenes. Required unless preset is set. | all |
preset | string. A preset name (GET /v1/presets); its options are the defaults and the output's own fields win. | all |
input | string. The input it reads; required when the job has several, unless concat is set. | video, audio, image, storyboard, gif, metadata, scenes |
concat | list of string, or object, 1 to 16 (fields). Parts played one after another: input names, { "input", "start", "end", "transition" }, still images, { "image", "duration", "motion", "transition" }, or title cards, { "color", "duration", "text", "transition" }. Not with input. | video, audio |
filename | string, up to 105 characters. The stored file name, <name>.<format> by default; one extension, matching format. | all |
format | one of mp4, mov, webm, mkv, ts, mp3, m4a, aac, wav, flac, ogg, opus, jpg, png, gif, json. The container or image format; from filename, or the type's default. | all |
strip_metadata | boolean. Drop the input's global and stream metadata (GPS, device tags). | video, audio, image, storyboard, gif |
trim | object (fields). The part of the input to use: start, and end or duration. | video, audio, storyboard, gif, scenes |
crop | object (fields). A rectangle of the input frame, in input pixels. | video, image, storyboard, gif |
rotate | 90, or 180, or 270. Degrees clockwise. | video, image, storyboard, gif |
flip | one of horizontal, vertical. Mirror the picture. | video, image, storyboard, gif |
resize | object (fields). A new size: width, height, aspect, and how the picture fits (fit). | video, image, gif |
speed | number, 0.25 to 4. How fast it plays, 0.25 to 4; the sound keeps its pitch. | video, audio, gif |
fps | number, 1 to 120. A constant frame rate. | video, gif |
color | object (fields). Brightness, contrast, saturation, gamma and hue. | video, image, storyboard, gif |
sharpen | object (fields). An unsharp mask. | video, image, gif |
blur | object (fields). A box blur of the whole frame, or of up to 4 regions. | video, image, gif |
overlays | list of object, 1 to 4 (fields). Images or videos drawn over the picture, in order. | video, image, gif |
text | list of object, 1 to 8 (fields). Up to 8 text layers, drawn after overlays in order. | video, image, gif |
subtitles | object (fields) | video |
fade | object (fields). Fade in at the start and out at the end; out needs trim.duration or trim.end. | video, audio, gif |
video | object (fields). The video encoder: codec, quality or CRF, preset, maximum bitrate, pixel format. | video |
audio | false, or object (fields). false for no sound, or the audio encoder and filters. | video, audio |
visualize | object (fields). A waveform or spectrum video drawn from the input's sound. | video |
at | number, 0 to 86,400, or HH:MM:SS string, or "auto". The frame time, or "auto" for the most representative of the first 300 frames. | image |
times | list of number, 0 to 86,400, or HH:MM:SS string, 1 to 16. One image per time, <name>_1, <name>_2, ...; not with at. | image |
quality | one of low, medium, high. JPEG quality; PNG ignores it. | image, storyboard |
interval | number, 0.5 to 3,600. Seconds between frames. | storyboard |
columns | integer, 1 to 16. Frames across. | storyboard |
rows | integer, 1 to 16. Frames down. | storyboard |
tile_width | integer, 16 to 640. Each frame fits in a square of this many pixels. | storyboard |
exact_times | boolean. Decode every frame for exact tile times, instead of key frames only. | storyboard |
colors | integer, 2 to 256. Colours in the palette. | gif |
threshold | number, 1 to 100. The score, 1 to 100, at which a frame starts a new scene (default 10, scdet's). | scenes |
What a type fills in#
The defaults, as the API fills them in for the smallest output of each type. A preset's options and your own fields replace them.
{ "type": "video" } becomes:
{
"type": "video",
"input": "talk",
"video": {
"codec": "h264",
"crf": 23,
"encoder_preset": "veryfast",
"pixel_format": "yuv420p",
"faststart": true
},
"audio": {
"codec": "aac",
"bitrate": "128k"
},
"name": "main",
"filename": "main.mp4",
"format": "mp4"
}Copy failed. The text is selected; copy it with your keyboard.
{ "type": "audio" } becomes:
{
"type": "audio",
"input": "talk",
"audio": {
"codec": "mp3",
"bitrate": "128k"
},
"name": "main",
"filename": "main.mp3",
"format": "mp3"
}Copy failed. The text is selected; copy it with your keyboard.
{ "type": "image" } becomes:
{
"type": "image",
"input": "talk",
"at": "auto",
"quality": "high",
"name": "main",
"filename": "main.jpg",
"format": "jpg"
}Copy failed. The text is selected; copy it with your keyboard.
{ "type": "storyboard" } becomes:
{
"type": "storyboard",
"input": "talk",
"interval": 10,
"columns": 5,
"rows": 4,
"tile_width": 320,
"exact_times": false,
"quality": "medium",
"name": "main",
"filename": "main.jpg",
"format": "jpg"
}Copy failed. The text is selected; copy it with your keyboard.
{ "type": "gif" } becomes:
{
"type": "gif",
"input": "talk",
"fps": 12,
"colors": 256,
"resize": {
"width": 480,
"enlarge": false
},
"trim": {
"start": 0,
"duration": 60
},
"name": "main",
"filename": "main.gif",
"format": "gif"
}Copy failed. The text is selected; copy it with your keyboard.
{ "type": "metadata" } becomes:
{
"type": "metadata",
"input": "talk",
"name": "main",
"filename": "main.json",
"format": "json"
}Copy failed. The text is selected; copy it with your keyboard.
{ "type": "scenes" } becomes:
{
"type": "scenes",
"input": "talk",
"threshold": 10,
"name": "main",
"filename": "main.json",
"format": "json"
}Copy failed. The text is selected; copy it with your keyboard.
Options#
The order is fixed, so a request means one thing: trim (and the time of an image), crop,
rotate and flip, resize, speed, fps, color and sharpen, blur, overlays in list
order, text in list order, then fade. crop uses input pixels; blur regions, overlays and
text use the frame after resize.
resize:containfits the whole picture in the box,coverfills it and crops the overflow atanchor,padfits it and fills the rest withpad_color. Onlywidthor onlyheightkeeps the shape.enlarge: falsekeeps an input smaller than the size at its own size.aspectalone crops or pads the input to that shape at its own size. Sizes from the input are kept inside 7,680 on a side and 33,554,432 pixels.speedchanges the picture and the sound, which keeps its pitch; sound fromaudio.mixstays at its own speed, and a copied stream cannot change speed.fade.outneeds the output's length: settrim.durationortrim.end.overlayskeep their last frame when they end, and the output ends with its main picture, also under a longer video overlay; setendto hide one. An overlay's sound is used only whenaudio.inputnames it.- Sound from another input (
audio.input) is padded with silence when it is shorter and cut when it is longer, so the output ends with its picture;audio.mixandaudio.codec: "copy"are not available with it. audio.mixputs more sound under this one (background music);audio.normalize: trueis -16 LUFS, -1.5 dBTP, LRA 11.video.codec: "copy"andaudio.codec: "copy"pass a stream through without decoding it, so options that need decoded frames or samples are rejected with it. A copied video cuts at key frames.visualizedraws a waveform or spectrum video from the input's sound and keeps the sound.textdraws up to 8 text layers, each onedrawtextper line with a font from Fonts:position,marginand the offsets place the block of lines, which align to the side ofposition;box,outlineandshadowstyle it;start,endandfadetime it on the output's timeline (animagetakes none of them). The text is drawn exactly as sent: quotes, colons, backslashes and%{...}are characters, never ffmpeg syntax. A character the font cannot draw, or a control character other than\n, is refused with the text's pointer.subtitlesburns the captions of an SRT or WebVTT input (UTF-8, at most 1 MB) into avideooutput after its text, each cue at its time, in a font from Fonts, centred at thebottomortop.size,marginand the outline width are pixels on a 1,080-line frame and scale with the output. Cue times follow the output's input, so a trimmed or sped up output shows the cues of the moments it shows; a concat follows its joined parts. The file's own tags and styles are removed before ffmpeg reads it, so every cue is plain text. The input is only for the subtitles: no other field may read it, and each output needs its own. A file that is not UTF-8 SRT or WebVTT fails the job withprocessing_failed(subtitles_invalid), a larger one withlimit_exceeded(subtitles_size), before ffmpeg runs.
{
"inputs": { "talk": "https://example.com/talk.mp4", "captions": "https://example.com/talk.srt" },
"outputs": [{ "type": "video", "input": "talk", "subtitles": { "input": "captions", "font": "inter-bold", "size": 44 } }]
}Copy failed. The text is selected; copy it with your keyboard.
concat#
Taken by: video, audio.
| Field | Type | Required |
|---|---|---|
input | string. A lowercase letter, then up to 39 lowercase letters, digits or underscores. | yes |
start | number, 0 to 86,400, or HH:MM:SS string. Seconds, or HH:MM:SS(.fraction). | no |
end | number, 0 to 86,400, or HH:MM:SS string. Seconds, or HH:MM:SS(.fraction). | no |
text | list of object, 1 to 4. Up to 4 text layers, drawn after overlays in order. | no |
transition | object | no |
concat.text#
| Field | Type | Required |
|---|---|---|
text | string. The text, 1 to 500 characters and at most 6 lines (\n). | yes |
font | one of inter, inter-bold, roboto, roboto-bold, open-sans, open-sans-bold, montserrat, montserrat-bold, poppins, poppins-bold, oswald, oswald-bold, bebas-neue, playfair-display, playfair-display-bold, merriweather, merriweather-bold, noto-sans, noto-sans-bold, noto-serif, noto-serif-bold, jetbrains-mono, jetbrains-mono-bold. A font id from GET /v1/fonts (default inter). | no |
size | integer, 8 to 1,000. The font size in pixels (default 48). | no |
color | one of black, white, or string. The text colour (default #FFFFFF). | no |
opacity | number, 0 to 1. The text opacity, 0 to 1 (default 1). | no |
line_height | number, 1 to 3. The distance between lines, times size (default 1.25). | no |
position | one of top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right. Where the text sits (default center); lines align to its side. | no |
margin | integer, 0 to 1,000. Pixels from the edges position touches (default 48). | no |
offset_x | integer, -7,680 to 7,680. Pixels to move right (negative: left). | no |
offset_y | integer, -7,680 to 7,680. Pixels to move down (negative: up). | no |
box | object. A box behind each line: color (default black), opacity (0.5), padding in pixels (16). | no |
outline | object. An outline around the letters: width in pixels (default 2), color (default black). | no |
shadow | object. A drop shadow: x and y in pixels (default 2), color (default black), opacity (0.5). | no |
start | number, 0 to 86,400, or HH:MM:SS string. When the text appears, on the output's timeline (a part's own on a part). | no |
end | number, 0 to 86,400, or HH:MM:SS string. When the text goes; the end of the output by default. | no |
fade | object. Seconds of fade in and fade out; out needs end. | no |
concat.transition#
| Field | Type | Required |
|---|---|---|
type | one of fade, fade-black, fade-white, dissolve, wipe-left, wipe-right, wipe-up, wipe-down, slide-left, slide-right, slide-up, slide-down, circle-open, circle-close, radial, zoom-in, pixelize | yes |
duration | number, 0.1 to 5. Seconds the two parts overlap, 0.1 to 5 (default 1). | no |
trim#
Taken by: video, audio, storyboard, gif, scenes.
| Field | Type | Required |
|---|---|---|
start | number, 0 to 86,400, or HH:MM:SS string. Seconds, or HH:MM:SS(.fraction). | no |
end | number, 0 to 86,400, or HH:MM:SS string. Seconds, or HH:MM:SS(.fraction). | no |
duration | number, 0 to 86,400, or HH:MM:SS string. Seconds, or HH:MM:SS(.fraction). | no |
crop#
Taken by: video, image, storyboard, gif.
| Field | Type | Required |
|---|---|---|
x | integer, 0 to 7,680 | yes |
y | integer, 0 to 7,680 | yes |
width | integer, 16 to 7,680 | yes |
height | integer, 16 to 7,680 | yes |
resize#
Taken by: video, image, gif.
| Field | Type | Required |
|---|---|---|
width | integer, 16 to 7,680, even | no |
height | integer, 16 to 7,680, even | no |
aspect | one of 16:9, 9:16, 1:1, 4:5, 4:3, 3:4 | no |
fit | one of contain, cover, pad | no |
anchor | one of center, top, bottom, left, right | no |
pad_color | one of black, white, or string. black, white or #RRGGBB. | no |
enlarge | boolean. Scale a smaller input up to the size (default true); false keeps it at its size, never larger. | no |
color#
Taken by: video, image, storyboard, gif.
| Field | Type | Required |
|---|---|---|
brightness | number, -1 to 1 | no |
contrast | number, 0 to 3 | no |
saturation | number, 0 to 3 | no |
gamma | number, 0.1 to 10 | no |
hue | number, -180 to 180 | no |
sharpen#
Taken by: video, image, gif.
| Field | Type | Required |
|---|---|---|
amount | number, 0 to 3 | no |
size | 3, or 5, or 7 | no |
blur#
Taken by: video, image, gif.
| Field | Type | Required |
|---|---|---|
strength | integer, 1 to 50 | yes |
regions | list of object, 1 to 4 | no |
blur.regions#
| Field | Type | Required |
|---|---|---|
x | integer, 0 to 7,680 | yes |
y | integer, 0 to 7,680 | yes |
width | integer, 16 to 7,680 | yes |
height | integer, 16 to 7,680 | yes |
overlays#
Taken by: video, image, gif.
| Field | Type | Required |
|---|---|---|
input | string. A lowercase letter, then up to 39 lowercase letters, digits or underscores. | yes |
position | one of top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right | no |
margin | integer, 0 to 1,000 | no |
width | integer, 8 to 7,680 | no |
opacity | number, 0 to 1 | no |
start | number, 0 to 86,400, or HH:MM:SS string. Seconds, or HH:MM:SS(.fraction). | no |
end | number, 0 to 86,400, or HH:MM:SS string. Seconds, or HH:MM:SS(.fraction). | no |
text#
Taken by: video, image, gif.
| Field | Type | Required |
|---|---|---|
text | string. The text, 1 to 500 characters and at most 6 lines (\n). | yes |
font | one of inter, inter-bold, roboto, roboto-bold, open-sans, open-sans-bold, montserrat, montserrat-bold, poppins, poppins-bold, oswald, oswald-bold, bebas-neue, playfair-display, playfair-display-bold, merriweather, merriweather-bold, noto-sans, noto-sans-bold, noto-serif, noto-serif-bold, jetbrains-mono, jetbrains-mono-bold. A font id from GET /v1/fonts (default inter). | no |
size | integer, 8 to 1,000. The font size in pixels (default 48). | no |
color | one of black, white, or string. The text colour (default #FFFFFF). | no |
opacity | number, 0 to 1. The text opacity, 0 to 1 (default 1). | no |
line_height | number, 1 to 3. The distance between lines, times size (default 1.25). | no |
position | one of top-left, top, top-right, left, center, right, bottom-left, bottom, bottom-right. Where the text sits (default center); lines align to its side. | no |
margin | integer, 0 to 1,000. Pixels from the edges position touches (default 48). | no |
offset_x | integer, -7,680 to 7,680. Pixels to move right (negative: left). | no |
offset_y | integer, -7,680 to 7,680. Pixels to move down (negative: up). | no |
box | object. A box behind each line: color (default black), opacity (0.5), padding in pixels (16). | no |
outline | object. An outline around the letters: width in pixels (default 2), color (default black). | no |
shadow | object. A drop shadow: x and y in pixels (default 2), color (default black), opacity (0.5). | no |
start | number, 0 to 86,400, or HH:MM:SS string. When the text appears, on the output's timeline (a part's own on a part). | no |
end | number, 0 to 86,400, or HH:MM:SS string. When the text goes; the end of the output by default. | no |
fade | object. Seconds of fade in and fade out; out needs end. | no |
text.box#
| Field | Type | Required |
|---|---|---|
color | one of black, white, or string. black, white or #RRGGBB. | no |
opacity | number, 0 to 1 | no |
padding | integer, 0 to 200 | no |
text.outline#
| Field | Type | Required |
|---|---|---|
width | integer, 1 to 20 | no |
color | one of black, white, or string. black, white or #RRGGBB. | no |
text.shadow#
| Field | Type | Required |
|---|---|---|
x | integer, -50 to 50 | no |
y | integer, -50 to 50 | no |
color | one of black, white, or string. black, white or #RRGGBB. | no |
opacity | number, 0 to 1 | no |
text.fade#
| Field | Type | Required |
|---|---|---|
in | number, 0.1 to 60 | no |
out | number, 0.1 to 60 | no |
subtitles#
Taken by: video.
| Field | Type | Required |
|---|---|---|
input | string. The input holding an SRT or WebVTT file (UTF-8, at most 1 MB); no other field of the job may read it. | yes |
font | one of inter, inter-bold, roboto, roboto-bold, open-sans, open-sans-bold, montserrat, montserrat-bold, poppins, poppins-bold, oswald, oswald-bold, bebas-neue, playfair-display, playfair-display-bold, merriweather, merriweather-bold, noto-sans, noto-sans-bold, noto-serif, noto-serif-bold, jetbrains-mono, jetbrains-mono-bold. A font id from GET /v1/fonts (default inter). | no |
size | integer, 8 to 400. The font size in pixels on a 1,080-line frame (default 48), libass's: the height of a line. | no |
color | one of black, white, or string. The text colour (default #FFFFFF). | no |
outline | object. The outline around the letters: width in pixels on a 1,080-line frame (default 2; 0 for none), color (default black). | no |
position | one of bottom, top. Where the lines sit, centred: bottom (default) or top. | no |
margin | integer, 0 to 1,000. Pixels from the bottom or top edge on a 1,080-line frame (default 48). | no |
subtitles.outline#
| Field | Type | Required |
|---|---|---|
width | integer, 0 to 20 | no |
color | one of black, white, or string. black, white or #RRGGBB. | no |
fade#
Taken by: video, audio, gif.
| Field | Type | Required |
|---|---|---|
in | number, 0.1 to 60 | no |
out | number, 0.1 to 60 | no |
color | one of black, white | no |
video#
Taken by: video.
| Field | Type | Required |
|---|---|---|
codec | one of h264, h265, vp9, av1, copy | no |
quality | one of low, medium, high, lossless | no |
crf | integer, 0 to 63 | no |
encoder_preset | one of ultrafast, superfast, veryfast, faster, fast, medium, slow | no |
max_bitrate | string | no |
pixel_format | one of yuv420p, yuv422p, yuv444p, yuv420p10le | no |
faststart | boolean | no |
audio#
Taken by: video, audio.
| Field | Type | Required |
|---|---|---|
input | string. A lowercase letter, then up to 39 lowercase letters, digits or underscores. | no |
codec | one of aac, mp3, opus, vorbis, flac, alac, pcm, copy | no |
quality | one of low, medium, high | no |
bitrate | string | no |
sample_rate | integer, 8,000 to 192,000 | no |
channels | 1, or 2 | no |
volume | number, 0 to 4 | no |
normalize | true, or object | no |
mix | list of object, 1 to 4 | no |
audio.normalize#
| Field | Type | Required |
|---|---|---|
loudness | number, -70 to -5 | no |
true_peak | number, -9 to 0 | no |
range | number, 1 to 20 | no |
audio.mix#
| Field | Type | Required |
|---|---|---|
input | string. A lowercase letter, then up to 39 lowercase letters, digits or underscores. | yes |
volume | number, 0 to 4 | no |
visualize#
Taken by: video.
| Field | Type | Required |
|---|---|---|
style | one of waveform, spectrum | yes |
width | integer, 16 to 7,680, even | no |
height | integer, 16 to 7,680, even | no |
fps | integer, 1 to 60 | no |
Quality#
quality is constant quality; crf and bitrate are the advanced form. A mapping keeps its
meaning: a change would be a new value, never a new meaning for an old one.
| Video codec | low | medium | high | lossless |
|---|---|---|---|---|
h264 | CRF 28 | CRF 23 | CRF 18 | CRF 0 |
h265 | CRF 32 | CRF 28 | CRF 22 | refused |
vp9 | CRF 40 | CRF 33 | CRF 24 | refused |
av1 | CRF 40 | CRF 32 | CRF 24 | refused |
| Audio codec | low | medium | high |
|---|---|---|---|
aac | 96k | 128k | 192k |
mp3 | 96k | 128k | 192k |
vorbis | 96k | 128k | 192k |
opus | 48k | 96k | 128k |
VP9 and AV1 run in pure constant quality (-b:v 0), or with video.max_bitrate in constrained
quality with the cap as the target bitrate; AV1 is several times slower than H.264, which
counts against your plan's longest job. H.265 in MP4 and MOV is tagged hvc1 so Safari plays it.
How inputs count#
A job reads each input once and counts its bytes once, however many outputs use it. The processed
duration and the output settings set the compute seconds: an output with trim processes only its
range, and an image at 50 minutes takes about as long as an image at 3 seconds. A storyboard
without exact_times uses the nearest key frames, which is faster than exact times; an image with
at: "auto" picks from the first 300 frames after its start.
Concatenation#
An output with concat plays 1 to 16 parts one after another; a part is an input name,
{ "input", "start", "end", "text" }, a still image, { "image", "duration", "motion", "text" } (Slideshows), or
a title card, { "color", "duration", "text" } (Join files). An object part takes transition, which crosses it with the
part before (Join files). A part's up to 4 text layers are drawn on that part alone,
timed on its own clock. The output's subtitles follow the joined timeline, which starts at 0. A video output needs a resize box, and every part is fitted into
it (contain becomes pad) at fps (30 by default). Each input part must contain an audio track unless the
output sets "audio": false or names its sound with audio.input, which replaces the parts' sound and
ends with the picture. An image or a card is silent next to them; an output of images and cards alone has no sound
unless audio.input names one. An audio output joins audio tracks only.
Per-operation endpoints#
For one input and one output, these endpoints take the output's fields and input in a flat body.
They create the same job as POST /v1/jobs (same /v1/jobs/{id}, webhooks and usage), with
operation set to the endpoint. extra_inputs names more inputs for overlays and mixes.
| Endpoint | Makes | Output name |
|---|---|---|
POST /v1/transcode | video | video |
POST /v1/thumbnails | image | thumbnail |
POST /v1/storyboard | storyboard | storyboard |
POST /v1/gif | gif | gif |
POST /v1/audio | audio | audio |
POST /v1/concat | video (or audio with "type": "audio") | video |
POST /v1/slideshow | video | video |
POST /v1/probe | metadata | metadata |
POST /v1/scenes | scenes | scenes |
POST /v1/concat takes inputs, a list of 2 to 16 parts: a source, or
{ "source", "start", "end" }. POST /v1/slideshow takes images, a list of 1 to 16 pictures: a
source, or { "source", "duration", "motion", "text", "transition" }. POST /v1/probe takes input and filename only, and
waits for the job.
Errors#
A field that is wrong returns 400 invalid_request with one errors[] entry per problem, each with
a pointer into your body (#/outputs/0/resize/fit) and a detail. A per-operation body's
pointers point into that body (#/resize/fit).
{
"type": "https://videxo.io/docs/errors#invalid_request",
"title": "The request is not valid. `errors` lists each field that is wrong.",
"status": 400,
"detail": "outputs[1].fade.out: fade.out needs the output's length: set trim.duration or trim.end (or an end on every concat part).",
"code": "invalid_request",
"reason": "invalid_fields",
"retryable": false,
"request_id": "req_7h2m4x9q0c3v8k1n5r6t2b4z",
"errors": [
{
"pointer": "#/outputs/1/fade/out",
"detail": "fade.out needs the output's length: set trim.duration or trim.end (or an end on every concat part)."
}
]
}Copy failed. The text is selected; copy it with your keyboard.
The full list is on Error codes.