Skip to content

Генерация видео

AITUNNEL поддерживает генерацию видео по текстовому промпту (text-to-video), по опорному изображению (image-to-video) и по референсу (reference-to-video) через асинхронный API.

Процесс состоит из трёх шагов:

  1. Отправить задачу: POST /v1/videos — мгновенно возвращает id, polling_url и status: "pending".
  2. Опрашивать статус: GET /v1/videos/{id} — повторять каждые 15–30 секунд до completed или failed.
  3. Скачать результат: GET /v1/videos/{id}/content — возвращает MP4.

Поддерживаемые модели

Актуальный список моделей генерации видео вместе с их возможностями (размеры, aspect ratio, длительности, поддержка аудио, image-to-video, референсов, passthrough-параметров и тарификации) доступен через публичный эндпоинт:

bash
curl https://api.aitunnel.ru/public/aitunnel/models/videos

Также его можно посмотреть на странице моделей.

Каждая запись содержит поля:

ПолеОписание
providerПровайдер модели (например, google, openai, bytedance, alibaba)
supported_resolutionsПоддерживаемые разрешения (например, 720p, 1080p, 4K)
supported_aspect_ratiosПоддерживаемые соотношения сторон (например, 16:9, 9:16)
supported_sizesТочные пиксельные размеры WIDTHxHEIGHT
supported_durationsДопустимые значения duration в секундах
supported_frame_imagesТипы опорных кадров для image-to-video: first_frame, last_frame
supports_audioПоддерживает ли генерацию аудио
supports_seedПринимает ли параметр seed
supports_reference_imagesПоддерживает ли input_references (reference-to-video)
allowed_passthrough_parametersРазрешённые ключи в provider.options.<slug>.parameters

Тарификация

Стоимость зависит от модели, разрешения и длительности:

  • В момент отправки задачи мы резервируем максимальную возможную стоимость запроса (worst-case) на вашем балансе.
  • Когда задача завершается (completed), мы списываем фактическую стоимость и возвращаем разницу на баланс.
  • Если задача упала (failed) — вся зарезервированная сумма возвращается автоматически.
  • Итоговая стоимость в рублях приходит в поле usage.cost_rub ответа GET /v1/videos/{id}, но только после статуса completed.

Отправка задачи

Базовый text-to-video

python
import os
import time
import requests

API_KEY = os.environ["AITUNNEL_API_KEY"]
BASE = "https://api.aitunnel.ru/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

resp = requests.post(
    f"{BASE}/videos",
    headers=headers,
    json={
        "model": "seedance-2.0-fast",
        "prompt": "A golden retriever playing fetch on a sunny beach, waves crashing behind",
        "size": "1280x720",
        "duration": 5,
    },
)
resp.raise_for_status()
job = resp.json()
job_id = job["id"]
print("Job submitted:", job_id, job["status"])

while True:
    time.sleep(15)
    status = requests.get(f"{BASE}/videos/{job_id}", headers=headers).json()
    print("Status:", status["status"])
    if status["status"] == "completed":
        video = requests.get(status["unsigned_urls"][0], headers=headers)
        with open("output.mp4", "wb") as f:
            f.write(video.content)
        print("Saved: output.mp4, cost:", status["usage"]["cost_rub"], "RUB")
        break
    if status["status"] == "failed":
        raise RuntimeError(f"Generation failed: {status.get('error')}")
typescript
const BASE = "https://api.aitunnel.ru/v1";
const headers = {
  Authorization: `Bearer ${process.env.AITUNNEL_API_KEY}`,
  "Content-Type": "application/json",
};

const submit = await fetch(`${BASE}/videos`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    model: "seedance-2.0-fast",
    prompt: "A golden retriever playing fetch on a sunny beach, waves crashing behind",
    size: "1280x720",
    duration: 5,
  }),
});
const job = await submit.json();
console.log("Job submitted:", job.id, job.status);

