> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Генерация видео Gemini Omni 1.2 Flash

> Видео по тексту и изображениям, референсы нескольких объектов, интерполяция первого и последнего кадров, редактирование и продолжение. До 4K, 24fps, со звуком.

> [!NOTE]
>
> Генерация по тексту и изображениям поддерживает целое число секунд от 3 до 15, по умолчанию 10. Интерполяция первого и последнего кадров и добавляемая часть продолжения ограничены 10 секундами. При редактировании `duration` игнорируется, а длительность исходного видео сохраняется. Входное видео по умолчанию редактируется; для продолжения требуется `"omni_reference_task_type": "extend"`.

```bash cURL theme={null}
curl --request POST \
  --url https://api.apimart.ai/v1/videos/generations \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "gemini-omni-1.2-flash",
    "prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 15
  }'
```

```python Python theme={null}
import time
import requests

base_url = "https://api.apimart.ai"
headers = {"Authorization": "Bearer <token>"}
payload = {
    "model": "gemini-omni-1.2-flash",
    "prompt": "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 15,
}
response = requests.post(
    f"{base_url}/v1/videos/generations",
    headers=headers, json=payload, timeout=30,
)
response.raise_for_status()
task_id = response.json()["data"][0]["task_id"]
print(task_id)

deadline = time.monotonic() + 600
while time.monotonic() < deadline:
    response = requests.get(
        f"{base_url}/v1/tasks/{task_id}", headers=headers, timeout=30,
    )
    response.raise_for_status()
    task = response.json()["data"]
    if task["status"] == "completed":
        print(task["result"]["videos"][0]["url"][0])
        break
    if task["status"] == "failed":
        raise RuntimeError(task["error"]["message"])
    time.sleep(5)
else:
    raise TimeoutError(f"Continue polling task {task_id}")
```

```javascript JavaScript theme={null}
const baseUrl = "https://api.apimart.ai";
const headers = {
  Authorization: "Bearer <token>",
  "Content-Type": "application/json",
};
const response = await fetch(`${baseUrl}/v1/videos/generations`, {
  method: "POST",
  headers,
  signal: AbortSignal.timeout(30_000),
  body: JSON.stringify({
    model: "gemini-omni-1.2-flash",
    prompt: "A marble rolling fast on a chain reaction style track, continuous smooth shot.",
    aspect_ratio: "16:9",
    resolution: "720p",
    duration: 15,
  }),
});
if (!response.ok) throw new Error(await response.text());
const taskId = (await response.json()).data[0].task_id;
console.log(taskId);

async function waitForTask(taskId) {
  const deadline = Date.now() + 600_000;
  while (Date.now() < deadline) {
    const response = await fetch(`${baseUrl}/v1/tasks/${taskId}`, {
      headers,
      signal: AbortSignal.timeout(30_000),
    });
    if (!response.ok) throw new Error(await response.text());
    const task = (await response.json()).data;
    if (task.status === "completed") return task.result.videos[0].url[0];
    if (task.status === "failed") throw new Error(task.error.message);
    await new Promise(resolve => setTimeout(resolve, 5000));
  }
  throw new Error(`Continue polling task ${taskId}`);
}
console.log(await waitForTask(taskId));
```

```json 200 theme={null}
{
  "code": 200,
  "data": [
    {
      "status": "submitted",
      "task_id": "task_01EXAMPLE"
    }
  ]
}
```

## Аутентификация

**Authorization** `string` *required*

