Skip to content

Seedance

Seedance — семейство видео-моделей ByteDance, обслуживаемое каналами Volcengine Ark. RouteAPI преобразует ваш запрос в вызов Ark /api/v3/contents/generations/tasks, поэтому каждая задача проходит тот же путь «отправка → опрос → скачивание», что и у других видеомоделей: см. Создание задачи и Получение задачи. Здесь описано, что читает адаптер Seedance, ограничения по моделям, как читать запись задачи Seedance и как считается стоимость.

Генерация видео асинхронна: отправьте задачу, сохраните task_id, опрашивайте каждые 10–15 секунд, а когда статус станет SUCCESS — скачайте результат. Клип на 4 секунды в 480p обычно занимает от одной до пяти минут; более высокое разрешение и большая длительность требуют больше времени.

Model IDМодель ArkРазрешениеДлительностьПримечания
seedance-2.5doubao-seedance-2-5-260628480p / 720p / 1080p4–30 сЧерновой предпросмотр, режимы референса/редактирования/продления, вывод mov
seedance-2.0doubao-seedance-2-0-260128480p / 720p / 1080p / 4k4–15 сРеференсные материалы: изображение, видео и аудио
seedance-2.0-fastdoubao-seedance-2-0-fast-260128480p / 720p4–15 сБолее быстрый и дешёвый вариант 2.0
seedance-2.0-minidoubao-seedance-2-0-mini-260615480p / 720p4–15 сНедорогой вариант 2.0

Отправляйте ID из GET /v1/models. Канал, обслуживающий эти модели, сопоставляет этот ID с соответствующим именем модели Ark из второго столбца, поэтому адаптер принимает обе схемы именования. Доступные вашему аккаунту модели и их цены задаются в консоли RouteAPI.

Столбцы разрешения и длительности — это диапазоны ByteDance для каждой модели. RouteAPI их не проверяет: единственная проверка длительности на нашей стороне — общее правило, что duration / seconds верхнего уровня должны укладываться в 0–3600 (см. Ограничения и ошибки). Всё остальное обеспечивает Ark — запрос на 30 секунд для модели 2.0, неподдерживаемое разрешение или слишком много референсных клипов сначала отправляются, а затем отклоняются Ark и возвращаются как fail_to_fetch_task со статусом и сообщением Ark. RouteAPI также не подставляет отсутствующие resolution или duration: значение по умолчанию применяет Ark. Оценка стоимости в этих случаях считается по 1080p и 5 секундам, поэтому зарезервированная сумма — это оценка, а не значение по умолчанию Ark.

Seedance 1.x (doubao-seedance-1-0-*, doubao-seedance-1-5-*) больше не обслуживается. Запрос, который сопоставляется с именем 1.x, отклоняется с 400 и кодом model_not_supported после сопоставления модели, но до резервирования или отправки провайдеру.

Отображение общего конверта

Section titled “Отображение общего конверта”
Поле конвертаЧто делает адаптер Seedance
promptДобавляется как завершающий элемент text, если metadata.content уже не содержит элемент text и content не является draft_task версии 2.5. Обязателен в каждом запросе
images / imageПо одному элементу image_url без role на изображение. Игнорируется при наличии metadata.content
ratioОтправляется как ratio Ark
resolutionОтправляется как resolution Ark
durationОтправляется как duration Ark; seconds верхнего уровня, разбираемый в положительное целое, его заменяет
generate_audioОтправляется как generate_audio; явный false также передаётся
metadataДекодируется в типизированную структуру; её значения важнее одноимённых полей верхнего уровня

size, input_reference и mode входят в общий конверт, но адаптер Seedance их не читает: используйте resolution / ratio, а также images или content.

Типы metadata проверяются до отправки: неверный тип (content объектом, image_url простой строкой, duration: "abc") возвращает 400, и ничего не списывается. Сообщение начинается с unmarshal metadata failed. Числовые и логические значения внутри metadata принимают и строковую форму ("duration": "6", "watermark": "false"); скалярные поля верхнего уровня должны использовать свои типы JSON.

