Skip to content

Получение статуса задачи видео

После отправки задачи через Создание задачи генерации видео опрашивайте GET /v1/video/generations/{task_id}, пока задача не достигнет конечного состояния, затем скачайте видео с GET /v1/videos/{task_id}/content. Опрос читает запись, которую RouteAPI обновляет в фоне, поэтому интервала в 10–15 секунд достаточно.

Получение записи задачи

Section titled “Получение записи задачи”
GET /v1/video/generations/{task_id}

Задачи привязаны к пользователю API Key: task_id, принадлежащий другому аккаунту, сообщается как task_not_exist.

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": 123456,
"action": "generate",
"status": "SUCCESS",
"progress": "100%",
"fail_reason": "",
"result_url": "https://...mp4",
"submit_time": 1792048458,
"start_time": 1792048461,
"finish_time": 1792048569,
"properties": {
"input": "",
"origin_model_name": "seedance-2.0-fast"
},
"data": { "id": "cgt-xxxxxxxx", "status": "succeeded" }
}
}
ПолеОписание
code"success" для читаемой задачи; при ошибке используется формат ошибки задачи, описанный ниже
data.idВнутренний ID строки; нигде в запросах не используется
data.task_idID задачи RouteAPI — значение для опроса и скачивания
data.statusNOT_START, SUBMITTED, QUEUED, IN_PROGRESS, SUCCESS или FAILURE
data.progressСтрока прогресса, например "30%" или "100%"
data.result_urlURL видео после успешного завершения. Может указывать на эндпоинт скачивания RouteAPI или напрямую на URL вышестоящего сервиса с ограниченным сроком жизни
data.fail_reasonПричина сбоя; в остальных случаях пусто
data.submit_time / start_time / finish_timeUnix-секунды. start_time и finish_time равны 0 до начала и завершения
data.created_at / updated_atUnix-секунды, время создания и последнего обновления строки
data.quotaКвота, списанная за задачу
data.platformЧисловой тип канала вышестоящего сервиса, выполнившего задачу
data.group / data.channel_id / data.user_idГруппа биллинга, канал и аккаунт-владелец. Полезно при обращении в поддержку
data.actionТип задачи: generate, textGenerate, firstTailGenerate, referenceGenerate или remixGenerate
data.propertiesСохранённые свойства: origin_model_name, upstream_model_name, а в input — снимок запроса к вышестоящему сервису, если адаптер его собирает. Для диагностики
data.dataПоследняя полезная нагрузка задачи от вышестоящего поставщика, сохранена для отладки. Её форма зависит от поставщика
СтатусЗначениеЧто делать
NOT_STARTСтрока создана, но вышестоящий сервис ещё не опрашивалсяПродолжать опрос
SUBMITTED / QUEUEDПринята, ожидает в очереди поставщикаПродолжать опрос
IN_PROGRESSИдёт генерацияПродолжать опрос
SUCCESSКонечный успехСкачать видео
FAILUREКонечная ошибкаПрочитать fail_reason; зарезервированная сумма уже возвращена

Только SUCCESS — конечный успех; FAILURE — конечная ошибка, и при её появлении зарезервированная сумма уже возвращена. Всё остальное означает, что нужно продолжать опрос.

import os
import time
import requests
BASE = "https://api.routeapi.ai"
HEADERS = {"Authorization": f"Bearer {os.environ['ROUTEAPI_KEY']}"}
task_id = requests.post(
f"{BASE}/v1/video/generations",
headers=HEADERS,
json={
"model": "seedance-2.0-fast",
"prompt": "An orange cat stretching on a windowsill at sunrise",
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
},
timeout=60,
).json()["task_id"]
while True:
task = requests.get(f"{BASE}/v1/video/generations/{task_id}", headers=HEADERS, timeout=30).json()["data"]
print(task["status"], task["progress"])
if task["status"] == "SUCCESS":
video = requests.get(f"{BASE}/v1/videos/{task_id}/content", headers=HEADERS, timeout=300)
video.raise_for_status()
with open(f"{task_id}.mp4", "wb") as f:
f.write(video.content)
break
if task["status"] == "FAILURE":
raise SystemExit(f"task failed: {task['fail_reason']}")
time.sleep(15)
#!/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":4,"resolution":"480p","ratio":"16:9"}' \
| 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=$(echo "$RESP" | jq -r .data.status)
echo "status: $STATUS $(echo "$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: $(echo "$RESP" | jq -r .data.fail_reason)"
exit 1
;;
esac
sleep 15
done
echo "timed out waiting for the task"
exit 1

Опрос GET /v1/video/generations/{task_id} обычно лишь читает локальную запись задачи, поэтому держите интервал 10–15 секунд и не нагружайте эндпоинт запросами без паузы.

GET /v1/videos/{task_id}/content

Потоково передаёт байты видео через RouteAPI, поэтому вызывающей стороне не нужно обращаться к хранилищу поставщика. Ответ содержит Cache-Control: public, max-age=86400 и Content-Type вышестоящего сервиса (по умолчанию video/mp4 для встроенных Base64-результатов).

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

Этот маршрут принимает API Key или сессию консоли и возвращает данные только задач, принадлежащих вызывающей стороне. Его ошибки используют объектную форму {"error": {"message": "...", "type": "..."}}:

СтатусЗначение
400Задача ещё не завершена; сообщение содержит текущий статус
404Задача неизвестна или принадлежит другому аккаунту
403Полученный URL видео отклонён правилами защиты исходящих запросов
500Не удалось прочитать строку задачи или её канал, либо разобрать URL видео
502Поставщик недоступен, вернул статус, отличный от 200, или URL видео пуст
СтатусКодЗначение
400task_not_existtask_id неизвестен или принадлежит другому аккаунту
500get_task_failedRouteAPI не смог прочитать собственную строку задачи
500marshal_response_failed, copy_response_body_failedRouteAPI не смог сериализовать или записать ответ

Запросы, отклонённые до маршрутизации, используют стандартное тело ошибки middleware {"error": {"message": ..., "type": "error", "code": ...}}, а не формат задачи.