Используйте Bearer Token. Получите ключ на [странице управления API Key](https://apimart.ai/keys). Отправляйте запросы с `Content-Type: application/json`.

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

**model** `string` *required*

Укажите `gemini-omni-1.2-flash`.

**prompt** `string` *required*

Обязательные текстовые инструкции: описание сцены для генерации по тексту либо движения, стиля и изменений для остальных режимов. `prompt` обязателен даже при передаче референсов, первого/последнего кадра, видео или `extend_from_task_id`. Без него возвращается HTTP 400.

**duration** `integer` (default: 10)

Длительность видео, создаваемого по тексту или изображениям: целое число от `3` до `15`, по умолчанию `10`. Для интерполяции первого/последнего кадров и продолжения допустимы только `3`–`10` секунд. При продолжении это длина добавляемого фрагмента; результат включает исходное видео и добавленную часть. При редактировании `duration` игнорируется, а длительность исходного видео сохраняется. Значения параметра вне допустимого диапазона приводят к ошибке задачи `invalid_duration`.

**resolution** `string` (default: 720p)

`360p` / `720p` / `1080p` / `4k`, без учёта регистра. `2160p` соответствует `4k`. `1080p` и `4k` получаются повышением разрешения. Разрешение влияет на выходные токены и резервируемую сумму. Другие значения приводят к ошибке задачи `invalid_resolution`.

**aspect\_ratio** `string` (default: 16:9)

Только `16:9` (горизонтальное, по умолчанию) и `9:16` (вертикальное). Другие значения обрабатываются как `16:9`.

**image\_urls** `string[]`

Массив референсов: только общедоступные прямые HTTP(S)-ссылки на изображения. Data URL и Base64 не поддерживаются. Одно изображение служит начальным кадром, несколько — референсами объектов. Всего до 10 изображений, включая первый и последний кадры. Для персонажей рекомендуется не более 2 персонажей и до 3 изображений каждого, суммарно не более 6.

**first\_frame\_image** `string`

Первый кадр. Самостоятельно задаёт начальное изображение, а вместе с `last_frame_image` включает интерполяцию между кадрами. Поддерживаются только общедоступные прямые HTTP(S)-ссылки на изображения.

**last\_frame\_image** `string`

Последний кадр. Требует `first_frame_image`, иначе задача завершается с `invalid_frame_images`. Соотношение сторон обоих изображений должно совпадать с `aspect_ratio`. Поддерживаются только общедоступные прямые HTTP(S)-ссылки на изображения.

**image\_with\_roles** `object[]`

Массив изображений с ролями — альтернатива прямым полям первого/последнего кадров. Выберите один способ указания. Все используемые изображения входят в общий лимит 10.

**Элемент массива**

**url** `string` *required*

Поддерживаются только общедоступные прямые HTTP(S)-ссылки на изображения.

**role** `string` *required*

`first_frame` — первый кадр, `last_frame` — последний. Остальные роли считаются референсами. Последний кадр требует первого.

**video\_urls** `string[]`

Видео для редактирования или продолжения: максимум 1 ролик длительностью до 15 секунд. Поддерживаются только общедоступные прямые HTTP(S)-ссылки на видео. Data URL и Base64 не поддерживаются. По умолчанию выполняется редактирование.

**omni\_reference\_task\_type** `string` (default: auto)

Тип задачи: `auto` (по умолчанию, определяется по входным данным) / `edit` (редактирование) / `extend` (продолжение) / `reference` (несколько изображений-референсов). Также принимаются `text_to_video` / `image_to_video` / `reference_to_video`. Если параметр не задан или равен `auto`, `video_urls` и `extend_from_task_id` по умолчанию запускают редактирование. Для продолжения явно укажите `extend`.

**extend\_from\_task\_id** `string`

ID вашей предыдущей задачи генерации для повторного использования видео без загрузки. По умолчанию видео редактируется. С `"omni_reference_task_type": "extend"` в конец добавляется фрагмент длиной до 10 секунд.

## Возможности и ограничения

* Выходное видео имеет 24fps и содержит речь, музыку или звуковые эффекты. Нужный звук можно описать в `prompt`.
* Аудиовход, системные промпты, `temperature` и параметры негативного промпта не поддерживаются. Исключения указывайте прямо в `prompt`.
* Региональные ограничения поставщика: в ЕЭЗ, Швейцарии и Великобритании не поддерживаются редактирование и продолжение загруженных видео, а также редактирование изображений с несовершеннолетними.
* Все результаты содержат невидимый водяной знак SynthID.

## Примеры

Отправляйте каждый JSON в `POST /v1/videos/generations`. Замените ссылки и ID задач из примеров своими доступными материалами.

### Вертикальное видео 4K на 15 секунд

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "Aerial shot over a misty mountain lake at sunrise, birds flying, slow forward camera move.",
  "aspect_ratio": "9:16",
  "resolution": "4k",
  "duration": 15
}
```

### Генерация по изображениям и референсы объектов

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "The cat playfully bats at the ball of yarn.",
  "image_urls": [
    "https://example.com/cat.png",
    "https://example.com/yarn.png"
  ],
  "duration": 12
}
```

### Интерполяция первого и последнего кадров

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "Smooth transition, camera slowly pushes in.",
  "first_frame_image": "https://example.com/start.jpg",
  "last_frame_image": "https://example.com/end.jpg",
  "aspect_ratio": "16:9",
  "duration": 8
}
```

### Указание кадров через роли

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "A smooth cinematic transition from sunrise to a starry night.",
  "image_with_roles": [
    {
      "url": "https://example.com/sunrise.jpg",
      "role": "first_frame"
    },
    {
      "url": "https://example.com/night.jpg",
      "role": "last_frame"
    }
  ],
  "duration": 8
}
```

