Seedance 2.5 の first/last frame 実測:終端誤差 5.4、2.0 Mini は 35.9

両端の画像を渡すと Seedance 2.5 は指定した終端に着地します。480p の終端誤差は 5.4、2.0 Mini は 35.9。aspect_ratio を送ると 400、480p は $0.11/秒で課金されました。

Seedance 2.5 の first/last frame 実測:終端誤差 5.4、2.0 Mini は 35.9

Seedance 2.5 は最終フレームをヒントではなく目的地として扱います。 ショットの両端を渡すと、指定したほうに実際に着地します。2.0 Mini がやってくれなかったのは、まさにこれです。

エンドポイント: POST /v1/videos  ->  202 + polling_url
フィールド:     frame_images[]、要素ごとに frame_type first_frame / last_frame
比率のルール:   2.5 のフレームジョブで aspect_ratio は 400。省くか adaptive。
2.0 も同じ?:   違う。2.0-mini は frame_images + aspect_ratio を受理。
終端フレーム誤差(0〜255 の平均絶対差、小さいほど近い):
                 Seedance 2.5 720p     2.0
                 Seedance 2.5 480p     5.4
                 Seedance 2.0 Mini    35.9
                 無関係な2枚          39.0(天井)
課金:           480p $0.11/秒、720p $0.24/秒、text-to-video の行
計測:           2026-08-24、構成ごとに 5 秒クリップ1本

最終更新 2026-08-24。以下の数値はすべてその日に ofox 経由の POST /v1/videos で取得したものです。動画モデルのルーティングは変わるので、検証表を自分のコードに写す前に4つのエラーケースを再実行してください。

first frame と last frame の渡し方

frame_images に2要素、それぞれ frame_type を付ける。 モードの切り替えスイッチはなく、エンドポイントがボディから image-to-video を推測します。

import base64, json, requests

def data_uri(path):
    return "data:image/jpeg;base64," + base64.b64encode(open(path, "rb").read()).decode()

body = {
    "model": "bytedance/seedance-2.5",
    "prompt": "The woman stops walking on the rain-slicked street, turns toward the "
              "camera, and the shot pushes in to her face. Hand-painted 2D animation style.",
    "duration": 5,
    "resolution": "480p",
    # ここで aspect_ratio を送らないのは意図的。次節を参照
    "frame_images": [
        {"type": "image_url", "image_url": {"url": data_uri("wide.jpg")},  "frame_type": "first_frame"},
        {"type": "image_url", "image_url": {"url": data_uri("close.jpg")}, "frame_type": "last_frame"},
    ],
}

r = requests.post("https://api.ofox.io/v1/videos", json=body,
                  headers={"Authorization": "Bearer YOUR_OFOX_API_KEY"})
print(r.status_code, r.json())   # 202 {'id': ..., 'status': 'queued', 'polling_url': ...}

data URI が通るのは、聞こえる以上に効きます。公開画像ホストを用意しなくても first-last-frame 生成を試せるということです。あとは polling_url を終了状態までポーリングするだけですが、そこには固有の落とし穴があるので、ループを書く前に目を通しておく価値があります。

プロンプトはここでも仕事をします。固定された2枚の画像に挟まれた飾りではなく、途中で何が起きるか、そこに何回のカメラワークを使うかを決めます。

本当に最終フレームに着地するのか

します。しかも 2.0 Mini との差は微妙ではありません。 同じ2枚、同じプロンプト、同じ尺、同じ日。

入力フレームと出力フレームを並べた比較グリッド。Seedance 2.5 は指定した冒頭の街並みと指定した終端のクローズアップを両方再現し、Seedance 2.0 Mini はまったく別の人物で終わっている

数値にするため、各クリップから0フレーム目と最終フレームを取り出し、フレームと元画像の両方を 256x144 にリサイズして、チャンネルごとの平均絶対差を 0〜255 スケールで取りました。小さいほど近いということです。

実行冒頭フレーム誤差終端フレーム誤差課金
Seedance 2.5、720p1.82.0$1.20
Seedance 2.5、1080p1.83.1$2.40
Seedance 2.5、480p3.05.4$0.55
Seedance 2.0 Mini、480p9.535.9$0.10
Seedance 2.0 Mini、480p、ratio なし9.637.1$0.10
参照:無関係な2枚38.639.0該当なし

最初に読むべきは最終行です。互いに何の関係もない2枚がおよそ 39。Mini の終端は 35.9、つまり自分の好きな場所で終わったということです。雨の色調は同じ、人物は別、フレーミングも別。冒頭フレームは話が違い、両モデルともしっかり押さえています。これは 2.0 系で見えていた挙動、つまり冒頭は守られ終端は流れるという観察と一致します。

この上に何か作る前に注意が2つ。各構成は1回の実行であって分布ではないので、順序を知見として、小数はサンプル1点として扱ってください。もう1つ、この差分指標は意図的に粗いものです。構図として正しいのに2フレーム早く着いた終端も減点します。その粗さがあるからこそ 35.9 は説得力を持ちます。これほど鈍い指標で無関係な2枚に迫る値が出るのは、実際に遠いということです。

