コンテンツにスキップ

Wan

Wan(通義万相)は Alibaba の動画生成ファミリーで、DashScope チャネルから提供されます。タスクは他の動画モデルと同じエンドポイントで送信します(タスクの作成、タスクの取得)。このページでは Wan 3.0 アダプターを一通り説明します。読み取るリクエストフィールド、DashScope リクエストの組み立て方、素材のルール、タスクレコードの読み方、秒単位の課金の計算方法です。

動画生成は非同期です。送信して task_id を保持し、10〜15 秒ごとにポーリングし、SUCCESS になったらダウンロードします。

モデル ID解像度長さ備考
wan3.0-video480P、720P、1080P2〜30 秒、または -1(スマート)標準版。テキストから動画、最初と最後のフレーム、マルチ参照素材
wan3.0-video-prime480P、720P、1080P2〜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 アダプターの処理
promptinput.prompt として送信されます。すべてのタスクリクエストと同様、空の prompt は送信前に 400 で拒否されます
image / imagesimage が設定されていればそれを最初のフレームに、なければ images の最初の空でない要素を最初のフレームにします。最後のフレームは images の 2 番目に空でない要素です。3 枚目以降は無視されます
input_reference単一画像の省略形で、images を 1 つの URL に置き換えます。最初のフレームは引き続きトップレベルの image が優先されます
resolutionparameters.resolution として送信され、大文字化され、必要なら P が付きます
ratioparameters.ratio として送信され、小文字化されます
sizeresolution と ratio に畳み込まれてから破棄されます。1920x1080 と 1920*1080 の両方を受け付け、対応表にない * 形式は 400、720p のような階層のみの値は解像度として使われます
durationparameters.duration として送信されます。省略時は 5 になります
secondsduration がない場合、整数の長さとして解釈されます
generate_audioparameters.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 に入れます。

フィールド型値説明
modelstringwan3.0-video、wan3.0-video-prime必須
promptstring—必須で空不可。参照モードでは素材を「image 1」「video 1」「audio 1」で指定します
resolutionstring480P、720P、1080P大文字小文字を問わず、末尾の P は省略可。既定は 1080P
ratiostringadaptive、21:9、16:9、4:3、1:1、3:4、9:16大文字小文字を問いません。省略時は DashScope が adaptive を適用
sizestring1280*720、1280x720、720presolution と ratio に畳み込まれて破棄されます。アダプターの対応表にあるサイズのみ受け付けます
durationinteger2〜30出力秒数。既定は 5。負の値や 3601 以上は共通のタスク検証で拒否されます。-1 のスマート長さは metadata.parameters でのみ使えます
secondsstring整数の文字列duration がない、または 0 のときに代わりに使われます。整数でない場合は 400
imagestringURL単一の最初のフレーム画像。最初のフレームはこれが優先され、次に images を見ます
imagesarrayURL の配列1 枚なら最初のフレーム、2 枚ならその順に最初と最後のフレーム
input_referencestringURLimages を 1 つの最初のフレーム URL に置き換えます。最初のフレームはトップレベルの image が優先されます
generate_audiobooleantrue / falseparameters.audio として送信され、明示的な false は false として転送されます
metadataobjectDashScope の 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 は DashScope の input / parameters オブジェクトに対応します。以下のキーはすべて任意です。

