通义万相
curl --request POST \
--url https://api.mixroute.ai/v1/video/generationsimport requests
url = "https://api.mixroute.ai/v1/video/generations"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/video/generations', 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://api.mixroute.ai/v1/video/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/video/generations"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/video/generations")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/video/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body视频系列
通义万相
万相 3.0、2.7、2.6 视频生成、参考输入、编辑参数与异步任务处理。
通义万相
curl --request POST \
--url https://api.mixroute.ai/v1/video/generationsimport requests
url = "https://api.mixroute.ai/v1/video/generations"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/video/generations', 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://api.mixroute.ai/v1/video/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/video/generations"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/video/generations")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/video/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_body万相使用统一的 MixRoute 视频端点。model 保留在顶层,厂商的 input 与 parameters 对象完整放入 metadata。不同版本使用不同输入协议,请按完整模型 ID 选择下方参数。
模型可用性以账户的 模型列表 为准,不将未返回的厂商型号或日期快照视为已开通。
提示词使用 metadata.input.prompt。兼容写法的优先级依次为 metadata.input.prompt、metadata.prompt、顶层 prompt,前者存在时优先。提示词与有效媒体至少提供其一,并继续满足所选模型自身的必填规则。
原生字段保持名称透传;上游新增字段可放在原有 input/parameters 位置,由上游校验型号与场景约束。这不代表每个字段都适用于所有型号。
I2V 使用 first_clip 续写时,duration 控制包含源片段的最终总时长,不只是新增秒数。R2V 使用图1/视频1或 Image 1 / Video 1,图片与视频分别计数。2.7 不再沿用 2.6 T2V/R2V 的 size 或 shot_type;I2V 输出比例跟随源素材,不传 ratio。
2.6 R2V 按 reference_urls 顺序用 character1、character2 等引用主体,不使用 2.7 的图/视频分别编号。参考素材使用公网 HTTP/HTTPS 或可访问的 OSS URL。此处列出的 2.6 标准型号不套用其他 Flash 型号的 audio=false 开关;旧版特效模板也不是这八个型号的通用能力。
优先使用公网 URL。OSS 临时资源和厂商资产 ID 与上游账户、地域有关,须可被当前渠道访问。读取第三方 CDN 结果地址时,不要附带 MixRoute Key。
上游完整响应保留在 data.data,可读取其中的 usage 与 request_id。UNKNOWN 表示上游任务不存在或已过期,不应一概当作生成失败。建议每 15 秒查询一次,限流或临时错误时退避。上游任务查询和结果链接保留期有限,通常为 24 小时,应及时保存产物。
最终费用以控制台账单为准。提交可能预扣额度,预扣与任务完成后的结算可能不同;不要将输入时长、负数或零时长理解为零费用任务。
POST https://api.mixroute.ai/v1/video/generations
支持模型
| 模型 ID | 模式 | 分辨率 | 时长(秒) |
|---|---|---|---|
| wan3.0-video | 全能参考视频生成 | 480P / 720P / 1080P | 2-30 / -1 |
| wan2.7-t2v | 文生视频 | 720P / 1080P | 2-15 |
| wan2.7-i2v | 图生视频 | 720P / 1080P | 2-15 |
| wan2.7-r2v | 参考生视频 | 720P / 1080P | 2-15(无视频)/ 2-10(有视频) |
| wan2.7-videoedit | 视频编辑 | 720P / 1080P | 2-10 |
| wan2.6-t2v | 文生视频 | 720P / 1080P | 2-15 |
| wan2.6-i2v | 图生视频 | 720P / 1080P | 2-15 |
| wan2.6-r2v | 参考生视频 | 720P / 1080P | 2-10 |
请求包装
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 是 | 完整 MixRoute 模型 ID。 |
metadata | object | 是 | 除 model 之外的厂商请求体容器。 |
metadata.input | object | 是 | 原生 input 对象,提示词和媒体的必填规则取决于型号。 |
metadata.parameters | object | 否 | 原生生成设置,保留字段名称与层级。 |
使用 MixRoute Key 与 Authorization: Bearer 认证,无需阿里 Key、业务空间 ID、地域端点或 X-DashScope-Async 请求头。不要将 input/parameters 放到顶层,也不要将其内容平铺到 metadata 下。
Wan 3.0
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
metadata.input.prompt | string | 按模式 | 文本提示词,最多 20000 字符,超出部分截断;与 media 至少提供其一。 |
metadata.input.media | object[] | 按模式 | 媒体项数组,与 prompt 至少提供其一;组合规则见下方。 |
metadata.input.media[].type | string | 按模式 | 每项必填:first_frame、last_frame、reference_image、reference_video、reference_audio、file 或 link。 |
metadata.input.media[].url | string | 按模式 | 每项必填。公网 HTTP/HTTPS URL;图像另支持 Base64 data URI。原生 OSS 资源须可被路由账户访问。 |
metadata.parameters.resolution | string | 否 | 480P、720P 或 1080P;省略时 MixRoute 显式填入 1080P。 |
metadata.parameters.ratio | string | 否 | adaptive(默认)、16:9、4:3、1:1、3:4 或 9:16;延长视频使用 adaptive。 |
metadata.parameters.duration | integer | 否 | 默认 5 秒。无视频输入时为 2-30 秒;有视频输入时,输入视频总时长与输出时长之和不超过 30 秒。-1 为智能时长。 |
metadata.parameters.audio | boolean | 否 | 默认 true;false 输出无音轨视频。 |
metadata.parameters.seed | integer | 否 | -1 或 0-2147483647;-1 或省略时随机,不保证输出完全一致。 |
metadata.parameters.prompt_extend | boolean | 否 | 提示词智能改写,默认 true。 |
metadata.parameters.watermark | boolean | 否 | 添加 AI 水印,默认 false。 |
媒体类型
| type | 数量或用途 |
|---|---|
first_frame / last_frame | 各最多一张,使用首帧或首帧+尾帧,不单独传尾帧。 |
reference_image | 最多 10 张参考图。 |
reference_video | 最多五个视频,每段 1-15 秒,总时长不超过 15 秒。 |
reference_audio | 最多五个音频,每段 1-15 秒,总时长不超过 15 秒。 |
file | 一个公开文档,不超过 100 MB;分页格式不超过 50 页。 |
link | 一个无需登录即可访问的公开网页。 |
- 首帧/首尾帧组与 reference_*、file、link 互斥。与万相 2.7 I2V 不同,3.0 首尾帧模式不能搭配驱动音频。
- 参考图片、视频和音频可相互组合;file 与 link 二选一,但可与 reference_* 组合,仍须满足各类型数量上限和总计 20 个媒体素材的上限。
- 素材按类型分别计数,在提示词中用图1、视频1、音频1,或 Image 1、Video 1、Audio 1 指代。
- 编辑/延长须传 reference_video 并在提示词中说明意图。延长使用 ratio=adaptive;编辑可用 adaptive 与 duration=-1 保留源构图并自动选择时长。输入视频总时长与输出时长之和仍须不超过 30 秒。
万相 3.0 不使用 size、negative_prompt、template、img_url、first_frame_url、last_frame_url、audio_url。网关会清理旧字段,并可将 audio_url 转为 reference_audio 媒体项;新请求直接使用 input.media。
Wan 2.7
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
metadata.input.prompt | string | 按模式 | 最多 5000 字符,超出部分截断。T2V/R2V 必填;I2V/VideoEdit 提供必需媒体时可省略。 |
metadata.input.negative_prompt | string | 否 | 描述不希望出现的内容,最多 500 字符,超出部分截断。 |
metadata.input.audio_url | string | 否 | 仅 T2V:驱动音频 URL,WAV/MP3、2-30 秒、不超过 15 MB;长音频截断,短于视频时尾部无声。 |
metadata.input.media | object[] | 按模式 | I2V、R2V、VideoEdit 必填;各模式使用不同的媒体类型与组合。 |
metadata.input.media[].type | string | 按模式 | 每个媒体项必填,取值须匹配下方的型号规则。 |
metadata.input.media[].url | string | 按模式 | 每个媒体项必填。公网 HTTP/HTTPS URL;图像另支持 data:image/…;base64,…。原生 OSS 引用须可被路由访问。 |
metadata.input.media[].reference_voice | string | 否 | 仅 R2V 的 reference_image/reference_video:音色参考 URL,WAV/MP3、1-10 秒、不超过 15 MB,优先于参考视频原声。 |
metadata.parameters.resolution | string | 否 | 720P 或 1080P(默认),注意大小写。 |
metadata.parameters.ratio | string | 否 | T2V/R2V/VideoEdit:16:9、9:16、1:1、4:3 或 3:4。T2V/R2V 默认 16:9;R2V 有首帧时忽略 ratio。VideoEdit 省略时跟随源视频。I2V 跟随输入图像/视频,不使用此字段。 |
metadata.parameters.duration | integer | 否 | T2V/I2V 为 2-15 秒,默认 5。R2V 无视频参考时为 2-15 秒,有视频时为 2-10 秒,默认 5。VideoEdit 省略时保留源时长,设置 2-10 时从开头截断。 |
metadata.parameters.audio_setting | string | 否 | 仅 VideoEdit:auto(默认)按提示词决定音频处理;origin 保留源音频。 |
metadata.parameters.prompt_extend | boolean | 否 | 提示词智能改写,默认 true。 |
metadata.parameters.watermark | boolean | 否 | 添加 AI 水印,默认 false。 |
metadata.parameters.seed | integer | 否 | 范围 0-2147483647,省略则随机;相同种子不保证完全相同的输出。 |
输入模式
| 模型 | 媒体规则 |
|---|---|
wan2.7-t2v | prompt 与可选 input.audio_url,不使用 media 数组。 |
wan2.7-i2v | 仅使用:first_frame;first_frame+driving_audio;first_frame+last_frame;first_frame+last_frame+driving_audio;first_clip;first_clip+last_frame。各 type 最多一次。 |
wan2.7-r2v | reference_image/reference_video 合计 1-5 个,可另配一张 first_frame。reference_voice 位于每个参考项内,不是独立媒体类型。 |
wan2.7-videoedit | 有且只有一个 type=video 的源视频,可另配最多四张 reference_image。 |
Wan 2.6
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
metadata.input.prompt | string | 按模式 | 最多 1500 字符,超出部分截断。T2V/R2V 必填;I2V 有输入图像时可省略。R2V 用 character1、character2 等引用素材。 |
metadata.input.negative_prompt | string | 否 | 反向提示词,最多 500 字符,超出部分截断。 |
metadata.input.img_url | string | 按模式 | 仅 I2V,必填:首帧图片 URL 或图像 Base64 data URI。 |
metadata.input.audio_url | string | 否 | 仅 T2V/I2V:驱动音频 URL,WAV/MP3、2-30 秒、不超过 15 MB。 |
metadata.input.reference_urls | string[] | 按模式 | 仅 R2V,必填:1-5 个素材 URL,图像最多五张、视频最多三个,合计不超过五个,每个素材包含一个主体。 |
metadata.input.reference_video_urls | string[] | 否 | 已弃用的 R2V 纯视频输入,最多三个视频;优先使用 reference_urls,不混用两种格式。 |
metadata.parameters.size | string | 否 | 仅 T2V/R2V:使用下方尺寸表中的 宽*高,默认 1920*1080。 |
metadata.parameters.resolution | string | 否 | 仅 I2V:720P 或 1080P(默认),宽高比跟随首帧图像。 |
metadata.parameters.duration | integer | 否 | T2V/I2V 为 2-15 秒,R2V 为 2-10 秒,默认 5。 |
metadata.parameters.prompt_extend | boolean | 否 | 仅 T2V/I2V:提示词智能改写,默认 true;不是 R2V 参数。 |
metadata.parameters.shot_type | string | 否 | single(默认)或 multi。T2V/I2V 须同时开启 prompt_extend 才生效;R2V 直接使用此字段。优先级高于提示词中的镜头描述。 |
metadata.parameters.watermark | boolean | 否 | 添加 AI 水印,默认 false。 |
metadata.parameters.seed | integer | 否 | 范围 0-2147483647,省略则随机;相同种子不保证完全相同的输出。 |
T2V / R2V 尺寸
| 档位 | size 取值 |
|---|---|
| 720P | 1280*720, 720*1280, 960*960, 1088*832, 832*1088 |
| 1080P | 1920*1080, 1080*1920, 1440*1440, 1632*1248, 1248*1632 |
媒体限制
| 输入 | 限制 |
|---|---|
| 图像 | JPEG/JPG、无透明通道 PNG、BMP、WebP;宽高各 240-8000 px,不超过 20 MB。3.0/2.7 另要求长短边比不超过 8:1。 |
| 3.0 参考视频 | MP4/MOV,每段 1-15 秒、合计不超过 15 秒;至少 16 fps;宽高各 240-4096 px;长短边比不超过 8:1;单个不超过 100 MB。 |
| 2.7 视频 | MP4/MOV;宽高各 240-4096 px,长短边比不超过 8:1,不超过 100 MB。first_clip/VideoEdit 源视频为 2-10 秒,R2V 参考视频为 1-30 秒。 |
| 2.6 R2V 视频 | reference_urls 支持 MP4/MOV、1-30 秒、不超过 100 MB;已弃用 reference_video_urls 格式的时长为 2-30 秒。 |
| 音频 | WAV/MP3,单个不超过 15 MB。3.0 参考音频每段 1-15 秒、合计不超过 15;2.7 reference_voice 为 1-10 秒;T2V 驱动音频与 I2V driving_audio 为 2-30 秒。 |
| 3.0 文件 | docx, doc, xlsx, xls, pptx, ppt, pdf, txt, key, pages, numbers, md; 不超过 100 MB;PDF/Word/PowerPoint/Keynote/Pages 文档不超过 50 页。 |
请求示例
设置 MIXROUTE_API_KEY,并将 example.com 媒体地址替换为可访问的源素材。每次 POST 会创建独立任务,提交超时后不要自动重复提交。Wan 3.0 Video
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan3.0-video",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting."
},
"parameters": {
"resolution": "480P",
"ratio": "16:9",
"duration": 2,
"audio": false,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.7 T2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-t2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting."
},
"parameters": {
"resolution": "720P",
"ratio": "9:16",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.7 I2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-i2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"media": [
{
"type": "first_frame",
"url": "https://example.com/reference.png"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.7 R2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-r2v",
"metadata": {
"input": {
"prompt": "Image 1 slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"media": [
{
"type": "reference_image",
"url": "https://example.com/reference.png"
}
]
},
"parameters": {
"resolution": "720P",
"ratio": "1:1",
"duration": 2,
"watermark": false
}
}
}'
Wan 2.7 VideoEdit
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-videoedit",
"metadata": {
"input": {
"prompt": "Change the mug color to blue while preserving the original motion and white tabletop.",
"media": [
{
"type": "video",
"url": "https://example.com/source.mp4"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 2,
"watermark": false
}
}
}'
Wan 2.6 T2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.6-t2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting."
},
"parameters": {
"size": "1280*720",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.6 I2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.6-i2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"img_url": "https://example.com/reference.png"
},
"parameters": {
"resolution": "720P",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.6 R2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.6-r2v",
"metadata": {
"input": {
"prompt": "character1 slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"reference_urls": [
"https://example.com/reference.png"
]
},
"parameters": {
"size": "1280*720",
"duration": 2,
"watermark": false
}
}
}'
首尾帧
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-i2v",
"metadata": {
"input": {
"prompt": "A closed gift box slowly opens, revealing a red ceramic mug.",
"media": [
{
"type": "first_frame",
"url": "https://example.com/first.png"
},
{
"type": "last_frame",
"url": "https://example.com/last.png"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 5
}
}
}'
文件输入,不传提示词
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan3.0-video",
"metadata": {
"input": {
"media": [
{
"type": "file",
"url": "https://example.com/product.pptx"
}
]
},
"parameters": {
"resolution": "480P",
"duration": 5
}
}
}'
响应与轮询
提交返回 MixRoute task_id(以及 id 别名),不是上游任务 ID。{
"id": "TASK_ID",
"task_id": "TASK_ID",
"object": "video",
"model": "wan3.0-video",
"status": "queued"
}
GET https://api.mixroute.ai/v1/video/generations/{task_id}
| 网关状态 | 上游状态 | 处理 |
|---|---|---|
NOT_START / QUEUED | PENDING | 等待并继续查询。 |
IN_PROGRESS | RUNNING | 继续轮询。 |
SUCCESS | SUCCEEDED | 读取 data.result_url。 |
FAILURE | FAILED / CANCELED / UNKNOWN | 停止,检查 data.fail_reason 与上游响应。 |
{
"code": "success",
"message": "",
"data": {
"task_id": "TASK_ID",
"status": "SUCCESS",
"progress": "100%",
"result_url": "https://example.com/generated.mp4",
"fail_reason": "",
"data": {
"request_id": "UPSTREAM_REQUEST_ID",
"output": {
"task_id": "UPSTREAM_TASK_ID",
"task_status": "SUCCEEDED",
"video_url": "https://example.com/generated.mp4"
},
"usage": {
"output_video_duration": 2,
"SR": 480,
"video_count": 1
}
}
}
}
只在 SUCCESS 后读取 result_url。失败时该字段可能填入失败原因,不一定是 URL。外层 code=“success” 仅代表查询成功,不代表视频生成成功。
Python 完整流程
import os
import time
from urllib.parse import quote, urlparse
import requests
BASE_URL = "https://api.mixroute.ai"
def create_video(session, payload):
response = session.post(BASE_URL + "/v1/video/generations", json=payload, timeout=120)
response.raise_for_status()
result = response.json()
task_id = result.get("task_id") or result.get("id")
if not task_id:
raise RuntimeError(result.get("message") or result)
return task_id
def wait_for_video(session, task_id, timeout_seconds=1200):
url = BASE_URL + "/v1/video/generations/" + quote(task_id, safe="")
deadline = time.monotonic() + timeout_seconds
delay = 15
while time.monotonic() < deadline:
remaining = deadline - time.monotonic()
if remaining <= 0:
break
try:
response = session.get(url, timeout=min(30, remaining))
except (requests.Timeout, requests.ConnectionError):
delay = min(delay * 2, 60)
else:
if response.status_code in (429, 500, 502, 503, 504):
delay = min(delay * 2, 60)
else:
response.raise_for_status()
result = response.json()
if result.get("code") not in (None, 0, 200, "0", "200", "success"):
raise RuntimeError(result.get("message") or result)
task = result.get("data") or {}
status = str(task.get("status", "")).upper()
if status == "SUCCESS":
video_url = task.get("result_url", "")
parsed = urlparse(video_url)
if parsed.scheme not in ("http", "https") or not parsed.netloc:
raise RuntimeError("Successful task has no valid video URL")
return task
if status in {"FAILURE", "FAILED", "EXPIRED", "CANCELED", "CANCELLED"}:
raise RuntimeError(task.get("fail_reason") or task)
if status not in {"QUEUED", "NOT_START", "PENDING", "IN_PROGRESS", "RUNNING"}:
raise RuntimeError("Unknown task status: " + status)
delay = 15
remaining = deadline - time.monotonic()
if remaining <= 0:
break
time.sleep(min(delay, remaining))
raise TimeoutError("Video task is still pending; keep its task ID and query it later")
if __name__ == "__main__":
payload = {
"model": "wan3.0-video",
"metadata": {
"input": {"prompt": "A red ceramic mug slowly rotates on a white tabletop."},
"parameters": {"resolution": "480P", "ratio": "16:9", "duration": 2, "audio": False},
},
}
with requests.Session() as session:
session.headers["Authorization"] = "Bearer " + os.environ["MIXROUTE_API_KEY"]
task_id = create_video(session, payload)
print("task_id:", task_id, flush=True)
task = wait_for_video(session, task_id)
print(task["result_url"])
print(task.get("data", {}).get("usage", {}))