curl --request POST \
--url https://apis.viggle.ai/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'prompt=A paper airplane gliding through a sunlit office' \
--form quality=low \
--form first_frame_image=@example-file \
--form 'first_frame_image_url=<string>' \
--form last_frame_image=@example-file \
--form 'last_frame_image_url=<string>' \
--form reference_video=@example-file \
--form 'reference_video_url=<string>' \
--form reference_image=@example-file \
--form 'reference_image_url=<string>' \
--form driving_video=@example-file \
--form 'driving_video_url=<string>' \
--form character_image=@example-file \
--form 'character_image_url=<string>' \
--form 'character_image_urls=<string>' \
--form enhance_mode=planner \
--form priority=1000 \
--form duration_s=5 \
--form resolution=768p \
--form aspect_ratio=16:9 \
--form seed=1 \
--form watermark=false \
--form enhance=trueimport requests
url = "https://apis.viggle.ai/v1/videos"
files = {
"first_frame_image": ("example-file", open("example-file", "rb")),
"last_frame_image": ("example-file", open("example-file", "rb")),
"reference_video": ("example-file", open("example-file", "rb")),
"reference_image": ("example-file", open("example-file", "rb")),
"driving_video": ("example-file", open("example-file", "rb")),
"character_image": ("example-file", open("example-file", "rb"))
}
payload = {
"prompt": "A paper airplane gliding through a sunlit office",
"quality": "low",
"first_frame_image_url": "<string>",
"last_frame_image_url": "<string>",
"reference_video_url": "<string>",
"reference_image_url": "<string>",
"driving_video_url": "<string>",
"character_image_url": "<string>",
"character_image_urls": "<string>",
"enhance_mode": "planner",
"priority": "1000",
"duration_s": "5",
"resolution": "768p",
"aspect_ratio": "16:9",
"seed": "1",
"watermark": "false",
"enhance": "true"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('prompt', 'A paper airplane gliding through a sunlit office');
form.append('quality', 'low');
form.append('first_frame_image', '<string>');
form.append('first_frame_image_url', '<string>');
form.append('last_frame_image', '<string>');
form.append('last_frame_image_url', '<string>');
form.append('reference_video', '<string>');
form.append('reference_video_url', '<string>');
form.append('reference_image', '<string>');
form.append('reference_image_url', '<string>');
form.append('driving_video', '<string>');
form.append('driving_video_url', '<string>');
form.append('character_image', '<string>');
form.append('character_image_url', '<string>');
form.append('character_image_urls', '<string>');
form.append('enhance_mode', 'planner');
form.append('priority', '1000');
form.append('duration_s', '5');
form.append('resolution', '768p');
form.append('aspect_ratio', '16:9');
form.append('seed', '1');
form.append('watermark', 'false');
form.append('enhance', 'true');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/videos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/videos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/videos"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apis.viggle.ai/v1/videos")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"progress": 50,
"created_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}Using Viggle-Animate
Replace characters in a driving video with your character images. A driving video is required.
curl --request POST \
--url https://apis.viggle.ai/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form 'prompt=A paper airplane gliding through a sunlit office' \
--form quality=low \
--form first_frame_image=@example-file \
--form 'first_frame_image_url=<string>' \
--form last_frame_image=@example-file \
--form 'last_frame_image_url=<string>' \
--form reference_video=@example-file \
--form 'reference_video_url=<string>' \
--form reference_image=@example-file \
--form 'reference_image_url=<string>' \
--form driving_video=@example-file \
--form 'driving_video_url=<string>' \
--form character_image=@example-file \
--form 'character_image_url=<string>' \
--form 'character_image_urls=<string>' \
--form enhance_mode=planner \
--form priority=1000 \
--form duration_s=5 \
--form resolution=768p \
--form aspect_ratio=16:9 \
--form seed=1 \
--form watermark=false \
--form enhance=trueimport requests
url = "https://apis.viggle.ai/v1/videos"
files = {
"first_frame_image": ("example-file", open("example-file", "rb")),
"last_frame_image": ("example-file", open("example-file", "rb")),
"reference_video": ("example-file", open("example-file", "rb")),
"reference_image": ("example-file", open("example-file", "rb")),
"driving_video": ("example-file", open("example-file", "rb")),
"character_image": ("example-file", open("example-file", "rb"))
}
payload = {
"prompt": "A paper airplane gliding through a sunlit office",
"quality": "low",
"first_frame_image_url": "<string>",
"last_frame_image_url": "<string>",
"reference_video_url": "<string>",
"reference_image_url": "<string>",
"driving_video_url": "<string>",
"character_image_url": "<string>",
"character_image_urls": "<string>",
"enhance_mode": "planner",
"priority": "1000",
"duration_s": "5",
"resolution": "768p",
"aspect_ratio": "16:9",
"seed": "1",
"watermark": "false",
"enhance": "true"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('prompt', 'A paper airplane gliding through a sunlit office');
form.append('quality', 'low');
form.append('first_frame_image', '<string>');
form.append('first_frame_image_url', '<string>');
form.append('last_frame_image', '<string>');
form.append('last_frame_image_url', '<string>');
form.append('reference_video', '<string>');
form.append('reference_video_url', '<string>');
form.append('reference_image', '<string>');
form.append('reference_image_url', '<string>');
form.append('driving_video', '<string>');
form.append('driving_video_url', '<string>');
form.append('character_image', '<string>');
form.append('character_image_url', '<string>');
form.append('character_image_urls', '<string>');
form.append('enhance_mode', 'planner');
form.append('priority', '1000');
form.append('duration_s', '5');
form.append('resolution', '768p');
form.append('aspect_ratio', '16:9');
form.append('seed', '1');
form.append('watermark', 'false');
form.append('enhance', 'true');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/videos', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/videos",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/videos"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apis.viggle.ai/v1/videos")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"prompt\"\r\n\r\nA paper airplane gliding through a sunlit office\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quality\"\r\n\r\nlow\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"first_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"last_frame_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"driving_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_image_urls\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance_mode\"\r\n\r\nplanner\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"priority\"\r\n\r\n1000\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"duration_s\"\r\n\r\n5\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"resolution\"\r\n\r\n768p\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"aspect_ratio\"\r\n\r\n16:9\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"seed\"\r\n\r\n1\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"watermark\"\r\n\r\nfalse\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"enhance\"\r\n\r\ntrue\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"progress": 50,
"created_at": "2023-11-07T05:31:56Z"
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}POST /v1/videos selects character animation when you supply character_image, character_image_url, character_image_urls, driving_video, or driving_video_url. Every character-animation request requires a driving video.
400 INVALID_REQUEST, regardless of image count, prompt, or enhance_mode. For H3 image-conditioned video generation, see First Frame or Reference Video/Image.Choose the animation path
| Input | Image requirements | Motion and prompt behavior |
|---|---|---|
Driving video, planner (default) or normal | 1 image for one target; 2–3 images with ordered target tags for multiple targets | Source video provides motion. Multiple targets require the tags described below. Without tags, only the first image is used. |
Driving video, agent | 1–10 ordered images | Images map to Character1..N. The agent reads the editing instruction; tags are optional. |
With a driving video: one character
Supply eitherdriving_video or driving_video_url, not both. One character image is sufficient:
curl https://apis.viggle.ai/v1/videos \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-F '[email protected]' \
-F '[email protected]'
With a driving video: multiple characters
Inplanner or normal, use 2–3 images and one ordered target description per image. Tags must begin the prompt, start at <Character1>, appear in order and have nonempty descriptions. Each description identifies the corresponding person in the source video.
{
"driving_video_url": "https://example.com/driving.mp4",
"character_image_urls": ["https://example.com/first.jpg", "https://example.com/second.jpg"],
"prompt": "<Character1>the person in white on the left<Character2>the person in red on the right"
}
planner/normal. enhance_mode=agent accepts 1–10 ordered images and reads the prompt directly; tags are optional.
Request parameters
Usemultipart/form-data, application/x-www-form-urlencoded, or application/json. Files require multipart; JSON and URL-encoded forms use media URLs. For multiple images, JSON accepts a native array; form fields accept the array encoded as a JSON string.
| Parameter | Type | Requirements |
|---|---|---|
driving_video | file | Source video. Required: supply exactly one of driving_video or driving_video_url. |
driving_video_url | HTTPS URL | Source video URL, under the same video limits as an upload. |
character_image | repeated file | Ordered uploads. Cannot be mixed with image URLs. |
character_image_url | HTTPS URL, repeatable in forms | Cannot be combined with character_image_urls or uploads. Use character_image_urls for multiple images in JSON. |
character_image_urls | array of HTTPS URLs | Ordered images. Cannot be combined with character_image_url or uploads. Counts and usage depend on the path above. |
prompt | string, optional | Target descriptions and editing instructions depend on enhance_mode. |
enhance_mode | planner, normal, agent | Defaults to planner. |
watermark | boolean | Defaults to false. Does not affect price. |
priority | integer | Defaults to 1000; supported tiers are 1000 and 0. |
quality or H3 frame/reference fields. H3’s duration_s, resolution, aspect_ratio and seed do not configure character animation. For H3 image-conditioned video generation, see First Frame or Reference Video/Image.
Media requirements
- Uploaded character images must be valid decodable images, such as JPEG or PNG, at most 20 MiB each. The API does not require a fixed aspect ratio, exact pixel dimensions or full-body composition. UHD-sized uploads are downscaled while preserving aspect ratio. Passing validation does not guarantee visual quality.
- Public media URLs must use accessible
https://. Do not sendhttp://or internalgs://references. - Driving videos are limited to 100 MiB, must contain a decodable video stream, be at least 64×64, and have even dimensions.
- Use 5–16 seconds for
planner/normal, or 5–60 seconds foragent.
planner/normal: longer clips may be queued and then fail. Stay within the mode-specific ranges above. H3’s duration_s cannot change these limits.Response and errors
200 OK with an anim_ ID and status: queued acknowledges acceptance, not successful rendering. Poll Get Video until ready or a failure terminal state.
Requests without a driving video, including empty, whitespace-only, or JSON null video URLs, return 400 INVALID_REQUEST before media staging, task creation or credit reservation. Changing prompt or the number of images does not resolve this error; add driving_video or driving_video_url.
Other input errors also return 400 INVALID_REQUEST, including mixed upload/URL fields, non-HTTPS URLs, invalid image uploads or more than 10 images.
Pricing
Character animation reserves 1 credit ($0.01) per second, rounded up, using the measured driving-video duration. Atready, settlement uses finished-video duration at the same rate and cannot exceed the reservation. Failed tasks release the reservation. See Pricing and retention.Authorizations
Server-side SDK clients use a project API key. Remote MCP clients use an OAuth access token. Never expose a project API key in browser code.
Headers
Optional caller-supplied correlation ID, up to 128 characters. The service returns the effective value in the response header for tracing and support.
1 - 128Optional source-channel label, up to 128 characters, used to attribute traffic to an SDK, integration, product surface, or internal workflow.
1 - 128Body
Body of POST /v1/videos: H3 uses multipart/form-data; character
animation also accepts application/json and
application/x-www-form-urlencoded. Which fields are
supplied selects the generation mode:
- Neither
first_frame_image/first_frame_image_urlnorlast_frame_image/last_frame_image_urlnor any reference or character-animation field supplied: text-to-video. - A first frame supplied, no last frame: first-frame-to-video.
- Both a first frame and a last frame supplied: first+last-frame-to-video.
- Any of
reference_video/reference_video_url/reference_image/reference_image_urlsupplied: reference-video (omni-reference) generation. driving_video/driving_video_urland/orcharacter_image/character_image_url/character_image_urlssupplied: character-animation generation, dispatched to a separate backend from the four modes above. A driving video is required (image-only requests are not supported); image usage depends on enhance_mode and target tags as described below. It has noqualitytier, noduration_s/resolution/aspect_ratio/seed, andpromptis optional rather than required; see below andGenerate Video (from Character Animation)for its own fields, pricing, and constraints.
Within a frame slot, supply at most one of the file and the URL
form. Supplying both first_frame_image and first_frame_image_url
(or both last_frame_image and last_frame_image_url) answers
400 INVALID_REQUEST with "supply only one of first_frame_image or
first_frame_image_url" (or the last_frame_* equivalent). A last
frame requires a first frame; supplying a last frame with no first
frame answers 400 INVALID_REQUEST with "a last frame requires a
first frame".
Reference-video mode is selected purely by whether any of the four
reference fields is present — there is no separate source/mode
parameter, and no error if you meant to but forgot: supplying none
of reference_video/reference_video_url/reference_image/
reference_image_url simply generates text-to-video instead (the
first bullet above), the same way omitting first_frame_image/
last_frame_image falls back to text-to-video rather than
erroring. reference_video and reference_video_url are declared
as arrays for forward compatibility, but at most 1 reference video
is accepted today; supplying any combination of the two fields that
adds up to more than 1 (two files, two URLs, or one of each) answers
400 INVALID_REQUEST with "at most 1 reference video(s) allowed".
reference_image and reference_image_url may be mixed freely, but
their combined count cannot exceed 4; going over answers
400 INVALID_REQUEST with "at most 4 reference images are allowed".
Reference fields cannot be combined with
first_frame_image/last_frame_image (file or URL form); doing so
answers 400 INVALID_REQUEST with
"reference_video/reference_image cannot be combined with
first_frame_image/last_frame_image". The reference video itself
(independent of duration_s, the target duration of the generated
video) must be 0.5–600 seconds long and at least 64x64 with even
width and height, the same constraints enforced on uploaded video
elsewhere in this API, and at most 100 MiB whether uploaded or
fetched from reference_video_url.
Frame and reference images (first_frame_image, last_frame_image,
reference_image) may be up to 20 MiB each when uploaded, and up to
30 MiB when fetched from the matching *_url field. The format is
detected from the image bytes — JPEG, PNG, WebP, GIF, BMP, TIFF, or
HEIC/HEIF/AVIF — and there is no minimum or maximum dimension; an
image at or above 4K (long edge >= 3840 px or short edge >= 2160 px)
is downscaled to fit 1920x1080, keeping its aspect ratio. An
oversized upload answers 400 INVALID_REQUEST with "invalid or
oversized first_frame_image upload" (naming the field), an
undecodable one with "first_frame_image must be a valid image"; a
URL that can't be decoded answers "first_frame_image_url is not a
valid image", and an unreadable reference video URL answers
"reference_video_url is not a valid video".
Character-animation mode cannot be combined with quality or H3 frame/reference fields. For character animation, supply character images as
character_image uploads or character_image_url/
character_image_urls (uploads and URLs cannot be combined in the
same request).
A driving video is required: supply exactly one of driving_video
(upload) or driving_video_url (URL). Image-only requests are not
supported; omitting the video returns HTTP 400 INVALID_REQUEST
before media staging or task admission, regardless of image count,
prompt, or enhance_mode. One image replaces one target character.
In planner (default) or normal mode, replacing 2 or 3 characters
requires ordered <Character1>, <Character2> (and <Character3>)
descriptions in prompt, one per image, describing targets in the
source video. Without these tags, only the first image is used.
In agent mode, 1-10 images are used in order as Character1..N;
tags are optional. The driving video supplies the source motion.
For planner and normal, use a driving video 5-16 seconds long.
For agent, use 5-60 seconds. Both uploads and URLs undergo API
media validation with a 100 MiB limit. The API currently checks
duration after truncating to whole seconds, accepting 5-60 whole
seconds for all modes; this does not override the worker's 16-second
limit in planner/normal. A longer video can be queued and then
fail in those modes. Uploaded videos are staged to object storage;
URL-form sources are also fetched by the worker.
Billed at ⌈duration_s⌉ × the per-second credit rate for
resolution (currently 1 credit/second — $0.01/sec — at 480p,
768p, 1080p, and 2k, rising to 5 credits/second — $0.05/sec —
at 4k; the same rate applies to both quality tiers). quality,
aspect_ratio, and enhance do not affect price, and
image/video-conditioned generation (first-frame, first-last-frame,
or reference-video) costs the same as text-only for the same
quality, resolution, and duration. Character-animation mode is billed
at 1 credit/second instead: it reserves the driving video's
measured duration rounded up. On completion the charge is
settled against the finished video's duration, never above the
reservation. It is not tied to duration_s; see
Generate Video (from Character Animation).
Every generated video includes native audio; there is no separate audio flag or field.
Required for H3 generation. For character animation, planner/normal use ordered Character tags for multiple targets; agent reads the editing instruction directly. See the animation path descriptions above.
1"A paper airplane gliding through a sunlit office"
Generation quality tier. low generates faster, for quicker iteration; high generates slower but produces higher-fidelity output. Both tiers are billed at the same per-second rate for a given resolution — see resolution below. Required for every mode except character-animation, which has no quality tiers and rejects this field outright if supplied.
low, high "low"
First-frame image uploaded directly. Mutually exclusive with first_frame_image_url. Supplying either switches on first-frame-to-video mode. Cannot be combined with any reference_video/reference_image field. Up to 20 MiB; JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF, detected from the file contents. An image with a long edge of 3840 px or more, or a short edge of 2160 px or more, is downscaled to fit 1920x1080, keeping its aspect ratio.
Publicly reachable URL of the first-frame image; the service fetches and re-hosts it. Mutually exclusive with first_frame_image. Cannot be combined with any reference_video/reference_image field. The fetched image may be up to 30 MiB, in the same formats and with the same downscaling as the upload form.
Last-frame image uploaded directly. Mutually exclusive with last_frame_image_url. Valid only alongside a first frame. Cannot be combined with any reference_video/reference_image field. Up to 20 MiB; JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF, detected from the file contents. An image with a long edge of 3840 px or more, or a short edge of 2160 px or more, is downscaled to fit 1920x1080, keeping its aspect ratio.
Publicly reachable URL of the last-frame image; the service fetches and re-hosts it. Mutually exclusive with last_frame_image. Valid only alongside a first frame. Cannot be combined with any reference_video/reference_image field. The fetched image may be up to 30 MiB, in the same formats and with the same downscaling as the upload form.
Reference video uploaded directly, for reference-video (omni-reference) generation. Declared as an array for forward compatibility, but at most 1 is accepted today — combined with reference_video_url. Not required if at least one reference image is supplied instead. Up to 100 MiB, in any container with a readable video stream (MP4, MOV, WebM, etc.). Must be 0.5–600 seconds long and at least 64x64 with even width/height. Cannot be combined with first_frame_image/last_frame_image.
1Publicly reachable URL of the reference video; the service fetches and re-hosts it. Declared as an array for forward compatibility, but at most 1 is accepted today — combined with reference_video. Same size, duration, and resolution constraints as reference_video.
1Reference images uploaded directly, for reference-video (omni-reference) generation. Up to 4 total, combined with reference_image_url. Can be freely mixed with reference_image_url. Up to 20 MiB; JPEG, PNG, WebP, GIF, BMP, TIFF, or HEIC/HEIF/AVIF, detected from the file contents. An image with a long edge of 3840 px or more, or a short edge of 2160 px or more, is downscaled to fit 1920x1080, keeping its aspect ratio.
4Publicly reachable URLs of reference images; the service fetches and re-hosts each one. Up to 4 total, combined with reference_image. Can be freely mixed with reference_image. Each fetched image may be up to 30 MiB, in the same formats and with the same downscaling as reference_image.
4Source video upload for character animation, at most 100 MiB. Use 5-16 seconds for planner/normal, or 5-60 seconds for agent. Cannot be combined with driving_video_url. Character animation requires exactly one of driving_video or driving_video_url; image-only requests return 400 INVALID_REQUEST.
Source video URL for character animation, under the same limits as driving_video. Cannot be combined with driving_video. Character animation requires exactly one of driving_video or driving_video_url; image-only requests return 400 INVALID_REQUEST.
Ordered character image uploads, at most 20 MiB per image. Requires a driving video. Image usage depends on enhance_mode and prompt tags as described above.
10One character image URL. Requires a driving video. Use character_image_urls for multiple images in JSON. Cannot be combined with character_image_urls or uploads.
10Ordered character image URLs. Requires a driving video. Image usage depends on enhance_mode and prompt tags as described above. Cannot be combined with character_image_url or uploads.
10How a character animation prepares the driving video for the
render. planner writes the prompt and paints the pinned frames;
normal repaints the first frame and uses a fixed prompt; agent
hands the whole edit (plan, paints, renders, review, final cut)
to an AI agent. Omit it for planner.
Character animation only:
H3 generation ignores it and uses enhance.
planner, normal, agent Admission-queue priority tier, shared by H3 and character-animation modes. Defaults to 1000 (top tier) — most callers never need to set this. Must be one of the server's configured tiers (currently 1000 or 0). An unsupported integer answers 400 INVALID_REQUEST with "invalid render request: unsupported priority 500" (ending with the value sent) in H3 modes, or "unsupported priority" in character-animation mode; a non-integer answers "priority must be an integer".
H3 generation only. Requested video duration in seconds, between 5 and 15 inclusive. Defaults to 5. Does not set character animation duration; that comes from the driving video.
5 <= x <= 15Output resolution tier — also selects the per-second credit rate charged for this request. 480p, 768p, 1080p, and 2k are billed at $0.01/sec (1 credit/second); 4k is billed at $0.05/sec (5 credits/second).
480p, 768p, 1080p, 2k, 4k Output aspect ratio.
16:9, 9:16, 1:1, 4:3, 3:4, 21:9 Deterministic generation seed. Omit for a random seed. H3 modes only — not applicable to character-animation mode.
x >= 0Whether to burn in a Viggle watermark.
Whether to run a low-effort AI Planner pass that rewrites only prompt before generation; any supplied frame or reference video/image is left unchanged. H3 modes only — not applicable to character-animation mode. Defaults to true; pass false to use prompt exactly as given. Does not affect price.
Response
Video generation accepted and queued.
Acceptance acknowledgment for POST /v1/videos, shared by all five
generation modes. This is a queued confirmation, not the final
result — poll GET /v1/videos/{video_id} (or watch it via
GET /v1/videos) until status reaches ready, then read
video_url from that response.
Public video ID — vid_-prefixed for the four H3 modes, anim_-prefixed for character-animation mode.
1Lifecycle state at acceptance time; always queued.
queued, processing, ready, failed, cancelled Always null on acceptance.
0 <= x <= 100ISO 8601 creation timestamp, second precision.