Параметры верхнего уровня

Section titled “Параметры верхнего уровня”

Эти поля читаются из верхнего уровня тела, поэтому та же структура, что отправляется другим провайдерам, работает без обёртки в metadata:

ПолеТипОписание
ratiostringСоотношение сторон: 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 или adaptive
resolutionstring480p, 720p, 1080p или 4k, если модель поддерживает
durationintegerДлительность в секундах. 0 означает «не задано» и не отправляется; чтобы передать явный ноль, используйте metadata
generate_audiobooleanГенерировать звуковую дорожку; явный false передаётся
secondsstringУстаревшая строковая форма длительности; если разбирается в положительное целое, заменяет и duration, и metadata.duration. Нечисловое значение игнорируется
ПолеТипОписание
contentarrayВходной материал; заменяет images. См. metadata.content
ratio, resolution, duration, generate_audioкак на верхнем уровнеИмеют приоритет над значением верхнего уровня. Положительный seconds по-прежнему важнее итоговой длительности
seedintegerСлучайное зерно; 0 передаётся как явное значение
framesintegerКоличество кадров. Если задано, заменяет длительность в оценке стоимости, и Ark использует его вместо длительности
camera_fixedbooleanФиксирует камеру
watermarkbooleanВодяной знак провайдера на результате. ByteDance указывает значение по умолчанию false
return_last_framebooleanДополнительно возвращает последний кадр как изображение
service_tierstringУровень обслуживания провайдера, например default. Передаётся без изменений
execution_expires_afterintegerСрок жизни задачи в секундах. ByteDance указывает 3600–259200, по умолчанию 172800; применяет Ark
priorityintegerПриоритет очереди у провайдера, 0–9, больше — раньше. Ark упорядочивает задачи только внутри вашего аккаунта
safety_identifierstringИдентификатор вашего конечного пользователя, до 64 символов. Передаётся в Ark, длина проверяется там
draftbooleanЧерновой предпросмотр Seedance 2.5 — см. Черновой предпросмотр
output_formatstringКонтейнер вывода, передаётся как есть. Seedance 2.5 принимает mp4 (по умолчанию) или mov
omni_reference_task_typestringРежим референса Seedance 2.5, передаётся как есть: auto, reference, edit или extend

callback_url не передаётся, и callback не отправляется — опрашивайте результат. tools тоже отбрасывается; веб-поиск у провайдера через этот API недоступен. Нераспознанные ключи, включая эти, не вызывают ошибку, а игнорируются. metadata.model не читается: model в теле всегда равен имени провайдерской модели канала.

content — упорядоченный массив входных элементов. У каждого есть type, соответствующее поле полезной нагрузки и необязательный role:

typeПолезная нагрузкаЗначения role
texttext—
image_urlimage_url.urlfirst_frame, last_frame, reference_image
video_urlvideo_url.urlreference_video
audio_urlaudio_url.urlreference_audio
draft_taskdraft_task.id—

RouteAPI проверяет форму элемента (неверный тип полезной нагрузки даёт 400), но не имя role; неизвестная роль передаётся, и Ark решает, отклонять ли её. URL может быть публичной ссылкой http(s), URI data: для изображений и аудио или ссылкой asset://<asset_id> — см. Материалы для загрузки материала и для изображений реальных людей, которые должны браться из проверенной группы материалов.

Правила, возникающие из преобразования:

  • Если content присутствует, он используется как есть; images верхнего уровня игнорируются, а не объединяются. Пустой массив content считается отсутствующим, поэтому images верхнего уровня продолжают действовать.
  • Если в content нет элемента text, prompt верхнего уровня добавляется как завершающий текстовый элемент. Единственное исключение — запрос 2.5, у которого content равен draft_task: prompt не добавляется, но prompt всё равно должен присутствовать в теле.
  • Ссылайтесь на материал по порядковому номеру в prompt («image 1», «video 1»), нумеруя по типу в порядке content.
  • Первый кадр, первый/последний кадр и мультиреференс — три разных режима. Не смешивайте их, пока не убедились, что модель принимает такую комбинацию.