なぜ 2.5 のフレームジョブで aspect_ratio が 400 になるのか

比率が first frame の画像から導出されるため、送ること自体が冗長ではなくエラーだからです。

POST /v1/videos  {model: bytedance/seedance-2.5, resolution: 480p,
                  aspect_ratio: "16:9", frame_images: [first, last]}

400 invalid_request
"The parameter ratio specified in the request is not valid. For first-frame or
 first-last-frame generation, the output ratio follows the first-frame image."

引っかかりやすい点は、こちらの first frame 画像がちょうど 1280x720 で、送った 16:9 は正しかったのに、それでも拒否されることです。API はあなたの値を画像と突き合わせているのではなく、このモードでは値を受け取ること自体を拒んでいます

ここから3つのことが導かれ、いずれも推測ではなく計測です。

リクエスト結果
2.5 + frame_images + aspect_ratio: "16:9"400、ratio not valid
2.5 + frame_images + aspect_ratio: "adaptive"202、出力 854x480
2.5 + frame_images、フィールド省略202、720p で 1280x720
2.5 の text-to-video + aspect_ratio: "16:9"、フレームなし202
2.0 Mini + frame_images + aspect_ratio: "16:9"202、出力 864x496

つまりこの制限は 2.5 のフレーム系タスク固有です。動画生成一般の規則でも、モデル全体の規則でも、ゲートウェイの規則でもありません。Seedance 2.0 に対して何か月も動いていたコードが、誰かがモデル ID を 2.5 に書き換えた日から 400 を返し始め、しかもエラーメッセージは誰も触っていないパラメータの話をします。

ByteDance はこれを明記しています。Seedance 2.5 プロンプトガイドはタスクをロックとアンロックに分け、「編集、first and last frames、延長」をロック側に置き、ロックとは「出力動画のアスペクト比、場合によっては尺が固定される」ことだと説明します。同じページには 2.0 の結果を説明する一文もあります。「Seedance 2.0 はこの区別をしない。」

frame_images のバリデータは他に何を弾くか

4つの形、すべて上流に行く前に捕捉されます。 どれも1秒ほどで返り、費用はかかりません。

送ったものHTTPメッセージ
2要素とも first_frame400frame_images: at most one first_frame and one last_frame
last_frame のみ400frame_images: last_frame requires a first_frame
frame_type: "start_frame"400frame_images[0]: frame_type must be first_frame or last_frame
frame_imagesinput_references を同時指定400frame_images and input_references are mutually exclusive

3つ目に添字付きのパスが入っている点に注目してください。ループでリクエストボディを生成しているとき、frame_images[0] はどの要素を見ればよいかを直接教えてくれます。ほとんどの動画 API はここまで返しません。

ofox の動画エンドポイントへの5つの POST がそれぞれ異なるエラーコードの HTTP 400 で拒否され、最後に ffprobe の出力が 480p と 720p のクリップを h264、1080p を hevc として並べているターミナル画面

5つの拒否はすべて Seedance 2.5 への実リクエストです。下部の ffprobe 行は実際に生成された3本で、1080p のコーデック変化はそこに出ています。

設計上いちばん効くのは2つ目のルールです。last frame だけのモードは存在しないので、既知の画像で終わらせたいパイプラインは、どこから始まるかも決めなければなりません。終わりだけが重要なら、それらしい冒頭の静止画を先に作って2枚まとめて渡してください。

image-to-video のクリップは実際いくらか

その解像度の text-to-video の行で課金されます。 モデルページは解像度とモードで値付けしていて image-to-video の行がないため、$0.568/秒 の「その他の組み合わせ」に落ちるのではという不安が自然に湧きます。落ちません。

解像度モデルページ text-to-video5 秒フレームジョブの実課金換算
480p$0.11/秒$0.55$0.11/秒
720p$0.24/秒$1.20$0.24/秒
1080p$0.48/秒$2.40$0.48/秒

3解像度、3回とも一致。ファイルは 854x480、1280x720、1920x1080 で返り、いずれも 24 fps、32 kHz の AAC トラック付きでした。尺はちょうど 5 秒ではなく 5.04 秒になるので、自前の計算ではなく usage.video_seconds で請求してください。

比較として、同じリクエストを bytedance/seedance-2.0-mini の 480p に投げると $0.10 でした。終端フレームを誰も検品しないスループット重視の仕事で Mini が正解であり続ける理由がこれです。5.5 倍安く、そしてこのタスクでは差がはっきり見えます。

Seedance 2.5 はどの解像度を受け付けるか

説明文ではなく料金表に聞いてください。 モデルページの説明文は現在 480p または 720p と書いていますが、同じページの料金表には text-to-video と video-to-video の 1080p 行があり、1080p の first-last-frame ジョブは実際に完走しました。

情報源主張
モデルページ説明文480p または 720p、既定は 720p
モデルページ料金表480p / 720p / 1080p の行、1080p の text-to-video は $0.48/秒
実 API、1080p の first-last-frame受理、176.2 秒で完了、$2.40 課金

