Wan
Wan(通义万相)是阿里的视频生成系列,由 DashScope 渠道提供。任务通过与其他视频模型相同的端点提交——见创建任务和查询任务。本页完整说明 Wan 3.0 适配器:它读取哪些请求字段、如何组装 DashScope 请求、素材规则、如何读取任务记录,以及按秒计费如何计算。
视频生成是异步任务:提交、保存 task_id、每 10–15 秒查询一次,状态变成 SUCCESS 后下载。
| 模型 ID | 分辨率 | 时长 | 说明 |
|---|---|---|---|
wan3.0-video | 480P、720P、1080P | 2–30 秒,或 -1 智能时长 | 标准版:文生视频、首尾帧图生视频、多模态参考素材 |
wan3.0-video-prime | 480P、720P、1080P | 2–30 秒,或 -1 智能时长 | 极速版,能力与标准版一致 |
请求省略时两者都默认 1080P 和 5 秒。两者都支持文生视频、首帧与首尾帧图生视频、参考图/参考视频/参考音频、视频编辑和视频延长。模型 ID 以 GET /v1/models 返回的为准;账户能用哪些模型、单价多少,以 RouteAPI 控制台为准。
该渠道还提供较旧的 Wan 2.x 模型(wan2.7-i2v、wan2.7-t2v、wan2.5-i2v-preview、wan2.2-*、wanx2.1-*),规则不同,不在本页范围。
通用信封如何映射
Section titled “通用信封如何映射”| 信封字段 | Wan 3.0 适配器的处理 |
|---|---|
prompt | 作为 input.prompt 发送。与所有任务请求一样,prompt 为空会在提交前被拒绝(400) |
image / images | 设置了 image 就用它作首帧,否则取 images 里第一张非空图片;尾帧取 images 里第二张非空图片。超过两张的图片会被忽略 |
input_reference | 单图简写:把 images 替换成一个 URL,但首帧仍由顶层 image 优先 |
resolution | 作为 parameters.resolution 发送,转为大写并在需要时补 P |
ratio | 作为 parameters.ratio 发送,转为小写 |
size | 折算成 resolution 和 ratio 后丢弃。1920x1080 和 1920*1080 都接受;* 形式不在支持表内时返回 400,而 720p 这样的纯档位会被当作分辨率使用 |
duration | 作为 parameters.duration 发送。缺失时变为 5 |
seconds | 在没有 duration 时解析为整数时长 |
generate_audio | 作为 parameters.audio 发送;显式 false 也会转发 |
metadata | 合并覆盖到已构建的请求上,因此 metadata.parameters.* 和 metadata.input.* 优先于映射值 |
两者同时发送时,显式的 resolution / ratio 优先于由 size 推导的值;size 始终会从上游请求体中移除。适配器随后把 input、parameters 和 model 发到 DashScope 的视频合成端点,你不需要自己调用该端点。
由于请求体采用 DashScope 的结构,同样的取值也可以放在 metadata 里:
{ "metadata": { "input": { "negative_prompt": "blurry, low quality" }, "parameters": { "duration": 10, "resolution": "720p", "ratio": "9:16" } }}metadata 不能换模型:metadata.model 与解析出的上游模型不一致时返回 400。
以下字段可以写在请求体顶层,模型专属参数放在 metadata 里。
| 字段 | 类型 | 取值 | 说明 |
|---|---|---|---|
model | string | wan3.0-video、wan3.0-video-prime | 必填 |
prompt | string | — | 必填且不能为空。参考素材模式里用「图 1」「视频 1」「音频 1」指代素材 |
resolution | string | 480P、720P、1080P | 大小写均可,结尾的 P 可省略。默认 1080P |
ratio | string | adaptive、21:9、16:9、4:3、1:1、3:4、9:16 | 大小写均可。不传时由 DashScope 按 adaptive 处理 |
size | string | 1280*720、1280x720 或 720p | 折算成 resolution 和 ratio 后丢弃。只有适配器表内的像素尺寸才接受 |
duration | integer | 2–30 | 输出时长(秒),默认 5。负数或大于 3600 会被通用任务校验拒绝;-1 智能时长只能写在 metadata.parameters 里 |
seconds | string | 整数字符串 | duration 缺失或为 0 时替代它。不是整数会返回 400 |
image | string | URL | 单张首帧图片;首帧优先取它,其次才看 images |
images | array | URL 列表 | 1 张为首帧;2 张依次为首帧和尾帧 |
input_reference | string | URL | 把 images 替换成一个首帧 URL;首帧仍由顶层 image 优先 |
generate_audio | boolean | true / false | 作为 parameters.audio 发送;显式 false 会按 false 转发 |
metadata | object | DashScope 的 input / parameters | 覆盖已映射的值,见下节 |
size 若是 宽*高 像素对,必须命中适配器的表:480P 接受 832*480、480*832、624*624;720P 接受 1280*720、720*1280、960*960、1088*832、832*1088;1080P 接受 1920*1080、1080*1920、1440*1440、1632*1248、1248*1632。比例由像素对约分得出,只有命中支持列表才保留,否则交给 DashScope 的默认比例。
metadata 参数
Section titled “metadata 参数”metadata 与 DashScope 的 input / parameters 对象一一对应,下列键均为可选。
| metadata 键 | 类型 | 说明 |
|---|---|---|
input.media | array | 由 {"type", "url"} 项组成的素材列表。给出后顶层图片字段不再生效 |
input.prompt | string | 发给上游时替换顶层 prompt,但通用校验仍要求顶层 prompt 存在 |
input.audio_url | string | 追加一条 reference_audio 的简写 |
input.negative_prompt | string | 反向提示词 |
input.template | string | DashScope 特效模板,原样转发 |
parameters.resolution | string | 同顶层 resolution |
parameters.ratio | string | 同顶层 ratio |
parameters.size | string | 同顶层 size |
parameters.duration | integer | -1 为智能时长,否则 2–30 |
parameters.audio | boolean | 同 generate_audio |
parameters.seed | integer | -1 或 0–2147483647。0 会作为显式值保留;相同种子不保证结果完全一致 |
parameters.watermark | boolean | 供应商侧水印,默认关闭 |
parameters.prompt_extend | boolean | 可以传,但没有任何作用——提示词改写始终开启,见下文 |
metadata.parameters.* 中的值优先于顶层对应字段。metadata 里不认识的键会被忽略,类型写错的键会在预扣前返回 400。
prompt_extend 无法关闭。顶层没有这个字段,写在顶层的 prompt_extend 会被直接忽略;写在 metadata.parameters 里时,适配器始终以 true 为起点,而该字段是不带指针的 bool 且带 omitempty,所以 false 在发给 DashScope 时会被丢掉,由上游默认值(开启)生效。写上它只是重申默认值,不会改变行为。
Wan 3.0 通过 input.media 接收素材,它是一个由 {"type": "...", "url": "..."} 项组成的数组。适配器会从顶层图片字段构建它,并合并你显式传入的内容:
type | 含义 | 上限(DashScope) |
|---|---|---|
first_frame | 视频首帧 | 1 |
last_frame | 视频尾帧,必须同时有首帧 | 1 |
reference_image | 用于主体/风格参考的参考图 | 10 |
reference_video | 用于参考生成、视频编辑或视频延长的参考视频 | 5 段,总时长 ≤15 秒 |
reference_audio | 参考音频。input.audio_url 会以该类型追加 | 5 段,总时长 ≤15 秒 |
在 metadata.input.media 中显式给出的 media 会原样保留;未给出时,适配器按 first_frame、last_frame 的顺序从顶层图片字段构建。这条兜底路径还会读取旧的 metadata.input.img_url / first_frame_url / last_frame_url,而 metadata.input.audio_url 始终会追加一条 reference_audio。这四个旧字段都会被折进 media 后清空——Wan 3.0 只认 media。
上表的数量和时长是 DashScope 的规则,RouteAPI 不做前置校验;违反时由上游拒绝并退款——可能表现为 fail_to_fetch_task 错误,也可能表现为 FAILURE 任务记录,而不是本地 400。
素材规则:
- 素材 URL 必须是无需登录即可直接下载的公网 http(s) 地址。图片还可以用
data:image/png;base64,...。 - 单个素材限制:图片 JPEG / JPG / PNG(无透明通道)/ BMP / WEBP,宽高 240–8000 像素,宽高比 ≤8:1,≤20MB;视频 mp4 / mov,每段 1–15 秒,≥16fps,宽高 240–4096 像素,≤100MB;音频 wav / mp3,每段 1–15 秒,≤15MB。
- 首帧/尾帧模式与参考素材模式互斥。在同一个
media里把首尾帧和reference_*混写会被上游拒绝:任务退款。 reference_image、reference_video、reference_audio可以自由组合。- 提示词里用「图 1」「视频 1」「音频 1」指代素材,序号按同类素材在
media中的出现顺序计算。
有两条规则在本地、提交前就拦下,既不访问上游也不扣费:
metadata.input.audio_url与first_frame或last_frame同时出现会返回400,消息为wan3 does not support audio_url together with first/last frame images。该检查只看input.audio_url;如果直接把reference_audio项写进media与帧混合,则由 DashScope 拒绝(任务FAILURE,退款)。- metadata 合并后,prompt 为空且
media为空会返回400(wan3 requires prompt or input.media)。实际上通用任务校验已经拒绝空 prompt,因此 prompt 始终必填。
只传 prompt 和视频参数:
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "wan3.0-video", "prompt": "An orange cat walking on a rooftop, cinematic lighting", "resolution": "480P", "ratio": "16:9", "duration": 2 }'首帧与首尾帧
Section titled “首帧与首尾帧”用顶层 images 传图片:1 张作为首帧,2 张依次作为首帧和尾帧。
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "wan3.0-video", "prompt": "The scene shifts naturally from morning to sunset while the camera moves smoothly", "images": [ "https://cdn.example.com/first.jpg", "https://cdn.example.com/last.jpg" ], "resolution": "720P", "ratio": "adaptive", "duration": 5 }'也可以在 metadata.input.media 里用显式 type 写出首尾帧;last_frame 必须和 first_frame 一起使用。
参考图 + 参考视频 + 参考音频
Section titled “参考图 + 参考视频 + 参考音频”需要参考素材时,在 metadata.input.media 里逐项写出。一旦给了 media,顶层图片字段就不再生效。
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "wan3.0-video", "prompt": "The character in image 1 performs the motion from video 1, dancing to the rhythm of audio 1", "resolution": "720P", "ratio": "adaptive", "duration": 8, "metadata": { "input": { "media": [ { "type": "reference_image", "url": "https://cdn.example.com/character.jpg" }, { "type": "reference_video", "url": "https://cdn.example.com/motion.mp4" }, { "type": "reference_audio", "url": "https://cdn.example.com/music.mp3" } ] } } }'含 reference_video 项的请求在提交时按 30 秒预扣,与请求的时长无关,因为此时无法确定最终输出长度——见计费。
视频编辑与视频延长
Section titled “视频编辑与视频延长”两者都用 reference_video 传原视频,用提示词表达意图。
- 视频编辑——例如「将视频 1 整体转换为黏土动画风格」。建议
ratio传adaptive,输出保持原视频比例。 - 视频延长——例如「将视频 1 向后延长,保持人物动作和镜头风格一致」。
ratio必须是adaptive。duration填「原视频时长 + 延长时长」:5 秒视频延长 2 秒填7。也可以填-1由模型决定。
有视频输入时,「输入视频时长 + 输出时长」不能超过 30 秒。该限制由 DashScope 执行;超出会失败并退款。
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "wan3.0-video", "prompt": "Convert video 1 entirely into a claymation style", "resolution": "480P", "ratio": "adaptive", "duration": 2, "metadata": { "input": { "media": [ { "type": "reference_video", "url": "https://cdn.example.com/input.mp4" } ] } } }'把同一段 5 秒视频延长 2 秒,只需改提示词和时长:
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "wan3.0-video", "prompt": "Extend video 1 forward by two seconds, keeping the character motion and camera style consistent", "resolution": "480P", "ratio": "adaptive", "duration": 7, "metadata": { "input": { "media": [ { "type": "reference_video", "url": "https://cdn.example.com/input.mp4" } ] } } }'智能时长由模型决定输出长度。在 metadata.parameters.duration 里传 -1;顶层 duration 传负数会被通用任务校验拒绝,返回 invalid_seconds。
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "wan3.0-video", "prompt": "An orange cat walking on a rooftop, cinematic lighting", "resolution": "480P", "ratio": "16:9", "metadata": { "parameters": { "duration": -1 } } }'智能时长任务提交时按 30 秒预扣,完成后按实际输出时长结算并退还差额。
curl https://api.routeapi.ai/v1/video/generations/task_FQvcRkHE9wjSWwyISDcrWCKoqCPNdkCx \ -H "Authorization: Bearer $ROUTEAPI_KEY"{ "code": "success", "message": "", "data": { "id": 4512, "created_at": 1792412645, "updated_at": 1792412780, "task_id": "task_FQvcRkHE9wjSWwyISDcrWCKoqCPNdkCx", "platform": "17", "user_id": 1024, "group": "default", "channel_id": 18, "quota": 50000, "action": "textGenerate", "status": "SUCCESS", "progress": "100%", "fail_reason": "", "result_url": "https://dashscope-result.oss.example/video.mp4", "submit_time": 1792412645, "start_time": 1792412650, "finish_time": 1792412780, "properties": { "input": "", "origin_model_name": "wan3.0-video", "upstream_model_name": "wan3.0-video" }, "data": { "request_id": "42a9c287-db7b-9edb-b613-xxxxxxxx", "output": { "task_id": "dd40fcb4-34f4-4292-a9e0-xxxxxxxx", "task_status": "SUCCEEDED", "video_url": "https://dashscope-result.oss.example/video.mp4", "orig_prompt": "An orange cat walking on a rooftop, cinematic lighting" }, "usage": { "video_count": 1, "duration": 2, "input_video_duration": 0, "output_video_duration": 2, "fps": 30, "SR": 480, "ratio": "16:9" } } }}外层字段由 RouteAPI 生成。判断进度以 data.status 为准;data.progress 对 Wan 只是粗略的阶段标记(20% 排队、30% 生成中、100% 完成),不是上游的真实百分比。data.quota 是目前已扣的额度,任务成功后即为结算后的金额。请求带了顶层图片字段(image、images 或 input_reference)时 data.action 为 generate,否则为 textGenerate。
data.data 是 DashScope 返回的任务原文,原样存储。需要关注这些字段:
| 字段 | 说明 |
|---|---|
data.data.output.task_id | DashScope 任务 ID,与外层 data.task_id 不同 |
data.data.output.video_url | 上游视频地址,与外层 data.result_url 相同 |
data.data.output.orig_prompt | DashScope 收到的提示词 |
data.data.usage.output_video_duration | 实际输出秒数——计费就是按它算 |
data.data.usage.input_video_duration | 输入视频秒数,不计费。纯文生视频为 0 |
data.data.usage.duration | 输入 + 输出秒数,仅供参考,从不用于结算 |
data.data.usage.SR | 实际输出分辨率档位,数字形式(480、720、1080),用于结算 |
data.data.usage.fps | 输出帧率,这两个模型为 30 |
data.data.usage.ratio | 实际画面比例。adaptive 时为原素材比例,如 427:240 |
任务结束前 data.data 可能只有部分字段,是否结束以 data.status 为准,不要看 usage 是否存在。
状态含义:NOT_START、QUEUED 继续轮询,IN_PROGRESS 生成中,SUCCESS 可以下载,FAILURE 看 fail_reason——预扣额度已经退回。
data.result_url 指向阿里托管的文件。该地址是临时的,阿里会按其自身策略使其过期,请尽快下载;也可以改用 RouteAPI 流式获取,不受该地址剩余有效期影响:
curl -L -o out.mp4 \ https://api.routeapi.ai/v1/videos/task_FQvcRkHE9wjSWwyISDcrWCKoqCPNdkCx/content \ -H "Authorization: Bearer $ROUTEAPI_KEY"content 端点只对调用者自己已完成的任务返回数据:未完成返回 400 并在消息里带上当前状态,未知或他人 task_id 返回 404,拉取上游失败返回 502。完整错误表见查询任务。还没过期的 result_url 也可以直接作为下一次请求的 reference_video 或 reference_image。
| DashScope 状态 | 任务记录状态 |
|---|---|
PENDING | QUEUED |
RUNNING | IN_PROGRESS |
SUCCEEDED | SUCCESS |
FAILED、CANCELED、UNKNOWN | FAILURE |
Wan 3.0 按输出秒数计费,并按分辨率缩放。控制台价格是 480P 的每秒单价,其余档位按模型的分辨率倍率相乘,默认 480P : 720P : 1080P = 1 : 2 : 4。
预扣与结算用同一套公式:
base quota = model price (per 480P second) × group ratioreserved quota = base quota × reserved seconds × resolution ratiosettled quota = min(base quota × output seconds × effective ratio, reserved quota)生效倍率 是请求档位的倍率;若 DashScope 报告的 SR 低于请求档位,则改用低档的倍率。它永远不会高于请求档位。
预扣与结算:
| 请求类型 | 提交时预扣 | 任务完成后 |
|---|---|---|
指定时长、不含 reference_video | 请求的秒数 | 实际输出秒数 |
含 reference_video 项 | 30 秒 | 实际输出秒数,退还差额 |
metadata.parameters.duration: -1(智能时长) | 30 秒 | 实际输出秒数,退还差额 |
适配器中可验证的结算规则:
- 只对
usage.output_video_duration计费。输入视频秒数、参考图、参考音频和首尾帧都不收费,是否生成音轨也不影响价格。 - 单价取提交时的快照。任务运行期间控制台调价不影响已提交的任务,预扣金额保持原样。
- 结算只退不补。上游报告秒数超过预扣、
SR更高,或usage格式异常时,保持预扣金额而不额外加扣;成功响应缺少usage时同样保持预扣。 - 任务失败——审核不通过、上游超时、取消——退回预扣额度。
400在提交前就被拒绝,不会扣费。 - 需要按 30 秒预扣的请求,账户余额或 Key 额度必须足以覆盖该预扣,否则提交时返回
403insufficient_user_quota。
提交响应带有 X-New-Api-Other-Ratios 头,列出实际应用的倍率,例如 5 秒 1080P 请求为 {"resolution-1080P":4,"seconds":5}。含参考视频或智能时长的请求,seconds 为 30。
示例(价格仅作假设,真实价格以控制台为准)。假设该模型 480P 每秒 $0.05,按默认 1 : 2 : 4,720P 为 $0.10、1080P 为 $0.20,分组倍率为 1:
- 请求
1080P、duration: 5。预扣 0.20 × 5 = $1.00。 - DashScope 返回
usage.SR: 720、output_video_duration: 5,即实际输出低了一档。结算 0.10 × 5 = $0.50,退还 $0.50。 - 如果报告的是
SR: 1080、5 秒,扣费维持 $1.00——结算永远不会超过预扣。
第二个示例:480P、输入 2 秒参考视频、duration: 2。因为有 reference_video,预扣 30 × $0.05 = $1.50;实际输出 2 秒,结算为 2 × $0.05 = $0.10,退还 $1.40。
参数错误在提交前就被拦下:返回 400,不发给上游,也不扣费。
| 状态码 | 错误码 | 含义 |
|---|---|---|
| 400 | invalid_request | prompt 缺失或为空(prompt is required);audio_url 与首/尾帧同时出现(wan3 does not support audio_url together with first/last frame images);prompt 与 media 都为空;metadata 字段类型错误;metadata.model 与解析出的模型不一致(can't change model with metadata) |
| 400 | invalid_request | 参数校验失败——见下面的消息表 |
| 400 | invalid_json | 请求体无法解析 |
| 400 | invalid_seconds | 顶层 duration / seconds 为负或大于 3600(seconds must be between 1 and 3600) |
| 400 | missing_model | 请求体没有 model(model field is required) |
| 400 | task_not_exist | task_id 未知或属于其他账户 |
| 403 | insufficient_user_quota | 余额或 Key 额度不足以覆盖预扣;不会提交 |
| 429 | — | 上游容量耗尽;消息会被替换为 Upstream load is saturated, please try again later |
| 500 | build_request_failed、do_request_failed、invalid_response | 转换失败、上游不可达,或 DashScope 没有返回任务 ID |
| 上游状态码 | ali_api_error | DashScope 在响应体中返回了错误码和消息 |
| 上游状态码 | fail_to_fetch_task | DashScope 拒绝了提交;HTTP 状态码即 DashScope 的状态码 |
Wan 3.0 校验返回的常见 400 消息(原文):
message | 原因 |
|---|---|
invalid duration: 40, wan3 supports -1 or 2-30 | 时长超出 2–30 且不是 -1 |
invalid resolution: 4KP, wan3 supports 480P, 720P, 1080P | 分辨率不在支持档位内(显示的是转大写并补 P 之后的值) |
invalid ratio: 1:2, wan3 supports adaptive, 21:9, 16:9, 4:3, 1:1, 3:4, 9:16 | 比例不在支持列表内 |
invalid seed: 3000000000, wan3 supports -1 or 0-2147483647 | 种子超出 -1 或 0–2147483647 |
invalid size: 1000*1000 | 宽*高 像素尺寸不在表内 |
wan3 does not support audio_url together with first/last frame images | 首尾帧与通过 input.audio_url 传入的参考音频混用 |
wan3 requires prompt or input.media | metadata 合并后既没有 prompt 也没有 media |
can't change model with metadata | metadata.model 与解析出的上游模型不一致 |
convert seconds to int failed: ... | seconds 不是整数字符串 |
seconds must be between 1 and 3600 | 顶层时长过小或过大;-1 请用 metadata.parameters.duration |
提交成功之后出现的失败——审核不通过、素材无法下载、素材组合不合法、输入 + 输出超过 30 秒——不会以 HTTP 错误返回,而是体现在任务记录的 FAILURE 状态和 fail_reason 里,预扣额度会退回。
与 DashScope 官方接口的区别
Section titled “与 DashScope 官方接口的区别”- 接口地址不同。RouteAPI 不提供
/api/v1/services/aigc/video-generation/video-synthesis,把 DashScope SDK 的 Base URL 改成我们的地址是不能直接用的。 - 阿里原生的
input/parameters对象要放在metadata.input/metadata.parameters里;常用参数(prompt、resolution、ratio、size、duration、images、generate_audio)也可以写在顶层,我们会自动映射。 - 返回的
task_id是 RouteAPI 的 ID,不是阿里的任务 ID。阿里的任务 ID 在data.data.output.task_id。 - 提示词智能改写(
prompt_extend)始终开启,无法关闭。 - 旧的按模型图片字段(
img_url、first_frame_url、last_frame_url、audio_url)会被丢弃,只有input.media会发到上游。 - 不支持回调通知,请用轮询查询结果。
- 计费按输出秒数乘分辨率倍率,不适用上游的按次或分档计价。
完整示例脚本
Section titled “完整示例脚本”需要 bash、curl 和 jq。
#!/usr/bin/env bashset -euo pipefail: "${ROUTEAPI_KEY:?set ROUTEAPI_KEY first}"BASE="${ROUTEAPI_BASE:-https://api.routeapi.ai}"AUTH="Authorization: Bearer $ROUTEAPI_KEY"
TASK_ID=$(curl -sS -X POST "$BASE/v1/video/generations" \ -H "$AUTH" -H "Content-Type: application/json" \ -d '{"model":"wan3.0-video","prompt":"An orange cat walking on a rooftop, cinematic lighting","resolution":"480P","ratio":"16:9","duration":2}' \ | jq -er .task_id)
echo "task: $TASK_ID"
for _ in $(seq 1 60); do RESP=$(curl -sS "$BASE/v1/video/generations/$TASK_ID" -H "$AUTH") STATUS=$(printf '%s' "$RESP" | jq -r .data.status) echo "status: $STATUS $(printf '%s' "$RESP" | jq -r .data.progress)"
case "$STATUS" in SUCCESS) echo "billed seconds: $(printf '%s' "$RESP" | jq -r .data.data.usage.output_video_duration)" curl -sSL -o "$TASK_ID.mp4" "$BASE/v1/videos/$TASK_ID/content" -H "$AUTH" echo "saved $TASK_ID.mp4" exit 0 ;; FAILURE) echo "failed: $(printf '%s' "$RESP" | jq -r .data.fail_reason)" exit 1 ;; esac
sleep 15done
echo "timed out waiting for the task"exit 1