Ограничения на референсы ниже задаёт Ark, а не RouteAPI: запрос сверх лимита отправляется и отклоняется провайдером.

ЭлементSeedance 2.5Серия 2.0
Референсные изображения1–301–9
Референсные видеоДо 10 клипов, суммарно ≤30 сДо 3 клипов, суммарно ≤15 с
Референсное аудиоДо 10 клипов, суммарно ≤30 сДо 3 клипов, суммарно ≤15 с, и обязательно вместе с изображением или видео
Одно изображениеМенее 30 МБ, 300–6000 px по сторонеТо же
Одно видеоmp4 / mov, менее 200 МБТо же
Одно аудиоwav / mp3, менее 15 МБТо же

Seedance 2.x отклоняет референсные изображения и видео с лицом реального человека. Чтобы использовать образ реального человека, сначала пройдите верификацию личности, а затем ссылайтесь на проверенный материал через asset:// — Материалы описывают сеанс верификации, проверенную группу и правила запроса.

Terminal window
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0-fast",
"prompt": "A paper boat drifting down a rain-soaked street, cinematic lighting",
"ratio": "16:9",
"resolution": "720p",
"duration": 5,
"generate_audio": false
}'

Первый кадр и первый + последний кадр

Section titled “Первый кадр и первый + последний кадр”

Одно изображение в images становится элементом изображения без роли, который Seedance трактует как первый кадр:

Terminal window
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "The camera slowly pushes in as the person looks up and smiles",
"images": ["https://cdn.example.com/first.jpg"],
"ratio": "adaptive",
"resolution": "720p",
"duration": 5
}'

Для явного управления первым и последним кадром используйте content и поместите prompt внутрь:

Terminal window
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "The bud slowly opens into a full bloom",
"metadata": {
"content": [
{ "type": "text", "text": "The bud slowly opens into a full bloom" },
{ "type": "image_url", "image_url": { "url": "https://cdn.example.com/bud.jpg" }, "role": "first_frame" },
{ "type": "image_url", "image_url": { "url": "https://cdn.example.com/flower.jpg" }, "role": "last_frame" }
],
"ratio": "adaptive",
"resolution": "720p",
"duration": 5
}
}'

Мультимодальные референсы

Section titled “Мультимодальные референсы”

Референсные изображения, видео и аудио смешиваются в одном массиве content с ролями reference_*. Нумеруйте материал по типу в порядке content и ссылайтесь на него в prompt именно так:

Terminal window
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "The person in image 1 dances following the moves in video 1, with audio 1 as background music",
"metadata": {
"content": [
{ "type": "text", "text": "The person in image 1 dances following the moves in video 1, with audio 1 as background music" },
{ "type": "image_url", "image_url": { "url": "https://cdn.example.com/person.jpg" }, "role": "reference_image" },
{ "type": "video_url", "video_url": { "url": "https://cdn.example.com/dance.mp4" }, "role": "reference_video" },
{ "type": "audio_url", "audio_url": { "url": "https://cdn.example.com/bgm.mp3" }, "role": "reference_audio" }
],
"ratio": "16:9",
"resolution": "720p",
"duration": 10
}
}'

Запрос с видеовходом тарифицируется по ставке видеовхода модели — см. Оплата. Количество, длительность и формат референсов контролирует Ark; см. таблицу ограничений в разделе metadata.content.

Специфичные режимы провайдера (Seedance 2.5)

Section titled “Специфичные режимы провайдера (Seedance 2.5)”

Seedance 2.5 добавляет выбор режима и выбор контейнера. Оба передаются без изменений для всех моделей Seedance, а принимает ли их провайдер, решает Ark:

