> Для получения чистого Markdown любой страницы добавьте .md к URL страницы.  
> Для полного индекса документации см. https://api.vega.chat/docs/llms.txt.  
> Для полного содержания документации см. https://api.vega.chat/docs/llms-full.txt.  
> Для интеграции AI‑клиентов (Claude Code, Cursor и др.) подключитесь к MCP‑серверу по адресу https://api.vega.chat/docs/_mcp/server.

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

VEGA поддерживает генерацию видео из текстовых подсказок (и необязательных референс‑изображений) через отдельный асинхронный API. Поддерживаемые модели, их возможности и цены можно посмотреть, отфильтровав наш [список моделей по видеовыходу](/aimodels?output_modalities=video).

Добавляете генерацию видео в приложение?  
[Кулинарная книга по генерации видео](/docs/cookbook/video-generation/choose-video-model) разбивает этот процесс на пошаговые рецепты по выбору модели, отправке задач text‑to‑video, использованию изображений, передаче параметров провайдера и обработке веб‑хуков.

Для переиспользуемых знаний агента между проектами установите  
[openrouter-video skill](https://github.com/OpenRouterTeam/skills/tree/main/skills/openrouter-video).

## Поиск моделей

Вы можете находить модели для генерации видео несколькими способами:

### Через API видеомоделей

Используйте специальный эндпоинт видеомоделей, чтобы получить список всех доступных моделей генерации видео вместе с поддерживаемыми параметрами:

```bash
curl "https://api.vega.chat/api/v1/videos/models"
```

Ответ возвращает массив `data`, где каждая модель содержит:

```json
{
  "data": [
    {
      "id": "google/veo-3.1",
      "canonical_slug": "google/veo-3.1",
      "name": "Google: Veo 3.1",
      "description": "...",
      "created": 1719792000,
      "supported_resolutions": ["720p", "1080p"],
      "supported_aspect_ratios": ["16:9", "9:16", "1:1"],
      "supported_sizes": ["1280x720", "1920x1080"],
      "pricing_skus": {
        "per-video-second": "0.50",
        "per-video-second-1080p": "0.75"
      },
      "allowed_passthrough_parameters": ["output_config"]
    }
  ]
}
```

| Поле                              | Описание                                                                 |
| --------------------------------- | ------------------------------------------------------------------------ |
| `id`                              | Слаг модели, используемый в запросах генерации                           |
| `canonical_slug`                  | Постоянный идентификатор модели                                          |
| `supported_resolutions`           | Список поддерживаемых разрешений вывода (например, `720p`, `1080p`)      |
| `supported_aspect_ratios`          | Список поддерживаемых соотношений сторон (например, `16:9`, `9:16`)    |
| `supported_sizes`                 | Список поддерживаемых размеров в пикселях (например, `1280x720`)        |
| `pricing_skus`                    | Информация о ценах по каждому SKU                                        |
| `allowed_passthrough_parameters`  | Параметры, специфичные для провайдера, которые можно передать через опцию `provider` |

Используйте этот эндпоинт, чтобы проверить, какие разрешения, соотношения сторон и параметры‑проброс поддерживаются каждой моделью перед отправкой запроса генерации.

### Через API моделей

Также можно использовать параметр запроса `output_modalities` в [API моделей](/docs/api-reference/models/get-models), чтобы найти модели генерации видео:

```bash
# Список только моделей генерации видео
curl "https://api.vega.chat/api/v1/models?output_modalities=video"
```

### На странице моделей

Перейдите на [страницу моделей](/models) и отфильтруйте по типу вывода, чтобы найти модели, способные генерировать видео. Ищите модели, у которых в `output_modalities` указано `"video"`.

## Как это работает

В отличие от генерации текста или изображений, генерация видео **асинхронна**, потому что создание видео занимает значительно больше времени. Рабочий процесс выглядит так:

1. **Отправка** запроса генерации на `POST /api/v1/videos`
2. **Получение** ID задачи и URL для опроса сразу же
3. **Опрос** URL (`GET /api/v1/videos/{jobId}`) до тех пор, пока статус не станет `completed`
4. **Скачивание** видео по URL контента (`GET /api/v1/videos/{jobId}/content`)

## Использование API

### Отправка запроса на генерацию видео

```python
import requests
import json
import time

url = "https://api.vega.chat/api/v1/videos"
headers = {
    "Authorization": f"Bearer {API_KEY_REF}",
    "Content-Type": "application/json"
}

payload = {
    "model": "{{MODEL}}",
    "prompt": "A golden retriever playing fetch on a sunny beach with waves crashing in the background"
}

# Шаг 1: Отправка запроса генерации
response = requests.post(url, headers=headers, json=payload)
result = response.json()

job_id = result["id"]
polling_url = result["polling_url"]
print(f"Job submitted: {job_id}")
print(f"Status: {result['status']}")

# Шаг 2: Опрос до завершения
while True:
    time.sleep(30)  # ждать 30 секунд между опросами
    poll_response = requests.get(polling_url, headers=headers)
    status = poll_response.json()

    print(f"Status: {status['status']}")

    if status["status"] == "completed":
        # Шаг 3: Скачивание видео
        content_url = status["unsigned_urls"][0]
        video_response = requests.get(content_url)
        with open("output.mp4", "wb") as f:
            f.write(video_response.content)
        print("Video saved to output.mp4")
        break
    elif status["status"] == "failed":
        print(f"Generation failed: {status.get('error', 'Unknown error')}")
        break
```

```typescript title="TypeScript (fetch)"
const headers = {
  Authorization: `Bearer ${API_KEY_REF}`,
  'Content-Type': 'application/json',
};

// Шаг 1: Отправка запроса генерации
const response = await fetch('https://api.vega.chat/api/v1/videos', {
  method: 'POST',
  headers,
  body: JSON.stringify({
    model: '{{MODEL}}',
    prompt: 'A golden retriever playing fetch on a sunny beach with waves crashing in the background',
  }),
});

const result = await response.json();
const jobId = result.id;
const pollingUrl = result.polling_url;
console.log(`Job submitted: ${jobId}`);
console.log(`Status: ${result.status}`);

// Шаг 2: Опрос до завершения
while (true) {
  await new Promise((resolve) => setTimeout(resolve, 30000)); // ждать 30 секунд
  const pollResponse = await fetch(pollingUrl, { headers });
  const status = await pollResponse.json();

  console.log(`Status: ${status.status}`);

  if (status.status === 'completed') {
    // Шаг 3: Скачивание видео
    const contentUrl = status.unsigned_urls[0];
    const videoResponse = await fetch(contentUrl);
    const videoBuffer = await videoResponse.arrayBuffer();
    // Сохраните или обработайте буфер видео
    console.log(`Video ready: ${contentUrl}`);
    break;
  } else if (status.status === 'failed') {
    console.error(`Generation failed: ${status.error ?? 'Unknown error'}`);
    break;
  }
}
```

```bash title="cURL"
# Шаг 1: Отправка запроса генерации
curl -X POST "https://api.vega.chat/api/v1/videos" \
  -H "Authorization: Bearer $VEGA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "{{MODEL}}",
    "prompt": "A golden retriever playing fetch on a sunny beach with waves crashing in the background"
  }'

# Ответ:
# {
#   "id": "<job_id>",
#   "polling_url": "https://api.vega.chat/api/v1/videos/<job_id>",
#   "status": "pending"
# }

# Шаг 2: Опрос статуса
curl "https://api.vega.chat/api/v1/videos/<job_id>" \
  -H "Authorization: Bearer $VEGA_API_KEY"

# Шаг 3: Как только статус станет "completed", скачайте из unsigned_urls[0]
```

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

| Параметр          | Тип     | Обязательно | Описание                                                                                                                                 |
| ----------------- | ------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `model`           | string  | Да          | Модель, используемая для генерации видео (например, `google/veo-3.1`)                                                                   |
| `prompt`          | string  | Да          | Текстовое описание генерируемого видео                                                                                                    |
| `duration`        | integer | Нет         | Длительность генерируемого видео в секундах                                                                                              |
| `resolution`     | string  | Нет         | Разрешение выходного видео (например, `720p`, `1080p`)                                                                                   |
| `aspect_ratio`   | string  | Нет         | Соотношение сторон выходного видео (например, `16:9`, `9:16`, `3:2`)                                                                   |
| `size`            | string  | Нет         | Точные пиксельные размеры в формате `WIDTHxHEIGHT` (например, `1280x720`). Взаимозаменяемо с `resolution` + `aspect_ratio`          |
| `frame_images`    | array   | Нет         | Изображения для первого/последнего кадра (image‑to‑video)                                                                               |
| `input_references`| array   | Нет         | Референс‑изображения для стилистического руководства (reference‑to‑video)                                                               |
| `generate_audio` | boolean | Нет         | Генерировать ли аудио вместе с видео. По умолчанию `true` для моделей, поддерживающих аудиовывод                                         |
| `seed`            | integer | Нет         | Сид для детерминированной генерации (не гарантируется всеми провайдерами)                                                             |
| `callback_url`    | string  | Нет         | URL для получения webhook‑уведомления по завершении задачи. Переопределяет URL обратного вызова, установленный на уровне рабочего пространства, если указан. Должен быть HTTPS |
| `provider`        | object  | Нет         | Конфигурация провайдера‑специфичных параметров                                                                                             |

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

* `480p`
* `720p`
* `1080p`
* `1K`
* `2K`
* `4K`

### Поддерживаемые соотношения сторон

* `16:9` — широкоформатный ландшафт  
* `9:16` — вертикальный/портретный  
* `1:1` — квадратный  
* `4:3` — стандартный ландшафт  
* `3:4` — стандартный портрет  
* `3:2` — фотографический ландшафт  
* `2:3` — фотографический портрет  
* `21:9` — ультраширокий  
* `9:21` — ультравысокий  

### Использование изображений

Существует два способа предоставить изображения, каждый из которых запускает разный режим генерации:

* **`frame_images`** — задаёт первое или последнее изображение кадра для **image‑to‑video** генерации. Каждый элемент должен включать `frame_type` со значением `first_frame` или `last_frame`.
* **`input_references`** — предоставляет стилистические или содержательные референс‑изображения для **reference‑to‑video** генерации. Модель использует их как визуальное руководство, а не как точные кадры.

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

#### Image‑to‑Video (`frame_images`)

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

#### Reference‑to‑Video (`input_references`)

```json
{
  "model": "alibaba/wan-2.7",
  "prompt": "A colossal solar flare beside a planet",
  "input_references": [
    {
      "type": "image_url",
      "image_url": {
        "url": "https://example.com/style-ref.png"
      }
    }
  ],
  "resolution": "1080p"
}
```

### Параметры, специфичные для провайдера

Можно передать провайдер‑специфичные опции через параметр `provider`. Опции индексируются по слагу провайдера, и только опции для выбранного провайдера будут переданы дальше:

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

Используйте [API видеомоделей](#через-api-видеомоделей), чтобы проверить, какие параметры‑проброс поддерживает каждая модель, через поле `allowed_passthrough_parameters`.

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

### Ответ на отправку (202 Accepted)

При отправке запроса генерации видео вы получаете мгновенный ответ с деталями задачи:

```json
{
  "id": "abc123",
  "polling_url": "https://api.vega.chat/api/v1/videos/abc123",
  "status": "pending"
}
```

### Ответ на опрос

При опросе статуса задачи ответ включает дополнительные поля по мере её выполнения:

```json
{
  "id": "abc123",
  "generation_id": "gen-1234567890-abcdef",
  "polling_url": "https://api.vega.chat/api/v1/videos/abc123",
  "status": "completed",
  "unsigned_urls": [
    "https://api.vega.chat/api/v1/videos/abc123/content?index=0"
  ],
  "usage": {
    "cost": 0.25,
    "is_byok": false
  }
}
```

### Статусы задач

| Статус        | Описание                                          |
| ------------- | ------------------------------------------------- |
| `pending`     | Задача отправлена и находится в очереди            |
| `in_progress` | Видео генерируется                                 |
| `completed`   | Видео готово к скачиванию                         |
| `failed`      | Генерация завершилась ошибкой (см. поле `error`)  |

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

Как только статус задачи станет `completed`, массив `unsigned_urls` будет содержать URL‑ы для скачивания сгенерированного видео. Можно также сразу использовать эндпоинт контента:

```bash
curl "https://api.vega.chat/api/v1/videos/{jobId}/content?index=0" \
  -H "Authorization: Bearer $VEGA_API_KEY" \
  --output video.mp4
```

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

## Веб‑хуки

Вместо опроса статуса задачи вы можете получать webhook‑уведомление по завершении генерации видео. Есть два способа задать URL обратного вызова:

1. **Для конкретного запроса**: передайте `callback_url` в теле запроса. Этот URL имеет приоритет над URL, заданным по умолчанию в рабочем пространстве.
2. **По умолчанию для рабочего пространства**: задайте URL обратного вызова в [настройках рабочего пространства](/workspaces). Он будет применяться ко всем запросам генерации видео, у которых не указан собственный `callback_url`.

### Полезная нагрузка веб‑хука

Когда задача переходит в терминальное состояние, на URL обратного вызова отправляется POST‑запрос с оболочкой события. Каждая доставка также содержит заголовок `X-OpenRouter-Idempotency-Key` вида `<job_id>-<status>` для безопасного дедуплирования повторных попыток.

`video.generation.completed`:

```json
{
  "type": "video.generation.completed",
  "created_at": "2026-04-24T12:00:00.000Z",
  "data": {
    "id": "abc123",
    "status": "completed",
    "generation_id": "gen-xyz789",
    "model": "google/veo-3.1",
    "unsigned_urls": [
      "https://api.vega.chat/api/v1/videos/abc123/content?index=0"
    ],
    "usage": {
      "cost": 0.5,
      "is_byok": false
    }
  }
}
```

`video.generation.failed`:

```json
{
  "type": "video.generation.failed",
  "created_at": "2026-04-24T12:00:00.000Z",
  "data": {
    "id": "abc123",
    "status": "failed",
    "generation_id": "gen-xyz789",
    "model": "google/veo-3.1",
    "error": "Content policy violation"
  }
}
```

`video.generation.cancelled`:

```json
{
  "type": "video.generation.cancelled",
  "created_at": "2026-04-24T12:00:00.000Z",
  "data": {
    "id": "abc123",
    "status": "cancelled",
    "generation_id": "gen-xyz789",
    "model": "google/veo-3.1",
    "error": "Job was cancelled"
  }
}
```

`video.generation.expired`:

```json
{
  "type": "video.generation.expired",
  "created_at": "2026-04-24T12:00:00.000Z",
  "data": {
    "id": "abc123",
    "status": "expired",
    "generation_id": "gen-xyz789",
    "model": "google/veo-3.1",
    "error": "Job exceeded maximum time to live"
  }
}
```

`generation_id` и `model` в `data` могут быть `null`, если задача завершилась ошибкой до того, как эти значения были присвоены (например, при раннем отказе валидации).

### Секрет подписи

В [настройках рабочего пространства](/workspaces) можно задать секрет подписи, чтобы проверять подлинность webhook‑полезных нагрузок от VEGA. При наличии секрета каждая доставка веб‑хука включает заголовок `X-OpenRouter-Signature`.

Подпись содержит метку времени и HMAC‑хеш:

```
X-OpenRouter-Signature: t=1234567890,v1=a1b2c3d4...
```

### Проверка подписи

Чтобы проверить подпись в вашем обработчике веб‑хука:

1. Извлеките метку времени (`t`) и хеш подписи (`v1`) из заголовка
2. Сформируйте подписываемый полезный груз: `{timestamp},{raw_request_body}` (соединённые запятой)
3. Вычислите HMAC‑SHA256 от этого груза, используя ваш секрет подписи в качестве ключа
4. Сравните полученный в шестнадцатеричном виде результат с значением `v1`

```typescript
import crypto from 'crypto';

const FIVE_MINUTES_IN_SECONDS = 300;

function verifyWebhookSignature(
  rawBody: string,
  signatureHeader: string,
  secret: string,
): boolean {
  const parts = signatureHeader.split(',');
  const timestamp = parts.find((p) => p.startsWith('t='))?.slice(2);
  const hash = parts.find((p) => p.startsWith('v1='))?.slice(3);

  if (!timestamp || !hash) {
    return false;
  }

  // Отклоняем метки времени старше 5 минут, чтобы предотвратить replay‑атаки
  const age = Math.floor(Date.now() / 1000) - Number(timestamp);
  if (Number.isNaN(age) || age > FIVE_MINUTES_IN_SECONDS) {
    return false;
  }

  const signedPayload = `${timestamp},${rawBody}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  if (expected.length !== hash.length) {
    return false;
  }

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(hash),
  );
}
```

Для проверки используйте **сырой запрос** (точные полученные байты). Парсинг и повторная сериализация JSON могут изменить порядок ключей или формат чисел, что приведёт к провалу проверки.

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

* **Подробные подсказки**: предоставляйте конкретные, описательные подсказки для лучшего качества видео. Указывайте детали движения, ракурсы камеры, освещение и композицию сцены.  
* **Подходящее разрешение**: более высокие разрешения требуют больше времени и стоят дороже. Выбирайте разрешение, соответствующее вашему случаю использования.  
* **Интервал опроса**: используйте разумный интервал опроса (например, 30 секунд), чтобы не перегружать API. Генерация видео обычно занимает от 30 секунд до нескольких минут в зависимости от модели и параметров.  
* **Обработка ошибок**: всегда проверяйте статус задачи на `failed` и корректно обрабатывайте поле `error`.  
* **Референс‑изображения**: при их использовании убедитесь, что они высокого качества и релевантны желаемому видеовыводу.  

## Отсутствие сохранения данных

Генерация видео **не подходит** для [Zero Data Retention (ZDR)](/docs/guides/features/zdr). Поскольку процесс асинхронный, сгенерированный видеоконтент должен временно храниться провайдером, чтобы его можно было получить после завершения генерации. Эта временная задержка не может быть обойдена.

Если у вас включено принудительное соблюдение ZDR (через [настройки аккаунта](/settings/privacy) или параметр запроса `zdr`), запросы генерации видео не будут маршрутизироваться.

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

**Задача «зависает» в `pending` надолго?**

* Генерация видео может занимать несколько минут в зависимости от модели, разрешения и нагрузки сервера.  
* Продолжайте опрашивать статус с регулярными интервалами.

**Генерация завершилась с ошибкой?**

* Проверьте поле `error` в ответе опроса для получения деталей.  
* Убедитесь, что модель поддерживает генерацию видео (`output_modalities` включает `"video"`).  
* Убедитесь, что подсказка соответствует рекомендациям модели.  
* Проверьте, что все референс‑изображения доступны и находятся в поддерживаемом формате.

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

* Используйте [API видеомоделей](#через-api-видеомоделей) или [страницу моделей](/models), чтобы найти доступные модели генерации видео.  
* Убедитесь, что слаг модели указан правильно (например, `google/veo-3.1`).