curl --request POST \
--url https://apis.viggle.ai/v1/renders \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form image='@example-file' \
--form 'image_url=<string>' \
--form 'character_id=<string>' \
--form motion_video='@example-file' \
--form 'motion_video_url=<string>' \
--form 'motion_id=<string>' \
--form background_mode=original \
--form 'bg_color=0,177,64'import requests
url = "https://apis.viggle.ai/v1/renders"
files = {
"image": ("example-file", open("example-file", "rb")),
"motion_video": ("example-file", open("example-file", "rb"))
}
payload = {
"image_url": "<string>",
"character_id": "<string>",
"motion_video_url": "<string>",
"motion_id": "<string>",
"background_mode": "original",
"bg_color": "0,177,64"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('image', '<string>');
form.append('image_url', '<string>');
form.append('character_id', '<string>');
form.append('motion_video', '<string>');
form.append('motion_video_url', '<string>');
form.append('motion_id', '<string>');
form.append('background_mode', 'original');
form.append('bg_color', '0,177,64');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/renders', 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/renders",
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=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\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/renders"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\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/renders")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/renders")
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=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"stage": "queued",
"progress": 50,
"video_url": "<string>",
"alpha_url": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"error": {
"code": "<string>",
"message": "<string>",
"details": {},
"request_id": "<string>"
},
"links": {
"self": "<string>",
"events": "<string>",
"download": "<string>"
}
}{
"id": "<string>",
"status": "queued",
"stage": "queued",
"progress": 50,
"video_url": "<string>",
"alpha_url": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"error": {
"code": "<string>",
"message": "<string>",
"details": {},
"request_id": "<string>"
},
"links": {
"self": "<string>",
"events": "<string>",
"download": "<string>"
}
}{
"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
}
}
}{
"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
}
}
}从角色与动作渲染视频
直接创建渲染任务,或提交已准备好的渲染草稿。
curl --request POST \
--url https://apis.viggle.ai/v1/renders \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form image='@example-file' \
--form 'image_url=<string>' \
--form 'character_id=<string>' \
--form motion_video='@example-file' \
--form 'motion_video_url=<string>' \
--form 'motion_id=<string>' \
--form background_mode=original \
--form 'bg_color=0,177,64'import requests
url = "https://apis.viggle.ai/v1/renders"
files = {
"image": ("example-file", open("example-file", "rb")),
"motion_video": ("example-file", open("example-file", "rb"))
}
payload = {
"image_url": "<string>",
"character_id": "<string>",
"motion_video_url": "<string>",
"motion_id": "<string>",
"background_mode": "original",
"bg_color": "0,177,64"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('image', '<string>');
form.append('image_url', '<string>');
form.append('character_id', '<string>');
form.append('motion_video', '<string>');
form.append('motion_video_url', '<string>');
form.append('motion_id', '<string>');
form.append('background_mode', 'original');
form.append('bg_color', '0,177,64');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://apis.viggle.ai/v1/renders', 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/renders",
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=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\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/renders"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\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/renders")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/renders")
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=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"character_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_video_url\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"motion_id\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"background_mode\"\r\n\r\noriginal\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"bg_color\"\r\n\r\n0,177,64\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"status": "queued",
"stage": "queued",
"progress": 50,
"video_url": "<string>",
"alpha_url": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"error": {
"code": "<string>",
"message": "<string>",
"details": {},
"request_id": "<string>"
},
"links": {
"self": "<string>",
"events": "<string>",
"download": "<string>"
}
}{
"id": "<string>",
"status": "queued",
"stage": "queued",
"progress": 50,
"video_url": "<string>",
"alpha_url": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"error": {
"code": "<string>",
"message": "<string>",
"details": {},
"request_id": "<string>"
},
"links": {
"self": "<string>",
"events": "<string>",
"download": "<string>"
}
}{
"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
}
}
}{
"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
}
}
}Content-Type 决定。
multipart/form-data 直接根据角色和动作输入创建渲染任务。两类输入均可使用文件、URL 或已保存素材的 ID。该形式返回 200,忽略 Idempotency-Key。
application/json 使用准备渲染返回的草稿创建任务。该形式返回 202,必须提供 Idempotency-Key。幂等范围为当前已认证项目或 OAuth 身份:相同键和相同标准化输入返回原任务,相同键配合不同输入则返回 IDEMPOTENCY_KEY_REUSED。
请求参数:multipart/form-data
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
character_id | string | 角色来源三选一 | — | 当前调用者拥有的 ready 角色 ID,通常以 char_ 开头。用于替代新图片。 |
image | file | 角色来源三选一 | — | 直接上传的角色图片,与 image_url、character_id 三选一。 |
image_url | string | 角色来源三选一 | — | 服务可下载的公开角色图片 URL,替代 image 或 character_id。 |
motion_id | string | 动作来源三选一 | — | 当前调用者拥有的 ready 动作 ID,通常以 mot_ 开头,用于替代新驱动视频。 |
motion_video | file | 动作来源三选一 | — | 直接上传的驱动视频,与 motion_video_url、motion_id 三选一。 |
motion_video_url | string | 动作来源三选一 | — | 服务可下载的公开驱动视频 URL,替代文件或动作 ID。 |
background_mode | string | 否 | original | original 保留或重建源背景;solid 使用 bg_color;transparent 输出 Alpha;inpaint 是 original 的兼容别名。 |
bg_color | string | solid 模式需要 | — | "R,G,B" 格式的纯色,如 "0,177,64",仅适用于 background_mode=solid。 |
character_id/motion_id 进行渲染。若只提供其中一组,例如有角色但无动作,则仍会报错。bg_color 仅适用于 solid 模式。
请求参数:application/json(草稿模式)
| 请求头 | 必填 | 说明 |
|---|---|---|
Idempotency-Key | 是 | 调用者生成的稳定键,长度 1–255 字符。相同标准化输入返回原任务,不同输入返回 IDEMPOTENCY_KEY_REUSED。 |
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
draft_id | string | 是 | 准备渲染返回的不透明草稿 ID。完成所有直传后原样传入;草稿仅能使用一次。 |
upload_completions | array | 有上传时必填 | 每个上传计划对应一项。草稿状态为 awaiting_uploads 时必填;无需上传时可省略或传空数组。 |
upload_completions[].upload_handle | string | 每项必填 | 对应上传计划中的不透明句柄,用于标识已完成的角色或动作上传。 |
upload_completions[].etag | string | 否 | 对象存储 PUT 返回的 ETag。若含外围引号,请保留。 |
响应参数
multipart 形式返回200 OK,JSON 草稿形式返回 202 Accepted,两者都返回 Render 对象。但直接 multipart 的 200 响应仅在 id、status、progress 和 created_at 中提供有效信息。
| 字段 | 类型 | 始终返回 | 说明 |
|---|---|---|---|
id | string | 是 | 以 render_ 开头的公开 ID。 |
status | string | 是 | queued、processing、ready、failed 或 cancelled。 |
stage | string 或 null | 是 | 可用时提供大致阶段。multipart 流程使用 analyzing/rendering/finishing,草稿流程可能使用其他值。 |
progress | integer 或 null | 是 | 可用时为 0–100 的进度。 |
video_url | string 或 null | 是 | 就绪后的成品视频 URL。 |
alpha_url | string 或 null | 是 | 透明输出的 Alpha 视频 URL。 |
created_at / completed_at | string 或 null | 是 | ISO 8601 时间。 |
error | object 或 null | 是 | 渲染失败时的错误详情。 |
links | object | 否 | {self, events, download},经过旧版迁移代理处理的任务不包含此字段。 |
{"id":"render_789ghi","status":"queued","stage":null,"progress":0,"video_url":null,"alpha_url":null,"created_at":"2026-07-21T10:00:00+00:00","completed_at":null,"error":null,"links":{"self":"/v1/renders/render_789ghi","events":"/v1/renders/render_789ghi/events","download":"/v1/renders/render_789ghi/download"}}
links.self 仍指向已停用的 GET /v1/renders/{render_id},不能继续使用。请用同一 id 调用获取视频轮询。links.events 和 links.download 不受影响。
直接 multipart 示例
body:=&bytes.Buffer{}; w:=multipart.NewWriter(body); image,_:=os.Open("character.png"); defer image.Close(); video,_:=os.Open("dance.mp4"); defer video.Close(); p,_:=w.CreateFormFile("image","character.png"); io.Copy(p,image); p,_=w.CreateFormFile("motion_video","dance.mp4"); io.Copy(p,video); w.WriteField("background_mode","original"); w.Close(); req,_:=http.NewRequest("POST","https://apis.viggle.ai/v1/renders",body); req.Header.Set("Authorization","Bearer "+os.Getenv("VIGGLE_API_KEY")); req.Header.Set("Content-Type",w.FormDataContentType()); resp,err:=http.DefaultClient.Do(req); if err!=nil { panic(err) }; defer resp.Body.Close()
const form=new FormData(); form.append("image",imageFile); form.append("motion_video",videoFile); form.append("background_mode","original"); const response=await fetch("https://apis.viggle.ai/v1/renders",{method:"POST",headers:{Authorization:`Bearer ${process.env.VIGGLE_API_KEY}`},body:form}); const render=await response.json();
import os, requests
with open("character.png","rb") as image, open("dance.mp4","rb") as video: response=requests.post("https://apis.viggle.ai/v1/renders",headers={"Authorization":f"Bearer {os.environ['VIGGLE_API_KEY']}"},files={"image":image,"motion_video":video},data={"background_mode":"original"})
response.raise_for_status(); render=response.json()
curl -X POST "https://apis.viggle.ai/v1/renders" -H "Authorization: Bearer $VIGGLE_API_KEY" -F "[email protected]" -F "[email protected]" -F "background_mode=original"
JSON 草稿示例
curl -X POST "https://apis.viggle.ai/v1/renders" \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"draft_id":"draft_abc123","upload_completions":[{"upload_handle":"up_1","etag":"\"9f...\""}]}'
import os, uuid, requests
response = requests.post(
"https://apis.viggle.ai/v1/renders",
headers={
"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={"draft_id": "draft_abc123", "upload_completions": [{"upload_handle": "up_1", "etag": "\"9f...\""}]},
)
response.raise_for_status()
render = response.json()
draft_id 和上传角色、动作素材的方法见准备渲染。授权
服务端 SDK 使用项目 API 密钥,Remote MCP 使用 OAuth 访问令牌。不要在浏览器代码中暴露项目密钥。
请求头
调用者生成的稳定幂等键,最长 255 字符。POST /v1/renders 的 JSON 草稿模式必填,multipart 模式忽略。
1 - 255可选的调用者自定义关联 ID,最长 128 字符。服务会在响应头返回实际使用的值,便于追踪和支持排查。
1 - 128可选来源标签,最长 128 字符,用于识别 SDK、集成、产品入口或内部工作流。
1 - 128请求体
角色在 image、image_url、character_id 中三选一,动作在 motion_video、motion_video_url、motion_id 中三选一。两组都完全省略时服务使用预配置默认角色和动作;仅提供一组仍会报错。
直接上传的角色图片,与 image_url、character_id 三选一。
服务可下载的公开角色图片 URL,替代 image 或 character_id。
当前调用者拥有的 ready 角色 ID,通常以 char_ 开头。用于替代新图片。
1直接上传的驱动视频,与 motion_video_url、motion_id 三选一。
服务可下载的公开驱动视频 URL,替代文件或动作 ID。
当前调用者拥有的 ready 动作 ID,通常以 mot_ 开头,用于替代新驱动视频。
1original 保留或重建源背景;solid 使用 bg_color;transparent 输出 Alpha;inpaint 是 original 的兼容别名。
original, solid, transparent, inpaint "R,G,B" 格式的纯色,如 "0,177,64",仅适用于 background_mode=solid。
"0,177,64"
响应
请求成功。
不含相关信息的渲染中,stage、progress、created_at 为 null,迁移代理处理的渲染可能省略 links,读取时应容忍缺失。响应提供结果 URL,但不提供媒体尺寸、时长、缩略图 URL 或链接过期元数据,不应自行推断这些字段。
以 render_ 开头的公开 ID。
1queued、processing、ready、failed 或 cancelled。
queued, processing, ready, failed, cancelled 可用时提供大致阶段。multipart 流程使用 analyzing/rendering/finishing,草稿流程可能使用其他值。
queued, preparing, generating, finalizing, ready, failed, cancelled, analyzing, rendering, finishing 可用时为 0–100 的进度。
0 <= x <= 100就绪后的成品视频 URL。
透明输出的 Alpha 视频 URL。
ISO 8601 时间。
ISO 8601 时间。
渲染失败时的错误详情。
Show child attributes
Show child attributes
{self, events, download},经过旧版迁移代理处理的任务不包含此字段。
Show child attributes
Show child attributes