Terminal window
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"prompt": "Continue the scene as the camera pulls back over the harbour",
"metadata": {
"omni_reference_task_type": "extend",
"output_format": "mov",
"content": [
{ "type": "text", "text": "Continue the scene as the camera pulls back over the harbour" },
{ "type": "video_url", "video_url": { "url": "https://cdn.example.com/scene.mp4" }, "role": "reference_video" }
],
"ratio": "16:9",
"duration": 8
}
}'

omni_reference_task_type принимает auto (по умолчанию), reference, edit или extend. Какую комбинацию входов ожидает каждый режим, определяется контрактом ByteDance; RouteAPI только передаёт значение.

Черновик — это недорогой предпросмотр. Генерация финального видео из него — вторая задача, оплачиваемая отдельно.

  1. Отправьте запрос с "metadata": { "draft": true, ... } и дождитесь SUCCESS.
  2. Прочитайте идентификатор провайдерской задачи из записи задачи: GET /v1/video/generations/{task_id} → data.data.id.
  3. Отправьте новую задачу, у которой content — единственный draft_task.

Шаг 1:

Terminal window
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"prompt": "An astronaut walks slowly on the moon",
"metadata": { "draft": true, "duration": 5, "ratio": "16:9" }
}'

Шаг 2, после того как задача-черновик стала SUCCESS. data.data.id — это идентификатор задачи Ark, а не внешний data.task_id:

Terminal window
curl -s https://api.routeapi.ai/v1/video/generations/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV \
-H "Authorization: Bearer $ROUTEAPI_KEY" | jq -r .data.data.id

Шаг 3:

Terminal window
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"prompt": "x",
"metadata": {
"content": [ { "type": "draft_task", "draft_task": { "id": "cgt-xxxxxxxx" } } ],
"resolution": "1080p",
"duration": 5
}
}'

prompt по-прежнему обязателен; в этой форме он не отправляется как текст, поэтому подойдёт любой непустой заполнитель. Продолжение по draft_task без явного duration резервируется так, будто длительность достигнет автоматического потолка модели (30 секунд для 2.5, 15 секунд для 2.0), и затем рассчитывается по фактическому использованию.

Идентификаторы черновиков принадлежат Ark. ByteDance указывает срок жизни 7 дней; RouteAPI его не проверяет, поэтому просроченный идентификатор приводит к ошибке у провайдера.

Terminal window
curl https://api.routeapi.ai/v1/video/generations/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV \
-H "Authorization: Bearer $ROUTEAPI_KEY"
{
"code": "success",
"message": "",
"data": {
"id": 4512,
"created_at": 1792048450,
"updated_at": 1792048569,
"task_id": "task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV",
"platform": "54",
"user_id": 1024,
"group": "default",
"channel_id": 18,
"quota": 108900,
"action": "generate",
"status": "SUCCESS",
"progress": "100%",
"fail_reason": "",
"result_url": "https://ark-content.example/xxxx.mp4",
"submit_time": 1792048458,
"start_time": 1792048461,
"finish_time": 1792048569,
"properties": {
"input": "{\"model\":\"doubao-seedance-2-0-fast-260128\",\"content\":[{\"type\":\"text\",\"text\":\"An orange cat stretching on a windowsill at sunrise\"}],\"generate_audio\":false,\"resolution\":\"720p\",\"ratio\":\"16:9\",\"duration\":5}",
"origin_model_name": "seedance-2.0-fast",
"upstream_model_name": "doubao-seedance-2-0-fast-260128"
},
"data": {
"id": "cgt-20261023100444-9kz46",
"model": "doubao-seedance-2-0-fast-260128",
"status": "succeeded",
"content": { "video_url": "https://ark-content.example/xxxx.mp4" },
"seed": 8202,
"resolution": "720p",
"duration": 5,
"ratio": "16:9",
"framespersecond": 24,
"usage": { "completion_tokens": 108900, "total_tokens": 108900 },
"created_at": 1792048458,
"updated_at": 1792048569
}
}
}

