Генерация видео
AITUNNEL поддерживает генерацию видео по текстовому промпту (text-to-video), по опорному изображению (image-to-video) и по референсу (reference-to-video) через асинхронный API.
Процесс состоит из трёх шагов:
- Отправить задачу:
POST /v1/videos— мгновенно возвращаетid,polling_urlиstatus: "pending". - Опрашивать статус:
GET /v1/videos/{id}— повторять каждые 15–30 секунд доcompletedилиfailed. - Скачать результат:
GET /v1/videos/{id}/content— возвращает MP4.
Поддерживаемые модели
Актуальный список моделей генерации видео вместе с их возможностями (размеры, aspect ratio, длительности, поддержка аудио, image-to-video, референсов, passthrough-параметров и тарификации) доступен через публичный эндпоинт:
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
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')}")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"}`);
}
}# 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Параметры запроса
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
model | string | да | ID модели (например, seedance-2.0). Список — через публичный эндпоинт моделей |
prompt | string | да | Текстовое описание видео |
duration | integer | нет | Длительность в секундах (значение должно входить в supported_durations модели) |
resolution | string | нет | Разрешение выхода (например, 720p, 1080p) |
aspect_ratio | string | нет | Соотношение сторон (например, 16:9, 9:16) |
size | string | нет | Точные пиксели WIDTHxHEIGHT. Альтернатива паре resolution + aspect_ratio |
frame_images | array | нет | Опорные кадры для image-to-video (first_frame, last_frame) |
input_references | array | нет | Референс-изображения для reference-to-video |
generate_audio | boolean | нет | Генерировать ли аудио (по умолчанию true для моделей с поддержкой) |
seed | integer | нет | Seed для детерминизма (не гарантируется всеми провайдерами) |
provider | object | нет | 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 с первым и/или последним кадром — модель сгенерирует переход между ними (или продолжение первого кадра).
{
"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.
{
"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:
{
"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)
{
"id": "abc123",
"polling_url": "https://api.aitunnel.ru/v1/videos/abc123",
"status": "pending"
}На этом шаге usage не возвращается — итоговая стоимость известна только после completed.
GET /v1/videos/{id} — статус
Поля расширяются по мере прогресса задачи.
Pending / in_progress:
{
"id": "abc123",
"polling_url": "https://api.aitunnel.ru/v1/videos/abc123",
"status": "in_progress"
}Completed:
{
"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:
{
"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-эндпоинту:
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и на странице моделей.
Смотрите также
- Видео запросы — отправка видео на вход моделям chat/completions (анализ, суммаризация).
- Генерация изображений — синхронная генерация изображений.
- Методы AITUNNEL — список всех поддерживаемых эндпоинтов.