Create Video Edit
Redraws part of a video and keeps the rest: the area a mask marks white is drawn again from the prompt and any input_references (for example a person replaced by the one in a reference picture), and everything outside the mask is the video's own pixels. Answers 202 with a job, polled and fetched exactly as a POST /v1/videos job. GET /v1/videos/models lists edit in a model's operations, with what its edits take under edit.
The video and the mask: the first duration seconds of video are edited, scaled to cover the output size and centre-cropped. mask is white where the picture may change, as an image (every frame) or a video (frame by frame); the model redraws in cells of 16 by 16 pixels, so its edge is coarse, and a mask with some room around the subject leaves space for a differently built one. A box around a person, grown by about 50 pixels, works.
Sound: audio: keep (the default) copies the video's soundtrack onto the edit; generate makes a new one.
Motion guide: motion_guide: true adds the video with the masked area blurred as a reference video, which keeps the redrawn subject where the original stood and moving as it moved. Name it in the prompt.
minimax-h3: 768p only. Write the prompt in its layout with [video editing + reference generation] (or [video editing] without references), say what replaces what, and that everything outside the edited area stays as it is.
Billing: as POST /v1/videos: per second of duration, at the mode's and tier's price.
Body
application/jsonA Create Video request plus the video to edit and the mask of what may change. frame_images and input_reference are refused: the edit starts from its video. The other fields work as on POST /v1/videos: duration is how much of the video is edited, from its start, and aspect_ratio or size the output's shape, which the video is scaled to cover and centre-cropped to.
-
model string required
-
prompt string required
Must be a string (a list or number is a 400).
at most 8000 characters -
duration integer
Seconds of video. minimax-h3 takes 4-15; default 6. A whole number sent as text (
"8") is accepted. -
seconds integer
OpenAI/Sora's name for
duration;durationwins when both are sent. -
resolution string
minimax-h3:
2Krenders the 768p preset and enlarges it 2x (16:9 is 2688x1536). It bills 3 times the seconds times thequalitytier, takes about 3 times as long, and runs at every tier:qualitystandard,maxorultra, or basenum_inference_steps, renders the 768p preset on the base weights before the same upscale.4Kis the 2K render enlarged 1.5x by SeedVR2 after the engine (16:9 is 4032x2304, the soundtrack kept): it bills as 2K (the upscale is free), runs at Turbo only (any other tier at 4K is a 400), and takes about 18 s more per second of video, plus any wait for the upscaler; the job'soutput.upscalesays it was applied.default 768p768p2K4K -
aspect_ratio stringdefault 16:916:99:164:33:41:121:9
-
size string
Width x height; an alternative to
aspect_ratio, and must agree with it when both are sent. The second six are 2K and the last six 4K (seeresolution).1344x768768x13441024x768768x1024768x7681536x6722688x15361536x26882048x15361536x20481536x15363072x13444032x23042304x40323072x23042304x30722304x23044608x2016 -
frame_images array of objectsat most 2 items
-
input_references array of objects
Reference media for the subject, style or sound. Ignored when
frame_imagesis sent. -
input_reference string or object
OpenAI/Sora's first frame, as an https URL (or base64 data URI) string or as
{image_url}. Ignored whenframe_imagesis sent. Any other type is a 400. -
generate_audio boolean
Strictly
trueorfalse(inmultipart/form-datathe texttrueorfalse); anything else is a 400.default true -
seed integer
-
num_inference_steps integer
minimax-h3: the number of denoising steps. Omit it for the Turbo LoRA (4 steps, or 8 with
input_references); 10 to 50 runs the full base model, which takes longer and bills thequalitytier whose step range holds the count: 10 to 20 asstandard(1.5x), 21 to 40 asmax(3x), 41 to 50 asultra(5x; see Billing). Sending the Turbo count itself changes nothing. Preferquality. Also accepted underprovider.options(seeprovider).range 4–50 -
quality string
minimax-h3: the quality tier, the same in every mode.
turbo(auto,low; the default) is the Turbo LoRA at 1x the price;standard(medium) is 20 base steps at 1.5x;max(high) is 40 base steps at 3x;ultrais 50 base steps at 5x. The job stores the tier's own name. Sendingnum_inference_stepstoo is a 400 unless it is the tier's count. Also accepted underprovider.options(seeprovider).turbostandardmaxultraautolowmediumhigh -
start_time_seconds number
minimax-h3: where to start reading each reference video in
input_references, in seconds. Also accepted underprovider.options(seeprovider).at least 0 -
callback_url string
An https URL notified on completion, failure, cancellation and expiry. See
GET /v1/webhooks/secret. -
provider object
OpenRouter's provider preferences. The routing fields (
order,only,ignore,sort,allow_fallbacks, ...) are accepted and ignored.optionscarries the model's own settings (quality,num_inference_steps,start_time_secondsfor minimax-h3;GET /v1/videos/modelslists each model'sallowed_) for clients that cannot add top-level fields. From OpenRouter's SDKs usepassthrough_ parameters options.stealth: they keep only the slugs on their closed list and drop any other,vultrincluded, without an error. The first form present wins, the top level before any option; a key the model does not declare is a 400 naming its path. -
video string or object required
The video to edit, an https URL or a base64 data URI (MP4 or MOV, up to 50 MB), at least
durationseconds long. -
mask string or object required
What may change, white on black, at any size (fitted as the video is). An image is the same mask for every frame; a video is one mask per frame, its last held if it ends early. An https URL or a base64 data URI.
-
audio string
keepcopies the video's own soundtrack onto the edit (the model still hears it, so mouths follow it);generatemakes a new one.default keepkeepgenerate -
motion_guide boolean
Adds the video with the masked area blurred as the last reference video,
<Video N>where N is one more than the reference videos you send, so the redrawn subject keeps the original's place and movement. Name it in the prompt (for example "<Video 1> is the original shot with the person blurred; it gives where the person stands and how they move"). It counts toward the model's reference videos.default false
Body
multipart/form-dataResponses
Accepted. The job, pending, with its polling_url and queue_position.
application/json · video-job-payload
A missing video or mask, a model that does not edit, frame_images sent, a resolution the model does not edit at, or anything POST /v1/videos refuses. The message names the field.
application/json · error-payload
The API key is missing, unknown or not active. Send it as Authorization: Bearer <key>.
application/json · error-payload
Unknown video model
application/json · error-payload
A media input is over its size limit
application/json · error-payload
Too many videos for this model from your subscription, as on POST /v1/videos. Wait for Retry-After, then retry.
application/json · error-payload
The model has no valid capability spec at the moment and is not served.
application/json · error-payload
curl https://api.vultrinference.com/v1/videos/edits \
-H "Authorization: Bearer $VULTR_INFERENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "minimax-h3",
"prompt": "[video editing + reference generation] In the edited area, the man in <Picture 1> takes the place of the woman and does what she does at the same moments. Everything outside the edited area stays as it is.",
"duration": 6,
"aspect_ratio": "16:9",
"video": "https://example.com/source.mp4",
"mask": "https://example.com/mask.mp4",
"input_references": [
{
"type": "image_url",
"image_url": {
"url": "https://example.com/character.png"
}
}
]
}'import os
import requests
response = requests.post(
"https://api.vultrinference.com/v1/videos/edits",
headers={"Authorization": f"Bearer {os.environ['VULTR_INFERENCE_API_KEY']}"},
json={
"model": "minimax-h3",
"prompt": "[video editing + reference generation] In the edited area, the man in <Picture 1> takes the place of the woman and does what she does at the same moments. Everything outside the edited area stays as it is.",
"duration": 6,
"aspect_ratio": "16:9",
"video": "https://example.com/source.mp4",
"mask": "https://example.com/mask.mp4",
"input_references": [
{
"type": "image_url",
"image_url": {
"url": "https://example.com/character.png",
},
},
],
},
)
print(response.json())const response = await fetch("https://api.vultrinference.com/v1/videos/edits", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VULTR_INFERENCE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "minimax-h3",
"prompt": "[video editing + reference generation] In the edited area, the man in <Picture 1> takes the place of the woman and does what she does at the same moments. Everything outside the edited area stays as it is.",
"duration": 6,
"aspect_ratio": "16:9",
"video": "https://example.com/source.mp4",
"mask": "https://example.com/mask.mp4",
"input_references": [
{
"type": "image_url",
"image_url": {
"url": "https://example.com/character.png"
}
}
]
}),
});
console.log(await response.json());{
"id": "video_3f2a9c1e7b4d5a6c8e0f1a2b",
"object": "video",
"model": "string",
"status": "pending",
"progress": 0,
"created_at": 1790000000,
"polling_url": "string"
}