Внешние поля формирует RouteAPI, и Получение задачи описывает их все. Для Seedance читайте data.status, data.progress, data.result_url, data.fail_reason и data.quota — в quota указана списанная на данный момент сумма; после успешной задачи это итоговая сумма. data.properties.input — снимок точного JSON, который RouteAPI отправил в Ark (URL медиа длиннее 512 байт заменяются на [omitted, N bytes]), самый быстрый способ убедиться, что запрос действительно ушёл в нужном разрешении. data.platform — тип канала: 54 для видеоканала Doubao, 45 для канала Volcengine.

data.data — это тело задачи самого Ark, сохранённое как есть; до завершения задачи оно может быть неполным. Если провайдер канала отвечает через шлюзовую обёртку ({"code": 200, "data": {...}}), перечисленные ниже поля лежат на уровень глубже, в data.data.data — судите о завершении по data.status, а не по наличию поля. Поля, которые стоит читать:

ПолеЗначение
data.data.idИдентификатор задачи Ark, отличный от внешнего data.task_id. Используется для финальной генерации из черновика 2.5
data.data.content.video_urlURL видео от Ark; то же значение, что и внешний data.result_url
data.data.content.last_frame_urlИзображение последнего кадра. Присутствует только при return_last_frame. RouteAPI сохраняет эту нагрузку как есть и разбирает из неё только content.video_url
data.data.duration / resolution / ratio / framespersecond / seedФактические параметры генерации
data.data.usage.completion_tokens / total_tokensТокены, учтённые Ark; total_tokens — количество для расчёта
data.data.errorКод и сообщение ошибки Ark при сбое

Статусы Ark отображаются в запись задачи так; статус, который RouteAPI не распознаёт, считается «всё ещё выполняется»:

status ArkСтатус записи задачиПрогресс
pending, queuedQUEUED10%
processing, runningIN_PROGRESS50%
succeededSUCCESS100%
failed, expired, cancelledFAILURE100%
любой другойIN_PROGRESS30%

Если Ark сообщает succeeded без video_url, RouteAPI оставляет задачу в IN_PROGRESS и опрашивает снова, а не рассчитывает задачу без результата. При FAILURE в fail_reason попадает сообщение ошибки Ark, а при его отсутствии — task failed; задача expired или cancelled без объекта ошибки сообщает task expired или task cancelled. Если раньше срабатывает собственный таймаут RouteAPI (по умолчанию 24 часа), статус тоже становится FAILURE с сообщением платформы, и в обоих случаях резерв возвращается.

data.result_url — это собственный URL Ark, и Ark делает его недействительным по своему расписанию (ByteDance указывает около 24 часов) — скачайте его сразу. Эндпоинт содержимого RouteAPI заново запрашивает сохранённый URL в момент вызова: он избавляет от необходимости следить за истекающими ссылками, но не может оживить уже истёкшую:

Terminal window
curl -L -o out.mp4 \
https://api.routeapi.ai/v1/videos/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV/content \
-H "Authorization: Bearer $ROUTEAPI_KEY"

Эндпоинт содержимого отдаёт только завершённые задачи самого вызывающего: незавершённая задача даёт 400 с указанием текущего статуса, неизвестный или чужой task_id — 404, а сбой получения файла у Ark — 502. Его ошибки используют форму {"error": {"message": "...", "type": "..."}} без поля code. Если включён return_last_frame, data.data.content.last_frame_url истекает тоже по расписанию Ark — скачайте его одновременно.

Модели Seedance тарифицируются по токенам, а не за запрос или за секунду. Цена в консоли указывается за миллион выходных токенов для уровня разрешения; запрос с видеовходом оплачивается по ставке видеовхода модели.

При отправке RouteAPI оценивает выходные токены по запрошенному разрешению и количеству кадров:

frames = 24 × duration + 1 (frames replaces duration when metadata.frames is set)
tokens = pixels × frames / 1024
pixels = 480p: 864×496, 720p: 1280×720, 1080p: 1920×1080, 4k: 3840×2160