metadata のキー型説明
input.mediaarray{"type", "url"} 項目からなる素材リスト。指定するとトップレベルの画像は使われません
input.promptstring上流へ送る際にトップレベルの prompt を置き換えますが、共通検証はトップレベルの prompt を依然として要求します
input.audio_urlstringreference_audio を追加する省略記法
input.negative_promptstringネガティブプロンプト
input.templatestringDashScope のエフェクトテンプレート。そのまま転送されます
parameters.resolutionstringトップレベルの resolution と同じ
parameters.ratiostringトップレベルの ratio と同じ
parameters.sizestringトップレベルの size と同じ
parameters.durationinteger-1 でスマート長さ、それ以外は 2〜30
parameters.audiobooleangenerate_audio と同じ
parameters.seedinteger-1 または 0〜2147483647。0 は明示値として保持されます。同じシードでも結果が完全に一致する保証はありません
parameters.watermarkbooleanプロバイダー側のウォーターマーク。既定はオフ
parameters.prompt_extendboolean受け付けますが効果はありません。プロンプト書き換えは常に有効です(下記参照)

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 項目を追加します。これら 4 つの旧フィールドは 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 以下、20 MB 以下。動画は mp4 / mov、各 1〜15 秒、16 fps 以上、各辺 240〜4096 ピクセル、100 MB 以下。音声は wav / mp3、各 1〜15 秒、15 MB 以下。
  • 最初/最後のフレームモードと参照素材モードは排他です。1 つの media 配列でフレームと reference_* 項目を混在させると上流で拒否され、タスクは返金されます。
  • reference_image、reference_video、reference_audio は自由に組み合わせられます。
  • プロンプトでは素材を「image 1」「video 1」「audio 1」のように、media 内の同じ種類の出現順で指定します。

2 つのルールは送信前にローカルで検査されるため、上流にも残高にも到達しません。

  • metadata.input.audio_url と first_frame または last_frame 項目を同時に指定すると 400 とメッセージ wan3 does not support audio_url together with first/last frame images が返ります。検査対象は input.audio_url のみです。media に直接 reference_audio 項目をフレームと並べて書いた場合は DashScope が拒否します(タスク FAILURE、返金)。
  • metadata マージ後、prompt が空で media 配列も空のリクエストは 400(wan3 requires prompt or input.media)になります。実際には共通のタスク検証が空の prompt を既に拒否するため、prompt は常に必須です。

prompt と動画パラメータだけを送ります。

Terminal window
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
}'

トップレベルの images 配列に画像を入れます。1 枚なら最初のフレーム、2 枚ならその順に最初と最後のフレームです。

Terminal window
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 があると、トップレベルの画像フィールドは無視されます。

Terminal window
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 秒分を予約します。最終的な出力長がその時点では分からないためです。課金を参照してください。

どちらも元動画を reference_video として渡し、意図をプロンプトで表現します。

  • 編集 — 例えば「video 1 を全体としてクレイアニメ調に変換する」。出力が元動画のアスペクト比を保つよう ratio: "adaptive" を送ります。
  • 延長 — 例えば「video 1 を前方に延長し、人物の動きとカメラのスタイルを保つ」。ratio は必ず adaptive です。duration は元動画の長さに延長分を足した値にします。5 秒の動画を 2 秒延長するなら 7 です。-1 にしてモデルに決めさせることもできます。

動画入力がある場合、元動画の長さと出力の長さの合計は 30 秒を超えられません。この制限は DashScope が適用し、破ると失敗して返金されます。

Terminal window
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 秒延長するには、プロンプトと長さを変えるだけです。

Terminal window
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 で拒否します。

Terminal window
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 秒分を予約し、完了時に実際の出力長で精算して差額を返金します。

Terminal window
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_idDashScope のタスク ID。外側の data.task_id とは異なります
data.data.output.video_urlプロバイダーの動画 URL。外側の data.result_url と同じ値
data.data.output.orig_promptDashScope が受け取ったプロンプト
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 に一部のフィールドしかないことがあります。完了判定は usage の有無ではなく data.status で行ってください。

ステータス:NOT_START と QUEUED はポーリング継続、IN_PROGRESS は生成中、SUCCESS はダウンロード、FAILURE は fail_reason を確認——予約額は既に返金済みです。

data.result_url は Alibaba がホストするファイルを指します。この URL は一時的なもので、Alibaba が独自のスケジュールで失効させるため早めにダウンロードしてください。RouteAPI 経由でストリーミングすれば URL の残存期間に依存しません。

Terminal window
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 のステータスタスクレコードのステータス
PENDINGQUEUED
RUNNINGIN_PROGRESS
SUCCEEDEDSUCCESS
FAILED、CANCELED、UNKNOWNFAILURE

