Seedance 2.0 API は、最初のレスポンスで完成動画を返す同期 API ではありません。作成リクエストで非同期タスクを開始し、返ってきた task ID を保存し、ポーリングまたは callback で状態を追い、succeeded になったら content.video_url を自分のストレージへコピーする流れです。
BytePlus ModelArk の国際ルートでは、作成 endpoint は https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks です。Seedance 2.0 の model ID は dreamina-seedance-2-0-260128 と dreamina-seedance-2-0-fast-260128 です。中国リージョンの Volcengine Ark を使う場合は endpoint と model ID が異なるため、dreamina-* と doubao-* を同じ設定に混ぜないでください。

まず 1 つのタスクを送信する
生成を開始するのは create call だけにします。送信前に route、model、prompt、参照素材、ratio、resolution、duration、audio、callback URL を検証します。レスポンスを受け取ったら provider task ID を自分の job ID、request hash、user ID、出力設定と一緒に保存します。
bashcurl -X POST "https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks" \ -H "Authorization: Bearer $ARK_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "dreamina-seedance-2-0-260128", "content": [ { "type": "text", "text": "A quiet product demo shot, slow camera move, clean studio light" } ], "ratio": "16:9", "resolution": "720p", "duration": 5, "generate_audio": false, "return_last_frame": true, "callback_url": "https://example.com/webhooks/seedance" }'
create request が timeout しても、すぐに 2 回目の生成を送らないでください。まず request hash で自分の job を探します。provider task ID が保存済みなら、その ID のポーリングを再開します。
ポーリングまたは callback で状態を進める
Seedance の状態は進捗率ではなく、キューの状態です。
| 状態 | 意味 | 次の処理 |
|---|---|---|
queued | 受理済み | backoff して待つ |
running | 生成中 | ポーリング継続 |
succeeded | 出力完了 | content.video_url をコピー |
failed | provider 側で失敗 | code と message を保存 |
expired | 実行期限切れ | 再実行可否を判断 |
cancelled | キュー内で取消 | ポーリング停止 |
bashcurl -X GET \ "https://ark.ap-southeast.bytepluses.com/api/v3/contents/generations/tasks/$TASK_ID" \ -H "Authorization: Bearer $ARK_API_KEY"
callback は速い更新に向いていますが、修復用 polling は残してください。デプロイ中、署名検証の不具合、ネットワーク障害で callback が失われることがあります。
結果をすぐ保存する
成功レスポンスの content.video_url は一時的な MP4 URL です。公式レスポンス契約では生成動画は 24 時間後に削除されるため、ユーザー向けの恒久 URL として使わず、自分の object storage にコピーします。
tsasync function saveSeedanceVideo(job, task) { const url = task.content?.video_url; if (!url) throw new Error("Seedance succeeded without video_url"); const res = await fetch(url); if (!res.ok) throw new Error(`download failed: ${res.status}`); await storage.putObject({ key: `seedance/${job.id}/output.mp4`, body: res.body, contentType: "video/mp4", }); }
provider の payload も保存します。model、status、seed、ratio、resolution、duration、generate_audio、usage.total_tokens は、サポート、課金確認、再現調査に必要です。

参照素材は content に入れる
Seedance 2.0 の参照素材は単なる添付ファイルではありません。content 配列が生成モードを決めます。first-frame は first_frame、first-and-last-frame は first_frame と last_frame、multimodal reference は reference_image、reference_video、reference_audio を使います。
json{ "model": "dreamina-seedance-2-0-260128", "content": [ { "type": "text", "text": "Use [image 1] as the product reference and keep the motion minimal." }, { "type": "image_url", "image_url": { "url": "https://cdn.example.com/reference-product.webp" }, "role": "reference_image" } ], "ratio": "16:9", "duration": 5, "generate_audio": false }
送信前に形式、サイズ、duration、権利を検証してください。audio だけの入力は避け、少なくとも image または video reference と組み合わせます。実在人物を扱う場合は、API 呼び出し前に同意と権利確認を入れます。
リトライを冪等にする
最も高くつくバグは、同じ job で有料生成を複数回作ることです。route、model ID、正規化した prompt、reference URL または asset ID、出力パラメータ、user ID から request hash を作り、同じ hash の job があれば新規 create を送らず既存 job を返します。

| 操作 | リトライ方針 |
|---|---|
| task ID 保存前の create | job と hash を確認してから再試行 |
| task ID 保存後の create | 再送せず polling に戻る |
| polling | backoff 付きで再試行 |
| callback | 冪等な状態更新にする |
| download | 一時 URL が有効な間だけ再試行 |
| failed task | error を分類してから判断 |
FAQ
Seedance 2.0 API は同期 API ですか?
いいえ。create は task ID を返し、MP4 は後で content.video_url に出ます。
polling と callback のどちらを使うべきですか?
両方です。callback は速い更新、polling は取りこぼしの修復に使います。
video_url は長期保存できますか?
恒久 URL としては使えません。生成動画は 24 時間後に削除されるため、すぐ自分のストレージに保存してください。
create が timeout したら?
request hash で既存 job を探し、provider task ID があれば polling を再開します。ID がない場合だけ同じ job で create を再試行します。