解像度の階層が開いた直後の数週間はこの種の食い違いが普通に起きます。そして解像度フィールドは検証がいちばん安い対象です。リクエストを送ってステータスコードを読むだけ。拒否は即時で無料です。

1080p では、ページのどこにも書かれていない変化が1つ起きます。ファイルが HEVC で返るのです。480p と 720p の出力は H.264 でした。ストリームコピーで連結する、あるいはブラウザにそのまま配信するなら、コーデックが混ざったバッチは事故になります。モデルから推測せず、ファイルのコーデックを確認してください。

尺は世代間で変わったもう1つの軸です。2.5 は 4〜30 秒、2.0 系は 15 秒まで。そして 30 秒のクリップにはプロンプト側におよそ10拍分の動きが要ります。足りないとモデルは1つの瞬間を10秒に引き伸ばします。このテンポの問題は 2.5 のプロンプトガイドで扱っていて、能力差の残りは 2.5 と 2.0 の比較にあります。

コンソールを2つ開かずに動画モデルを比較するには

この記事の比較に必要だったのは、手配が面倒なことが1つだけです。同じボディを seedance-2.5seedance-2.0-mini に、他は何も変えずに投げること。モデル ID が2つ、キーは1つ、エンドポイントの形は1つ。ネイティブにやるならプロバイダーのコンソール2つ、残高2つ、リクエストスキーマ2つで、そこまで来るとたいていの人はあるモデルと「別のモデルの記憶」を比べてベンチマークと呼び始めます。

ここでは両モデルとも同じ POST /v1/videos に答えます。動画エンドポイントがモデル非依存だからで、2つの実行の差分は model フィールドだけでした。私たちは ofox の動画エンドポイントを使いましたが、ベンダーをまたいでリクエストの形を保つゲートウェイなら同じことができます。クロスモデル比較を信じる前に確認すべきは、ゲートウェイが途中でフィールドを正規化していないことaspect_ratio が 2.5 と 2.0 で同じ挙動になっていたら、それが匂いです。今回は同じになりませんでした。フィールドが各モデルに手を加えられずに届いている証拠です。

参考資料

よくある質問

Seedance 2.5 に first frame と last frame をどう渡しますか?
POST /v1/videos の frame_images 配列に要素を2つ入れ、それぞれに image_url と frame_type(first_frame または last_frame)を付けます。モードはボディから推測されるので mode パラメータはありません。画像は公開 URL でも data URI でも渡せます。base64 の data URI が通るので、テストのために画像ホストを立てる必要はありません。
Seedance 2.5 は指定した最終フレームに本当に着地しますか?
します。出力の最終フレームと指定した last frame を比較したところ、平均絶対ピクセル誤差は 480p で 5.4、720p で 2.0 でした(0〜255 スケール)。同じリクエストを Seedance 2.0 Mini に投げると 35.9 で、無関係な2枚の画像の基準値が 39.0 です。Mini では最終フレームは提案、2.5 では目標です。
2.5 の first-last-frame ジョブで aspect_ratio が 400 になるのはなぜですか?
出力比率が first frame の画像から決まるため、このフィールドは無視されるのではなく拒否されます。エラーは「first-frame または first-last-frame 生成では出力比率が first frame 画像に従う」と述べます。送った比率が画像と完全に一致していても発火します。aspect_ratio を省くか、adaptive を送ってください。
同じ制限は Seedance 2.0 にもありますか?
ありません。frame_images と aspect_ratio 16:9 を含む同一のボディが bytedance/seedance-2.0-mini では受理され、864x496 のクリップが返りました。この制限は 2.5 のロックされたタスク種別に固有で、フレーム指定生成一般の規則ではありません。だからこそ 2.0 で動いていたコードがモデル ID を変えた日に壊れます。
last frame だけ送れますか?
送れません。400 で frame_images: last_frame requires a first_frame が返ります。first_frame を2つ送るのも 400 で at most one first_frame and one last_frame です。どちらも上流に行く前に検証されるため、費用はかからず1秒ほどで返ってきます。
Seedance 2.5 の image-to-video はいくらですか?
「その他の組み合わせ」の行ではなく、その解像度の text-to-video のレートで課金されます。5 秒 480p のジョブは $0.55、720p は $1.20 で、モデルページの $0.11/秒 と $0.24/秒 に一致します。失敗したジョブは usage が null で課金されません。
Seedance 2.5 は 1080p に対応していますか?
モデルページの料金表には text-to-video と video-to-video の 1080p 行があり、実際に 1080p の first-last-frame ジョブが 176.2 秒で完了し $2.40 課金されました。これは text-to-video の $0.48/秒 です。一方で同じページの説明文には今も 480p または 720p と書かれています。説明文より料金表と実リクエストを信じてください。
出力に音声は付きますか?
既定で付きます。取得したクリップはすべて 32 kHz の AAC トラックと 24 fps の H.264 映像を持っていました。後で結合する予定なら重要です。音声ストリームも揃っていないと、ffmpeg concat のストリームコピーは通りません。