Seedance 2.0 動画生成 API の使い方 (2026)
Seedance 2.0 API クイックスタート:ofox の 1 キーで POST /v1/videos、completed までポーリングし unsigned_urls[0] を読む。Python と Node のコード、価格は $0.07/s から。
Seedance 2.0 は ByteDance の text-to-video / image-to-video モデルであり、これを呼ぶ最速の方法は ofox 経由だ。1 つの API キー、USD 建て課金、そして 1 つの非同期 REST エンドポイントで済む。モデル ID とプロンプトを付けて POST https://api.ofox.ai/v1/videos を送り、polling_url を受け取り、ステータスが completed になるまでポーリングし、unsigned_urls[0] からクリップを読む。ベンダーごとのアカウントも、個別の SDK も要らない。以下はそのまま動くクイックスタートだ。認証、Python と Node での text-to-video コール、非同期ライフサイクル、画像と参照入力、そしてクリップ 1 本の実際のコストを扱う。
| エンドポイント | POST https://api.ofox.ai/v1/videos(非同期) |
| 認証 | ofox の Bearer キー 1 つ |
| モデル ID | bytedance/seedance-2.0, -fast, -mini |
| 最初のクリップまで | 約 5 分 |
| 結果の取得 | GET /v1/videos/{id} をポーリングし unsigned_urls[0] を読む |
必要なもの
必要なのは 3 つ。ofox をチャットや画像のコールに使っているなら、そのうち 2 つはすでに持っている。
- ofox API キー。 ベース URL は
https://api.ofox.ai/v1、認証は標準のAuthorization: Bearerヘッダーだ。OpenAI 互換のチャットや画像リクエストに使うのと同じキーで動画ジョブも投げられるので、別のアカウントやベンダー SDK をセットアップする必要はない。 - エンドポイント。 すべては
POST /v1/videosとGET /v1/videos/{id}を通る。API の表面積はこれで全部だ。 - モデル ID。
bytedance/seedance-2.0がフラッグシップだ。text-to-video、image-to-video、video-to-video、同期音声に対応し、4〜15 秒のクリップ、最大 4K まで。bytedance/seedance-2.0-fastとbytedance/seedance-2.0-miniは安価なティアで、どちらも 720p が上限だ。
キーは一度だけ設定する:
export OFOX_API_KEY="sk-..."
最初のリクエスト:text-to-video
動画生成は、チャット補完のようなブロッキングコールではない。クリップにはレンダリング時間がかかるので、POST /v1/videos はすぐに 202 Accepted と polling_url を返し、ジョブが終端状態に達するまでその URL をポーリングする。モードは送るフィールドから推論される。画像フィールドがなければ text-to-video だ。
以下は Python での完全な往復だ。ジョブをサブミットし、まともな間隔でポーリングし、unsigned_urls[0] からクリップを取り出す。
import os, time, requests
BASE = "https://api.ofox.ai/v1"
HEAD = {"Authorization": f"Bearer {os.environ['OFOX_API_KEY']}"}
TERMINAL = {"completed", "failed", "cancelled", "expired"}
job = requests.post(f"{BASE}/videos", headers=HEAD, json={
"model": "bytedance/seedance-2.0",
"prompt": "A red kayak cuts through morning fog on a still lake, slow dolly forward.",
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9",
})
job.raise_for_status() # 202 Accepted
task_url = job.json()["polling_url"]
while True:
task = requests.get(task_url, headers=HEAD).json()
if task["status"] in TERMINAL: # break on ALL four terminal states
break
time.sleep(2) # poll every 1-2s, not in a tight loop
if task["status"] == "completed":
print("clip:", task["unsigned_urls"][0]) # there is no output_url field
print("billed:", task["usage"]["video_cost"], "USD",
"for", task["usage"]["video_seconds"], "s")
else:
print("job ended as:", task["status"])
Node で fetch を使った同じ形:
const BASE = "https://api.ofox.ai/v1";
const HEAD = {
Authorization: `Bearer ${process.env.OFOX_API_KEY}`,
"Content-Type": "application/json",
};
const TERMINAL = ["completed", "failed", "cancelled", "expired"];
const job = await fetch(`${BASE}/videos`, {
method: "POST",
headers: HEAD,
body: JSON.stringify({
model: "bytedance/seedance-2.0",
prompt: "A red kayak cuts through morning fog on a still lake, slow dolly forward.",
duration: 8,
resolution: "1080p",
aspect_ratio: "16:9",
}),
});
const { polling_url } = await job.json(); // 202 Accepted
let task;
do {
await new Promise((r) => setTimeout(r, 2000)); // poll every 1-2s
task = await (await fetch(polling_url, { headers: HEAD })).json();
} while (!TERMINAL.includes(task.status));
if (task.status === "completed") {
console.log("clip:", task.unsigned_urls[0]); // not output_url
console.log("billed:", task.usage.video_cost, "USD");
}
初めて呼ぶ人がつまずく点が 2 つある。1 つ目は resp["output_url"] に手を伸ばすことだ。これは存在せず、Python では None、Node では undefined を返す。クリップは unsigned_urls[0] にある。2 つ目は completed だけをチェックするポーリングループだ。failed や expired で終わったジョブは決して completed にならないので、他の終端状態を無視するループは永遠に回り続ける。4 つすべてで抜けること。
非同期ライフサイクルの扱い
Seedance のジョブは、決まった状態の集合を移っていく。3 つは一時的、4 つは終端だ。processing という状態は存在しないので、それをチェックしてはいけない。
| ステータス | フェーズ | すべきこと |
|---|---|---|
pending | 受理、未キュー | 1〜2s ごとにポーリング継続 |
queued | レンダリング待ちでキュー | 1〜2s ごとにポーリング継続 |
in_progress | レンダリング中 | 1〜2s ごとにポーリング継続 |
completed | 完了、URL 付与 | unsigned_urls[0] からダウンロード |
failed | 生成エラー | エラーを読み、再試行またはフォールバック |
cancelled | 自分でキャンセルした | ポーリング停止 |
expired | タスク失効 | 再サブミット |
ポーリングの間隔は重要だ。GET /v1/videos/{id} は 1 秒に 1 回より速くしないこと。おおよそ 1〜2 秒ごとがちょうどいい。タイトループで叩き続けてもクォータを浪費するだけで、何も早くはならない。クリップはどのみち上流でレンダリングされているからだ。
結果 URL には賞味期限があるので、completed をダウンロードの合図とみなそう。unsigned_urls はジョブ完了の約 24 時間後に失効する。mirror_urls は永続的だが、各署名付きリンクはそれぞれ固有の TTL を持つ。実践的には、ステータスが completed に切り替わったら、API の URL を保存して後でクライアントに配信するのではなく、unsigned_urls[0] をすぐに自分のバケット(S3、R2、GCS)に取り込むこと。
本番では、ポーリングスレッドの代わりに webhook を使いたいのが普通だ。作成時に callback_url を渡すと、ジョブが終端状態に達したときに ofox が HMAC 署名付きのペイロードを POST する。アドレスは公開 HTTPS でなければならず、プライベート・ループバック・その他到達不能なホストはサブミット時に 400 invalid_callback_url で拒否される。ポーリングと webhook は排他ではないので、ハッピーパスには webhook、バックストップに緩いポーリングを併用するのがよくあるパターンだ。
ジョブを途中で止めたい? DELETE /v1/videos/{id} でキャンセルでき、タスクは cancelled に落ち着く。
image-to-video と参照画像
静止画をアニメートするにも、参照フレームで生成を操舵するにも、エンドポイントを切り替える必要はない。同じ POST /v1/videos、同じポーリングだ。リクエストのモードは、どのフィールドを含めるかから推論される。
- 画像フィールドなしなら text-to-video、上記のコールだ。
frame_imagesなら image-to-video。開始フレーム 1 枚の URL を渡すか、その間を補間するために最初と最後のフレームを渡す。input_referencesなら参照ガイド付き生成で、アイデンティティ・スタイル・製品の見た目を固定する画像を与える。
開始フレームからの image-to-video:
job = requests.post(f"{BASE}/videos", headers=HEAD, json={
"model": "bytedance/seedance-2.0",
"prompt": "The logo tilts up and catches a rim light, subtle rotation.",
"frame_images": ["https://your-cdn.com/first-frame.png"],
"duration": 8,
"resolution": "1080p",
"aspect_ratio": "16:9",
})
それ以降はすべて同一だ。202、polling_url、同じステータス集合、そして unsigned_urls[0] のクリップ。音声は 3 ティアすべてで生成されるので、欲しい音をプロンプトで名指しすること。さもなければモデルが推測したものを引き継ぐことになる。
価格:定額ではなく解像度別
これは多くの人が誤解する数字だ。カタログで Seedance 2.0 の横に見える from $0.07/s は 480p の下限であって、定額ではない。価格はリクエストする解像度に応じて上がるので、クリップの実際のコストは、あなたの解像度における 1 秒あたりレート × クリップ尺だ。以下がフラッグシップの text-to-video レートカードだ:
| 解像度 | bytedance/seedance-2.0(text-to-video) |
|---|---|
| 480p | $0.07/s |
| 720p | $0.16/s |
| 1080p | $0.34/s |
| 4K | $1.37/s |
課金は出力秒あたりで、完了レスポンスが正確な請求額を usage.video_cost で教えてくれる。だから 8 秒の 1080p クリップは 8 x $0.34 = $2.72、同じクリップを 4K にすると 8 x $1.37 = $10.96 だ。video-to-video は各解像度で text-to-video より 1 秒あたり少し高く、詳細はモデルページに全部書いてある。
安価なティアは解像度をコストと引き換えにし、どちらも 720p が上限だ。bytedance/seedance-2.0-fast は 480p で $0.06/s、720p で $0.13/s、bytedance/seedance-2.0-mini は 480p で $0.04/s、720p で $0.08/s。出力の大半がどのみち 720p にダウンスケールされるフィードに載るなら、$0.08/s の Mini が 3 つの中で最も安い 720p レートだ。
3 ティアすべてが同じエンドポイントを共有し、違うのは model 文字列だけなので、ドラフトは Mini にルーティングし、フラッグシップはマスター用に取っておける。Fast が Mini に対するプレミアムに見合うのはいつかを含む完全な一騎打ちは Seedance 2.0 ティア比較 を、解像度別の完全なマトリクスは Seedance 2.0 モデルページ を読んでほしい。
1 つのキーで、あらゆる動画モデル
このクイックスタートが短いのは、ofox が動画スタック全体を 1 つの認証と 1 つのスキーマにまとめているからだ。パターンはすでに手にしている。/v1/videos にサブミットし、ポーリングし、ダウンロードする。モデルの差し替えは文字列 1 つの変更だ。
すでに持っているキーで Seedance 2.0 を生成する。 ofox 動画 API を始める:1 つのキー、USD 建て課金、レンダリングした秒数だけ支払い、ベンダーごとのサインアップは不要。
あるクリップに Seedance が合わないなら、同じエンドポイントでカタログの残りにも手が届く。Alibaba の Wan は最小 2 秒から始まり、Seedance の下限は 4 秒だ。そのトレードオフは Seedance 2.0 vs Wan の比較 で扱っている。すべてのオプションパラメータを含む正確なリクエスト・レスポンスフィールドは ofox 動画 API リファレンス にある。
FAQ
Seedance 2.0 API はどう呼び出しますか?
Bearer の ofox キーと、model、prompt、duration、resolution、aspect_ratio の JSON ボディを付けて POST https://api.ofox.ai/v1/videos を送ります。202 と polling_url が返ります。status が completed になるまで GET /v1/videos/{id} を 1〜2 秒ごとにポーリングし、unsigned_urls[0] からクリップを読みます。
output_url を読むと動画 URL が空なのはなぜですか?
output_url というフィールドは存在しません。クリップは unsigned_urls(配列なので unsigned_urls[0] を使う)か mirror_urls にあります。resp["output_url"] を読むと毎回 None が返ります。
Seedance 2.0 の結果 URL はどれくらい有効ですか?
unsigned_urls は完了の約 24 時間後に失効します。mirror_urls は永続的ですが、各署名付きリンクはそれぞれ固有の TTL を持ちます。ステータスが completed になったらすぐにファイルをダウンロードしてください。
Seedance 2.0 API の料金はいくらですか? 定額ではなく、解像度に応じた出力秒あたりの課金です。フラッグシップの text-to-video は 480p で $0.07/s、720p で $0.16/s、1080p で $0.34/s、4K で $1.37/s です。8 秒の 1080p クリップは $2.72 です。
Seedance 2.0 は画像から動画を生成できますか?
はい。image-to-video には frame_images、参照ガイド付き生成には input_references を渡します。モードはフィールドから推論され、画像がなければ text-to-video です。
最も安い Seedance 2.0 モデルはどれですか?
bytedance/seedance-2.0-mini で、480p が $0.04/s、720p が $0.08/s です。-fast と同様に 720p が上限です。1080p と 4K に到達するのはフラッグシップだけです。
