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 動画生成 API の使い方 (2026)

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 つ
モデル IDbytedance/seedance-2.0, -fast, -mini
最初のクリップまで約 5 分
結果の取得GET /v1/videos/{id} をポーリングし unsigned_urls[0] を読む

必要なもの

必要なのは 3 つ。ofox をチャットや画像のコールに使っているなら、そのうち 2 つはすでに持っている。

  1. ofox API キー。 ベース URL は https://api.ofox.ai/v1、認証は標準の Authorization: Bearer ヘッダーだ。OpenAI 互換のチャットや画像リクエストに使うのと同じキーで動画ジョブも投げられるので、別のアカウントやベンダー SDK をセットアップする必要はない。
  2. エンドポイント。 すべては POST /v1/videosGET /v1/videos/{id} を通る。API の表面積はこれで全部だ。
  3. モデル ID。 bytedance/seedance-2.0 がフラッグシップだ。text-to-video、image-to-video、video-to-video、同期音声に対応し、4〜15 秒のクリップ、最大 4K まで。bytedance/seedance-2.0-fastbytedance/seedance-2.0-mini は安価なティアで、どちらも 720p が上限だ。

キーは一度だけ設定する:

export OFOX_API_KEY="sk-..."

最初のリクエスト:text-to-video

動画生成は、チャット補完のようなブロッキングコールではない。クリップにはレンダリング時間がかかるので、POST /v1/videos はすぐに 202 Acceptedpolling_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 だけをチェックするポーリングループだ。failedexpired で終わったジョブは決して 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",
})

それ以降はすべて同一だ。202polling_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 キーと、modelpromptdurationresolutionaspect_ratio の JSON ボディを付けて POST https://api.ofox.ai/v1/videos を送ります。202polling_url が返ります。statuscompleted になるまで 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 に到達するのはフラッグシップだけです。

本更新で確認したソース