Wan 3.0 は出力秒数単位で課金され、解像度で倍率がかかります。コンソールの価格は 480P の毎秒単価で、他の階層はその単価にモデルの解像度倍率を掛けた値です。既定は 480P : 720P : 1080P = 1 : 2 : 4 です。

予約と最終請求は同じ形で計算されます。

base quota = model price (per 480P second) × group ratio
reserved quota = base quota × reserved seconds × resolution ratio
settled 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 クォータが必要です。不足すると 403 insufficient_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 だとします。

  1. 1080P、duration: 5 をリクエスト。予約は 0.20 × 5 = $1.00。
  2. DashScope が usage.SR: 720、output_video_duration: 5 を返し、出力が 1 階層低かった場合。精算は 0.10 × 5 = $0.50 で、$0.50 が返金されます。
  3. SR: 1080 で 5 秒と報告されていれば、請求は $1.00 のままです。精算が予約を超えることはありません。

2 つ目の例:480P、2 秒の元動画、duration: 2。reference_video があるため予約は 30 × $0.05 = $1.50。実際の出力は 2 秒なので、2 × $0.05 = $0.10 に精算され、$1.40 が返金されます。

パラメータの誤りは送信前に検出されます。400 を返し、上流へ送られず、課金もされません。

ステータスコード意味
400invalid_requestprompt の欠落または空(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)
400invalid_requestパラメータ検証の失敗。下のメッセージ表を参照
400invalid_json本文を解析できない
400invalid_secondsトップレベルの duration / seconds が負、または 3600 超(seconds must be between 1 and 3600)
400missing_model本文に model がない(model field is required)
400task_not_existtask_id が未知、または別アカウントのもの
403insufficient_user_quota残高または Key クォータが予約額に足りない。送信されません
429—上流の容量が枯渇。メッセージは Upstream load is saturated, please try again later に置き換えられます
500build_request_failed、do_request_failed、invalid_response変換失敗、上流に到達できない、または DashScope がタスク ID を返さない
上流ステータスali_api_errorDashScope がレスポンス本文でエラーコードとメッセージを返した
上流ステータスfail_to_fetch_taskDashScope が送信を拒否。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.mediametadata マージ後に prompt も media もない
can't change model with metadatametadata.model が解決された上流モデルと異なる
convert seconds to int failed: ...seconds が整数文字列でない
seconds must be between 1 and 3600トップレベルの長さが範囲外。-1 は metadata.parameters.duration を使う

送信後の失敗——審査拒否、素材のダウンロード不可、素材の組み合わせ不正、入力 + 出力が 30 秒超——は HTTP エラーになりません。タスクレコードの FAILURE と fail_reason として現れ、予約額は返金されます。

  • エンドポイントが異なります。RouteAPI は /api/v1/services/aigc/video-generation/video-synthesis を公開しておらず、DashScope SDK のベース URL を当社に向けても動作しません。
  • DashScope ネイティブの input / parameters オブジェクトは metadata.input / metadata.parameters に入れます。共通パラメータ(prompt、resolution、ratio、size、duration、images、generate_audio)はトップレベルにも書け、自動でマッピングされます。
  • 返る task_id は RouteAPI の ID で、DashScope のものではありません。DashScope の ID は data.data.output.task_id にあります。
  • プロンプト書き換え(prompt_extend)は常に有効で、無効にできません。
  • 旧来のモデル別画像フィールド(img_url、first_frame_url、last_frame_url、audio_url)は破棄され、input.media だけがプロバイダーに届きます。
  • コールバック通知には対応していません。タスクエンドポイントをポーリングしてください。
  • 課金は出力秒数に解像度倍率を掛けたもので、プロバイダーのリクエスト単位や段階的な課金は適用されません。

bash、curl、jq が必要です。

#!/usr/bin/env bash
set -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 15
done
echo "timed out waiting for the task"
exit 1