while (true) {
  await new Promise((r) => setTimeout(r, 15_000));
  const poll = await fetch(`${BASE}/videos/${job.id}`, { headers });
  const status = await poll.json();
  console.log("Status:", status.status);

  if (status.status === "completed") {
    const video = await fetch(status.unsigned_urls[0], { headers });
    const buf = Buffer.from(await video.arrayBuffer());
    require("fs").writeFileSync("output.mp4", buf);
    console.log("Cost:", status.usage.cost_rub, "RUB");
    break;
  }
  if (status.status === "failed") {
    throw new Error(`Generation failed: ${status.error ?? "unknown"}`);
  }
}
shell
# 1. Отправить задачу
curl -X POST "https://api.aitunnel.ru/v1/videos" \
  -H "Authorization: Bearer $AITUNNEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.0-fast",
    "prompt": "A golden retriever playing fetch on a sunny beach",
    "size": "1280x720",
    "duration": 5
  }'
# => { "id": "abc123", "polling_url": "https://api.aitunnel.ru/v1/videos/abc123", "status": "pending" }

# 2. Опросить статус (повторять до completed/failed)
curl "https://api.aitunnel.ru/v1/videos/abc123" \
  -H "Authorization: Bearer $AITUNNEL_API_KEY"

# 3. Скачать видео после completed
curl -L "https://api.aitunnel.ru/v1/videos/abc123/content?index=0" \
  -H "Authorization: Bearer $AITUNNEL_API_KEY" \
  --output video.mp4

Параметры запроса

ПараметрТипОбязательныйОписание
modelstringдаID модели (например, seedance-2.0). Список — через публичный эндпоинт моделей
promptstringдаТекстовое описание видео
durationintegerнетДлительность в секундах (значение должно входить в supported_durations модели)
resolutionstringнетРазрешение выхода (например, 720p, 1080p)
aspect_ratiostringнетСоотношение сторон (например, 16:9, 9:16)
sizestringнетТочные пиксели WIDTHxHEIGHT. Альтернатива паре resolution + aspect_ratio
frame_imagesarrayнетОпорные кадры для image-to-video (first_frame, last_frame)
input_referencesarrayнетРеференс-изображения для reference-to-video
generate_audiobooleanнетГенерировать ли аудио (по умолчанию true для моделей с поддержкой)
seedintegerнетSeed для детерминизма (не гарантируется всеми провайдерами)
providerobjectнетPassthrough-параметры провайдера

Указывайте duration явно

Если duration не задан, биллинг использует максимальную длительность модели для расчёта резерва, и вы переплатите до получения результата (избыток вернётся после completed). Явное duration даёт минимальный резерв сразу.

Поддерживаемые разрешения и aspect ratio

Общий набор значений по всем моделям (конкретные опции зависят от модели — сверяйтесь с её supported_resolutions / supported_aspect_ratios / supported_sizes):

  • Разрешения: 480p, 720p, 1080p, 1K, 2K, 4K
  • Aspect ratios: 16:9, 9:16, 1:1, 4:3, 3:4, 21:9, 9:21

Image-to-Video (опорные кадры)

Передайте массив frame_images с первым и/или последним кадром — модель сгенерирует переход между ними (или продолжение первого кадра).

json
{
  "model": "wan-2.7",
  "prompt": "A character walking through a misty forest",
  "frame_images": [
    {
      "type": "image_url",
      "image_url": { "url": "https://example.com/first-frame.png" },
      "frame_type": "first_frame"
    }
  ],
  "resolution": "1080p",
  "duration": 5
}

Для указания последнего кадра используйте "frame_type": "last_frame". Поддерживаемые типы опорных кадров для модели указаны в поле supported_frame_images публичного эндпоинта.

Reference-to-Video (визуальный референс)

input_references — референсные изображения для стиля или содержания, а не покадровая основа. Поддерживается моделями, у которых supports_reference_images: true.

json
{
  "model": "seedance-1-5-pro",
  "prompt": "A colossal solar flare beside a planet",
  "input_references": [
    {
      "type": "image_url",
      "image_url": { "url": "https://example.com/style-ref.png" }
    }
  ],
  "resolution": "1080p",
  "duration": 6
}

Комбинация frame_images + input_references

Если заданы оба поля, frame_images имеет приоритет и запрос обрабатывается как image-to-video.

Passthrough-параметры провайдера

Некоторые модели принимают специфичные опции через поле provider.options.<slug>.parameters:

json
{
  "model": "veo-3.1",
  "prompt": "A time-lapse of a flower blooming",
  "provider": {
    "options": {
      "google-vertex": {
        "parameters": {
          "personGeneration": "allow",
          "negativePrompt": "blurry, low quality"
        }
      }
    }
  }
}

Разрешённые ключи для каждой модели приходят в поле allowed_passthrough_parameters публичного эндпоинта моделей. Всё, что не входит в этот список, будет отфильтровано и залогировано, но не приведёт к ошибке.

Формат ответов

POST /v1/videos — отправка (202 Accepted)

json
{
  "id": "abc123",
  "polling_url": "https://api.aitunnel.ru/v1/videos/abc123",
  "status": "pending"
}

На этом шаге usage не возвращается — итоговая стоимость известна только после completed.

GET /v1/videos/{id} — статус

Поля расширяются по мере прогресса задачи.

Pending / in_progress:

json
{
  "id": "abc123",
  "polling_url": "https://api.aitunnel.ru/v1/videos/abc123",
  "status": "in_progress"
}

Completed:

json
{
  "id": "abc123",
  "generation_id": "gen-1234567890-abcdef",
  "polling_url": "https://api.aitunnel.ru/v1/videos/abc123",
  "status": "completed",
  "unsigned_urls": [
    "https://api.aitunnel.ru/v1/videos/abc123/content?index=0"
  ],
  "model": "seedance-2.0-fast",
  "usage": {
    "cost_rub": 47.92
  }
}

Failed:

json
{
  "id": "abc123",
  "status": "failed",
  "error": "Provider rejected the prompt due to content policy",
  "model": "seedance-2.0-fast",
  "usage": {
    "cost_rub": 0
  }
}

Возможные статусы

СтатусОписание
pendingЗадача принята и стоит в очереди
in_progressИдёт генерация
completedВидео готово, можно скачивать
failedГенерация упала (см. поле error); резерв полностью возвращён

Скачивание видео

После completed — используйте либо URL из unsigned_urls[0], либо обращайтесь напрямую к content-эндпоинту:

bash
curl -L "https://api.aitunnel.ru/v1/videos/abc123/content?index=0" \
  -H "Authorization: Bearer $AITUNNEL_API_KEY" \
  --output video.mp4

Параметр index по умолчанию 0. Используйте другие значения, если модель вернула несколько выходных видео.

Авторизация обязательна

Content-эндпоинт требует тот же Authorization: Bearer заголовок, что и остальные запросы. Ссылки в unsigned_urls нельзя открывать в браузере без авторизации.

Лучшие практики

  • Подробные промпты — указывайте движение, ракурс, освещение, композицию сцены.
  • Разумный duration — чем короче, тем дешевле и быстрее. Задавайте явно, чтобы не резервировать максимум.
  • Интервал опроса — 15–30 секунд. Генерация занимает от 30 секунд до нескольких минут.
  • Всегда обрабатывайте failed — читайте поле error и логируйте его.
  • Качество референсов — для image-to-video и reference-to-video используйте изображения с разрешением, близким к выходному size.

Устранение неполадок

Задача надолго зависла в pending?

  • Нормально для тяжёлых моделей (veo-3.1, sora-2-pro на 1080p) — генерация может занять несколько минут.
  • Продолжайте опрос на обычном интервале.

400 Bad Request на POST /v1/videos?

  • Проверьте, что size / resolution / aspect_ratio / duration входят в capability-лист модели (supported_sizes, supported_resolutions, supported_aspect_ratios, supported_durations из эндпоинта моделей).
  • Для моделей с supports_reference_images: false поле input_references вернёт 400.
  • Поле frame_images работает только для моделей с непустым supported_frame_images.

status: "failed"?

  • Проверьте поле error — чаще всего это content-policy отказ или недоступное опорное изображение.
  • Убедитесь, что все URL в frame_images / input_references публично доступны и в поддерживаемом формате (JPEG / PNG / WebP).
  • Резерв уже возвращён на баланс — можно смело повторять.

Модель не найдена?

  • Используйте ID модели без префикса провайдера (например, seedance-2.0, а не bytedance/seedance-2.0).
  • Актуальный список доступен по GET https://api.aitunnel.ru/public/aitunnel/models/videos и на странице моделей.

Смотрите также

AITUNNEL