### Редактирование видео

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "Make the violin invisible. Keep everything else the same.",
  "video_urls": [
    "https://example.com/clip.mp4"
  ]
}
```

При редактировании длительность результата совпадает с исходным видео; `duration` не влияет на неё.

Используйте короткие и конкретные инструкции. Для локального изменения можно добавить `Keep everything else the same`.

### Продолжение существующей задачи

```json theme={null}
{
  "model": "gemini-omni-1.2-flash",
  "prompt": "The camera continues panning across the mountains.",
  "extend_from_task_id": "task_01PREVIOUS",
  "omni_reference_task_type": "extend",
  "duration": 8
}
```

Для продолжения загруженного видео замените `extend_from_task_id` на `video_urls`, сохранив `"omni_reference_task_type": "extend"`. Результат содержит исходное видео и фрагмент, добавленный в конец. `duration` задаёт только длину новой части, не более 10 секунд; оплачиваются только добавленные секунды. Например, исходное видео длиной 5 секунд с `duration: 4` даёт результат около 9 секунд.

## Ответ на отправку и проверка задачи

Успешная отправка возвращает HTTP 200. ID находится в `data[0].task_id`. Проверяйте [статус задачи](https://docs.apimart.ai/ru/api-reference/tasks/status.md) каждые 5–10 секунд до `completed` или `failed`. Рекомендуемое общее ожидание — 10 минут. При тайм-ауте клиента продолжайте проверять исходную задачу, не отправляя её повторно.

```bash theme={null}
curl --request GET \
  --url https://api.apimart.ai/v1/tasks/task_01EXAMPLE \
  --header 'Authorization: Bearer <token>'
```

Ориентиры: видео 360p на 15 секунд генерируется примерно за 30 секунд, а 4K на 15 секунд — примерно за 5 минут. Ориентируйтесь на фактический статус задачи.

```json theme={null}
{
  "code": 200,
  "data": {
    "id": "task_01EXAMPLE",
    "status": "completed",
    "progress": 100,
    "result": {
      "videos": [
        {
          "url": [
            "https://cdn.example.com/gemini_omni_video.mp4"
          ]
        }
      ]
    }
  }
}
```

`data` в ответе проверки — объект задачи. `data.result.videos[0].url` — массив; первая ссылка находится в `data.result.videos[0].url[0]`. Видео можно воспроизвести или скачать; для долгого хранения сохраните его у себя. `data.cost` — итоговая стоимость в долларах США.

| Статус | Действие |
| - | - |
| `pending` / `processing` | Продолжайте опрос; прогресс доступен в `data.progress`. |
| `completed` | Получите ссылку и сохраните видео. |
| `failed` | Прочитайте `data.error.message`. Неуспешные задачи не оплачиваются. |

## Оплата и резервирование баланса

Оплата по токенам: разрешение влияет на число выходных токенов в секунду. При генерации по тексту или изображениям `duration` задаёт длительность результата. При редактировании параметр игнорируется и сохраняется длительность исходного видео; при продолжении он задаёт только длину добавляемой части. Актуальные ставки указаны в [тарифах APIMart](https://apimart.ai/pricing).

При отправке резерв рассчитывается по разрешению и `max(10, duration)` секундам; при входном видео используется оценка в 15 секунд. Резерв не является итоговой оплатой. После успеха разница пересчитывается по фактическому использованию; итог находится в `data.cost`.

При продолжении оплачиваются только добавленные секунды. Неуспешные задачи не оплачиваются. Если баланса недостаточно для резерва, возвращается HTTP 402.

## Обработка ошибок

Ошибки параметров (`invalid_*` / `unsupported_*`) сразу переводят задачу в `failed` без оплаты. Проверяйте статус даже после успешной отправки.

| Ошибка / статус | Причина и действие |
| - | - |
| `invalid_duration` | `duration` вне диапазона 3–15 либо интерполяция / продолжение дольше 10 секунд. Укажите допустимое целое число. |
| `invalid_task_type` | Неподдерживаемое значение `omni_reference_task_type`. Используйте `auto` / `edit` / `extend` / `reference`; также принимаются `text_to_video` / `image_to_video` / `reference_to_video`. |
| `invalid_resolution` | Используйте `360p` / `720p` / `1080p` / `4k`; также допускается `2160p`. |
| `invalid_frame_images` | Передан только последний кадр. Добавьте первый. |
| `unsupported_image_count` | Более 10 изображений, включая первый/последний кадры. Уменьшите количество. |
| `unsupported_video_count` | Более 1 входного видео. Оставьте один ролик длиной до 15 секунд. |
| `HTTP 400` | Отсутствует обязательный `prompt`. Передавайте текстовые инструкции даже при наличии медиа. |
| `HTTP 401` | Недействительный ключ. Проверьте Authorization. |
| `HTTP 402` | Не хватает баланса для резерва. Пополните счёт или уменьшите разрешение. |
| `HTTP 429` | Превышен лимит запросов. Повторите с увеличивающейся задержкой. |
| `status: failed` | Ошибка поставщика или отклонение по правилам контента. Прочитайте `data.error.message` и измените запрос. |

## Частые вопросы

### Нужен ли `prompt`, если я передаю изображения или видео?

Да. `prompt` обязателен во всех режимах: генерация по изображениям, интерполяция первого/последнего кадра, редактирование, продолжение и повторное использование видео через `extend_from_task_id`. Если поле отсутствует, возвращается HTTP 400.

### Можно ли передавать изображения или видео напрямую в Base64?

Нет. `image_urls`, `first_frame_image`, `last_frame_image`, `image_with_roles[].url` и `video_urls` принимают только общедоступные прямые HTTP(S)-ссылки. Не передавайте `data:image/...`, `data:video/...` или строки Base64 без префикса.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.