Если длительность не указана, берётся 5 секунд; если content — это draft_task без явной длительности, берётся автоматический потолок модели (30 секунд для 2.5, 15 секунд для 2.0). Отсутствующее или нераспознанное разрешение оценивается как 1080p. Автоматическая длительность ByteDance (-1) на верхнем уровне отклоняется проверкой 0–3600; если передать её строкой "-1" внутри metadata, она уходит провайдеру, и оценка использует тот же автоматический потолок. Оценка умножается на коэффициент модели, коэффициент группы и множитель видеовхода, и эта сумма резервируется. Для модели, тарифицируемой по коэффициенту, а не по фиксированной цене, оценка сравнивается с обычным предварительным списанием, и резервируется большая сумма. Расчёт по токенам при завершении выполняется только если для модели задан коэффициент; если коэффициента нет, резерв становится итоговым списанием (а если у модели нет ни коэффициента, ни фиксированной цены, запросы отклоняются, если только для вашего аккаунта не разрешены модели без коэффициента).

ЗапросРезерв при отправкеПри успехе
Указан durationоценка токенов × ценаusage.total_tokens от Ark × цена, разница списывается или возвращается
duration не указаноценка по 5 стот же расчёт
Задан metadata.framesоценка по количеству кадровтот же расчёт
draft_task без durationоценка по 30 с / 15 стот же расчёт
Настроена фиксированная ценафиксированная ценабез изменений; расчёта по токенам нет
SUCCESS без usage—резерв остаётся
FAILURE, expired, cancelled—резерв возвращается
400резерва нетсписания нет

Цена за токен зависит от уровня выходного разрешения, наличия видеовхода и — для моделей, где таблица цен определяет это измерение — от генерации аудио. Когда используется таблица цен модели и полученный множитель не равен 1.0, заголовок X-New-Api-Other-Ratios в ответе на отправку содержит его как элемент video_input. Встроенная резервная таблица задаёт для модели 2.0 уровни base (480p / 720p), 1080p и 4k и ставку видеовхода для каждого; у fast-варианта только уровень base и коэффициент видеовхода 22/37. У seedance-2.5 и seedance-2.0-mini нет встроенной таблицы цен, их уровни берутся из конфигурации консоли. Канал также может переопределить коэффициенты таблицей VideoPrice, привязанной к запрашиваемому вами ID модели. Цены и уровни, показанные в консоли, являются истиной в последней инстанции.

Пример расчёта (цены гипотетические; реальные смотрите в консоли). Пусть seedance-2.0-fast стоит $2 за 1 млн выходных токенов в 720p, коэффициент группы равен 1:

  1. Отправка в 720p, duration: 5. Оценка: 1280 × 720 = 921 600 пикселей, 24 × 5 + 1 = 121 кадр, 921 600 × 121 / 1024 = 108 900 токенов, резерв $0.2178.
  2. Ark сообщает usage.total_tokens: 105000, итоговое списание — $0.21, возвращается $0.0078.
  3. Если бы в том же запросе был элемент reference_video, встроенная таблица fast-варианта применила бы множитель видеовхода 22/37 ≈ 0.5946 и к оценке, и к расчёту: резерв ≈ $0.1295, списание ≈ $0.1249.

Запрос, у которого баланс или квота ключа не покрывает резерв, отклоняется ещё до отправки провайдеру: 403 insufficient_user_quota для кошелька, 403 pre_consume_token_quota_failed для квоты ключа.

