Seedance 2.5: первый и последний кадр, ошибка финала 5.4
Отдайте оба конца — и Seedance 2.5 приходит в заданный финал: ошибка 5.4 в 480p против 35.9 у 2.0 Mini. Поле aspect_ratio даёт 400, 480p стоит $0.11/с.
Seedance 2.5 относится к последнему кадру как к пункту назначения, а не как к подсказке. Дайте ему оба конца сцены — и он приедет ровно туда, куда просили. Именно этого 2.0 Mini делать не хотел.
Эндпоинт: POST /v1/videos -> 202 + polling_url
Поле: frame_images[] с frame_type first_frame / last_frame
Правило: aspect_ratio на кадровых задачах 2.5 — это 400. Опустить или adaptive.
На 2.0 так же? Нет. 2.0-mini принимает aspect_ratio вместе с кадрами.
Ошибка финального кадра, средняя абсолютная разница 0–255, меньше — ближе:
Seedance 2.5, 720p 2.0
Seedance 2.5, 480p 5.4
Seedance 2.0 Mini 35.9
две несвязанные картинки 39.0 (потолок)
Тариф: $0.11/с на 480p, $0.24/с на 720p, по строке text-to-video
Измерено: 2026-08-24, по одному клипу 5 секунд на конфигурацию
Обновлено 2026-08-24. Все числа ниже получены через POST /v1/videos на ofox в этот день. Маршрутизация видеомоделей меняется, поэтому перед переносом таблицы проверок в свой код перепроверьте четыре случая с ошибками.
Как передать первый и последний кадр
Два элемента в frame_images, у каждого свой 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 важнее, чем кажется: генерацию по первому и последнему кадру можно проверить, не поднимая публичный хостинг изображений. Дальше опрашивайте polling_url до финального статуса — а у этого свой набор ловушек, который стоит прочитать до того, как писать цикл.
Промпт здесь по-прежнему работает. Это не украшение между двумя зафиксированными картинками: он решает, что происходит по дороге и сколько движений камеры на это тратится.
Действительно ли модель приходит в последний кадр
Да, и разрыв с 2.0 Mini совсем не тонкий. Те же две картинки, тот же промпт, та же длительность, тот же день.

Чтобы получить число, мы вытащили нулевой и финальный кадр каждого клипа, привели кадр и исходное изображение к 256x144 и посчитали среднюю абсолютную разницу по каналам в шкале 0–255. Меньше — ближе.
| Прогон | Ошибка первого кадра | Ошибка финального кадра | Списано |
|---|---|---|---|
| Seedance 2.5, 720p | 1.8 | 2.0 | $1.20 |
| Seedance 2.5, 1080p | 1.8 | 3.1 | $2.40 |
| Seedance 2.5, 480p | 3.0 | 5.4 | $0.55 |
| Seedance 2.0 Mini, 480p | 9.5 | 35.9 | $0.10 |
| Seedance 2.0 Mini, 480p, без поля ratio | 9.6 | 37.1 | $0.10 |
| Ориентир: две несвязанные картинки | 38.6 | 39.0 | — |
Читайте с последней строки. Две картинки, не имеющие друг к другу отношения, дают около 39. Финал Mini — 35.9, то есть он закончил там, где сам решил: палитра дождя та же, персонаж другой, кадрирование другое. С первым кадром история иная, его держат обе модели, и это совпадает с поведением линейки 2.0, где первый кадр соблюдается, а последний уплывает.
Две оговорки, прежде чем строить на этом. Каждая конфигурация — один прогон, а не распределение, поэтому выводом считайте порядок, а десятые — одной точкой. И метрика намеренно грубая: она накажет верную композицию, которая пришла на два кадра раньше. Эта грубость и делает 35.9 убедительной. Настолько тупой метрикой невозможно случайно получить значение, вплотную подошедшее к «несвязанным картинкам».
Почему aspect_ratio даёт 400 на кадровой задаче 2.5
Потому что пропорции выводятся из изображения первого кадра, и передача поля — это ошибка, а не избыточность.
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."
Ловушка вот в чём: наше изображение первого кадра ровно 1280x720, то есть отправленное 16:9 было верным. И всё равно отказ. API не сравнивает ваше значение с картинкой — он в этом режиме не принимает значение вообще.
Отсюда три следствия, и все три измерены, а не предположены:
| Запрос | Результат |
|---|---|
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, выход 1280x720 на 720p |
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, начнёт возвращать 400 в тот день, когда кто-то поправит ID модели на 2.5, и сообщение об ошибке будет про параметр, которого никто не трогал.
ByteDance документирует это прямо. Гайд по промптам Seedance 2.5 делит задачи на заблокированные и незаблокированные, помещает «редактирование, первый и последний кадры, продление» в первую группу и поясняет, что заблокированные означают: «соотношение сторон выходного видео, а в ряде случаев и длительность, зафиксированы». На той же странице есть фраза, объясняющая наш результат на 2.0: «Seedance 2.0 не делает такого различия».
Что ещё отклоняет валидатор frame_images
Четыре формы, все ловятся до отправки к провайдеру. Каждая вернулась примерно за секунду и ничего не стоила.
| Что отправлено | HTTP | Сообщение |
|---|---|---|
Оба элемента с first_frame | 400 | frame_images: at most one first_frame and one last_frame |
Только last_frame | 400 | frame_images: last_frame requires a first_frame |
frame_type: "start_frame" | 400 | frame_images[0]: frame_type must be first_frame or last_frame |
frame_images вместе с input_references | 400 | frame_images and input_references are mutually exclusive |
Обратите внимание на путь с индексом в третьей строке. Когда тела запросов генерируются в цикле, frame_images[0] сразу показывает, на какой элемент смотреть. Большинство видео API столько не отдают.