СтатусКодЗначение
400invalid_requestОтсутствующий или пустой prompt, некорректный JSON или поле metadata неверного типа
400invalid_secondsduration / seconds верхнего уровня или числовой metadata.duration отрицательны либо больше 3600
400model_not_supportedЗапрос сопоставлен с моделью Seedance 1.x, которая больше не обслуживается
400task_not_existtask_id неизвестен или принадлежит другому аккаунту
403insufficient_user_quota, pre_consume_token_quota_failedБаланс кошелька или квота ключа не покрывают резерв
429—Ёмкость провайдера исчерпана; сообщение заменяется на Upstream load is saturated, please try again later
500build_request_failed, do_request_failed, invalid_responseСбой преобразования, провайдер недоступен, или Ark не вернул ID задачи
500get_channel_failedНе удалось выбрать канал на стороне релея (например, запись канала исчезла во время запроса)
503get_channel_failedКанал столкнулся с серьёзной ошибкой учётных данных или оплаты у провайдера; подробности скрыты
статус провайдераfail_to_fetch_taskArk отклонил отправку; HTTP-статус и сообщение — от Ark

Частые сообщения 400, ровно как они возвращаются:

messageПричина
prompt is requiredprompt отсутствует, пуст или состоит из пробелов
seconds must be between 1 and 3600duration / seconds верхнего уровня или числовой metadata.duration отрицателен либо слишком велик
unmarshal metadata failed: ...У поля metadata неверный тип; остальная часть сообщения называет его
model <id> is not supported by this channelИмя исходной или провайдерской модели совпадает с выведенным из эксплуатации Seedance 1.x
task_not_existID задачи неизвестен или принадлежит другому аккаунту

Сбои после отправки (модерация контента, таймаут провайдера, отмена) не проявляются как HTTP-ошибки. Они отражаются в записи задачи как FAILURE с fail_reason, и зарезервированная сумма возвращается. expired и cancelled сообщаются так же.

  • Эндпоинты другие. RouteAPI не предоставляет /api/v3/contents/generations/tasks, поэтому направить SDK Volcengine на наш базовый URL не получится.
  • Специфичные для Ark параметры передаются в metadata; общие поля (prompt, images, ratio, resolution, duration, generate_audio) можно отправлять и на верхнем уровне — они будут сопоставлены.
  • Возвращаемый task_id — идентификатор RouteAPI, а не Ark. Идентификатор Ark находится в data.data.id записи задачи.
  • Вы отправляете ID модели из каталога; канал сопоставляет его с именем модели Ark, поэтому к эндпоинт-ID Ark (ep-...) вы никогда не обращаетесь напрямую.
  • Список задач, отмена задачи, callback-уведомления и веб-поиск не поддерживаются; callback_url и tools отбрасываются.
  • Оплата идёт по токенам согласно таблице цен консоли, а не по собственной тарификации Ark.

Требуются bash, curl и jq.

#!/usr/bin/env bash
set -euo pipefail
: "${ROUTEAPI_KEY:?set ROUTEAPI_KEY first}"
BASE="${ROUTEAPI_BASE:-https://api.routeapi.ai}"
AUTH="Authorization: Bearer $ROUTEAPI_KEY"
TASK_ID=$(curl -sS -X POST "$BASE/v1/video/generations" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"model":"seedance-2.0-fast","prompt":"An orange cat stretching on a windowsill at sunrise","duration":5,"resolution":"720p","ratio":"16:9","generate_audio":false}' \
| jq -er .task_id)
echo "task: $TASK_ID"
for _ in $(seq 1 60); do
RESP=$(curl -sS "$BASE/v1/video/generations/$TASK_ID" -H "$AUTH")
STATUS=$(printf '%s' "$RESP" | jq -r .data.status)
echo "status: $STATUS $(printf '%s' "$RESP" | jq -r .data.progress)"
case "$STATUS" in
SUCCESS)
curl -sSL -o "$TASK_ID.mp4" "$BASE/v1/videos/$TASK_ID/content" -H "$AUTH"
echo "saved: $TASK_ID.mp4"
exit 0
;;
FAILURE)
echo "failed: $(printf '%s' "$RESP" | jq -r .data.fail_reason)"
exit 1
;;
esac
sleep 15
done
echo "timed out waiting for the task"
exit 1

Цикл ждёт 15 минут; увеличьте счётчик для длинных задач или высокого разрешения.