Все пять отказов — живые вызовы к Seedance 2.5. Строка ffprobe внизу относится к трём клипам, которые всё-таки отработали, и именно там видно смену кодека на 1080p.
Вторая строка — то, вокруг чего стоит проектировать. Режима «только последний кадр» нет, поэтому пайплайн, который хочет закончить на известном изображении, обязан решить и то, с чего он начинается. Если важен только финал, сгенерируйте правдоподобный начальный кадр и передайте оба.
Сколько на самом деле стоит клип image-to-video
Он тарифицируется по строке text-to-video для своего разрешения. Карточка модели считает цену по разрешению и режиму, строки image-to-video там нет, поэтому естественно опасаться, что вы попадёте на «все остальные комбинации» по $0.568/с. Не попадёте.
| Разрешение | Карточка модели, text-to-video | Списано за наш клип 5 с | Отсюда |
|---|---|---|---|
| 480p | $0.11/с | $0.55 | $0.11/с |
| 720p | $0.24/с | $1.20 | $0.24/с |
| 1080p | $0.48/с | $2.40 | $0.48/с |
Три разрешения, три точных совпадения. Файлы вернулись как 854x480, 1280x720 и 1920x1080, все по 24 кадра в секунду с дорожкой AAC на 32 кГц. Длительность выходит 5.04 секунды, а не ровно 5, поэтому считайте по полю usage.video_seconds, а не по собственной арифметике.
Для сравнения: тот же запрос на bytedance/seedance-2.0-mini в 480p обошёлся в $0.10 за клип. Поэтому Mini остаётся правильным инструментом для потоковой работы, где финальный кадр никто не проверяет. Он в пять с половиной раз дешевле — и на этой задаче разница видна.
Какие разрешения принимает Seedance 2.5
Спрашивайте таблицу цен, а не описание. Карточка модели сейчас печатает текстовое резюме про 480p или 720p, тогда как таблица цен на той же странице содержит строки 1080p для text-to-video и video-to-video, а задача 1080p с первым и последним кадром у нас дошла до конца.
| Источник | Что говорит |
|---|---|
| Описание на карточке | 480p или 720p, по умолчанию 720p |
| Таблица цен на карточке | Строки 480p, 720p, 1080p; 1080p text-to-video по $0.48/с |
| Живой API, first-last-frame в 1080p | Принято, завершено за 176.2 с, списано $2.40 |
Такое расхождение нормально в первые недели после открытия нового уровня разрешения, а поле разрешения — самая дешёвая вещь для проверки: отправьте запрос, прочитайте код ответа. Отказ мгновенный и бесплатный.
На 1080p меняется то, о чём на странице не сказано: файл вернулся в HEVC, тогда как выходы 480p и 720p были H.264. Если вы склеиваете клипы копированием потоков или отдаёте их прямо в браузер, смешанная по кодекам партия вас укусит. Проверяйте кодек у файла, а не предполагайте его по модели.
Длительность — вторая ось, изменившаяся между поколениями: 2.5 берёт от 4 до 30 секунд, линейка 2.0 останавливается на 15. Клипу в 30 секунд нужно около десяти тактов действия в промпте, иначе модель растянет один момент на десять секунд. Про этот ритм мы писали в гайде по промптам 2.5, а остальные отличия — в сравнении 2.5 и 2.0.
Как сравнить две видеомодели без двух консолей
Сравнение в этой статье потребовало ровно одной неудобной вещи: прогнать одно и то же тело запроса на seedance-2.5 и seedance-2.0-mini, не меняя больше ничего. Два ID модели, один ключ, одна форма эндпоинта. Нативно это две консоли провайдеров, два баланса и две схемы запроса — и на этом месте большинство сравнивает одну модель со своим воспоминанием о другой и называет это бенчмарком.
Обе модели здесь отвечают на одном и том же POST /v1/videos, потому что видеоэндпоинт не зависит от модели: разница между прогонами была только в поле model. Мы использовали видеоэндпоинт ofox, и тот же приём работает с любым шлюзом, который сохраняет форму запроса между вендорами. Перед тем как доверять межмодельному сравнению, проверьте, не нормализует ли шлюз поля по дороге. Если бы aspect_ratio вёл себя одинаково на 2.5 и 2.0, это был бы плохой знак. Он вёл себя по-разному — значит, поле доходит до каждой модели нетронутым.
Источники
Часто задаваемые вопросы
- Как передать первый и последний кадр в Seedance 2.5?
- Положите оба изображения в массив frame_images у POST /v1/videos, у каждого элемента укажите image_url и frame_type — first_frame или last_frame. Режим выводится из тела запроса, отдельного параметра mode нет. Изображения принимаются как публичные URL и как data URI: base64 работает, так что поднимать хостинг картинок ради теста не нужно.
- Seedance 2.5 действительно приходит в заданный последний кадр?
- Да, и близко. Мы сравнили финальный кадр вывода с запрошенным последним кадром и получили среднюю абсолютную ошибку по пикселям 5.4 на 480p и 2.0 на 720p по шкале 0–255. Тот же запрос на Seedance 2.0 Mini дал 35.9 при базовом уровне 39.0 для двух несвязанных изображений. На Mini последний кадр — пожелание, на 2.5 — цель.
- Почему aspect_ratio возвращает 400 на задаче с кадрами в 2.5?
- Потому что соотношение сторон берётся из изображения первого кадра, и поле не игнорируется, а отклоняется. Текст ошибки говорит, что при генерации по первому или по первому и последнему кадру пропорции выхода следуют за первым кадром. Ошибка срабатывает, даже если переданное соотношение точно совпадает с изображением. Не передавайте aspect_ratio или отправьте adaptive.
- Действует ли то же правило для Seedance 2.0?
- Нет. Идентичное тело с frame_images и aspect_ratio 16:9 было принято на bytedance/seedance-2.0-mini и вернуло клип 864x496. Ограничение относится к заблокированным типам задач именно у 2.5, а не к генерации по кадрам вообще — поэтому код, работавший на 2.0, ломается в день смены ID модели.
- Можно отправить только последний кадр?
- Нет, придёт 400 с текстом frame_images: last_frame requires a first_frame. Два first_frame тоже нельзя: 400 и at most one first_frame and one last_frame. Обе проверки выполняются до отправки к провайдеру, поэтому они бесплатны и возвращаются примерно за секунду.
- Сколько стоит клип image-to-video на Seedance 2.5?
- Он тарифицируется по строке text-to-video для своего разрешения, а не по строке «все остальные комбинации». Наша задача 5 секунд в 480p стоила $0.55, а в 720p — $1.20, что в точности равно $0.11/с и $0.24/с с карточки модели. У неудачных задач usage равен null, и они не тарифицируются.
- Поддерживает ли Seedance 2.5 разрешение 1080p?
- В таблице цен на карточке модели строки 1080p есть и для text-to-video, и для video-to-video, а наша задача 1080p с первым и последним кадром завершилась за 176.2 секунды и стоила $2.40 — это ставка text-to-video $0.48/с. При этом описание на той же странице по-прежнему говорит про 480p или 720p. Доверяйте таблице цен и живому запросу.
- Есть ли в выходном файле звук?
- Да, по умолчанию. Во всех полученных клипах была дорожка AAC на 32 кГц рядом с видео H.264 на 24 кадрах в секунду. Если планируете склейку, это важно: аудиопотоки тоже должны совпадать, иначе ffmpeg concat с копированием потоков откажется работать.


