Создаёт видео до 15 секунд со звуком из текста, изображения или референсов, а ещё правит и продлевает готовые ролики. Цена зависит от разрешения: 360p — 3 ₽/сек., 720p — 4 ₽/сек., 1080p — 6 ₽/сек., 4K — 12 ₽/сек.
Общая документация Public API · API-ключ можно создать в настройках аккаунта
Gemini Omni 1.2 Flash делает короткие ролики со звуком: рекламную сцену, вертикальное видео для соцсетей, оживление снимка или сюжет с вашими персонажами и товарами. Ещё она правит готовый ролик по текстовому заданию и дописывает к нему продолжение. Запрос создаёт асинхронную операцию, результат забирается по её id.
Отправьте POST https://bratuha.ru/api/v1/operations с заголовком Authorization: Bearer brth_ваш_ключ и JSON. В ответ сразу придут id операции и стартовый статус. Сохраните id, по нему проверяется результат.
Пять типов генерации: references - видео по референсам, text - видео из текста, image - видео из изображения, edit - редактирование видео, extend - продление видео: вернётся исходный ролик вместе с продолжением.
{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "text",
"prompt": "Бумажный кораблик плывёт по луже после дождя, низкая камера следует за ним, слышно капли и далёкий гром.",
"aspect_ratio": "9:16",
"resolution": "720p",
"duration": 8
}
}
tool содержит gemini-omni-1-2-flash, а input - настройки запуска. Набор полей зависит от типа генерации. У каждого нового запуска должен быть свой UUID в заголовке Idempotency-Key. Повтор того же запроса с тем же ключом не создаст вторую операцию.
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
generation_type | string | Да | Тип генерации: references, text, image, edit или extend. Если не передано, references, и тогда нужен reference_image_urls. |
prompt | string | Да | Задание, от 3 до 20000 символов. Для новых роликов опишите сцену, действие, камеру и звук, для редактирования - что изменить, для продления - что произойдёт дальше. |
first_frame_image | string | В image | Ссылка на изображение, с которого начнётся ролик. JPG, PNG или WebP. |
reference_image_urls | string[] | В references | Массив ссылок на изображения персонажей, предметов или стиля, от 1 до 10 файлов. JPG, PNG или WebP. |
edit_video_url | string | В edit | Ссылка на видео для правки. MP4, MOV или WebM, до 15 секунд и до 64 МБ. |
extend_video_url | string | В extend | Ссылка на видео для продления. MP4, MOV или WebM, до 15 секунд и до 64 МБ. |
aspect_ratio | string | Нет | auto, 16:9 или 9:16. auto берёт соотношение из загруженных изображений, а без них даёт 16:9. Если не передано, auto. В edit и extend не используется: ролик сохраняет соотношение сторон исходника. |
resolution | string | Нет | 360p, 720p, 1080p или 4k. От него зависит цена за секунду. Если не передано, 720p. |
duration | integer | В text, image, references | Длительность ролика, целое число от 3 до 15 секунд. Если не передано, 5. |
extend_duration |
Файлы передаются доступными http или https ссылками, данные файла в JSON не вставляются.
Замените примерные ссылки на собственные доступные файлы.
cURL:
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a54-8d3e-4b7a-9c10-2e5f7a8b9c01" \
-d '{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "text",
"prompt": "Бумажный кораблик плывёт по луже после дождя, низкая камера следует за ним, слышно капли и далёкий гром.",
"aspect_ratio": "9:16",
"resolution": "720p",
"duration": 8
}
}'
JavaScript / TypeScript:
const response = await fetch("https://bratuha.ru/api/v1/operations", {
method: "POST",
headers: {
Authorization: "Bearer brth_ваш_ключ",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "text",
"prompt": "Бумажный кораблик плывёт по луже после дождя, низкая камера следует за ним, слышно капли и далёкий гром.",
"aspect_ratio": "9:16",
"resolution": "720p",
"duration": 8
}
}),
});
const data = await response.json();
if (!response.ok) throw new Error(JSON.stringify(data));
console.log(data.id);
Python:
import json
import uuid
import requests
body = json.loads(r'''{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "text",
"prompt": "Бумажный кораблик плывёт по луже после дождя, низкая камера следует за ним, слышно капли и далёкий гром.",
"aspect_ratio": "9:16",
"resolution": "720p",
"duration": 8
}
}''')
response = requests.post(
"https://bratuha.ru/api/v1/operations",
headers={"Authorization": "Bearer brth_ваш_ключ",
"Idempotency-Key": str(uuid.uuid4())},
json=body,
timeout=60,
)
response.raise_for_status()
print(response.json()["id"])
cURL:
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a54-8d3e-4b7a-9c10-2e5f7a8b9c01" \
-d '{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "image",
"prompt": "Лёгкий ветер шевелит листья, камера медленно поднимается к кроне дерева.",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"resolution": "1080p",
"duration": 6
}
}'
JavaScript / TypeScript:
const response = await fetch("https://bratuha.ru/api/v1/operations", {
method: "POST",
headers: {
Authorization: "Bearer brth_ваш_ключ",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "image",
"prompt": "Лёгкий ветер шевелит листья, камера медленно поднимается к кроне дерева.",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"resolution": "1080p",
"duration": 6
}
}),
});
const data = await response.json();
if (!response.ok) throw new Error(JSON.stringify(data));
console.log(data.id);
Python:
import json
import uuid
import requests
body = json.loads(r'''{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "image",
"prompt": "Лёгкий ветер шевелит листья, камера медленно поднимается к кроне дерева.",
"first_frame_image": "https://cdn.example.com/first-frame.jpg",
"resolution": "1080p",
"duration": 6
}
}''')
response = requests.post(
"https://bratuha.ru/api/v1/operations",
headers={"Authorization": "Bearer brth_ваш_ключ",
"Idempotency-Key": str(uuid.uuid4())},
json=body,
timeout=60,
)
response.raise_for_status()
print(response.json()["id"])
cURL:
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a54-8d3e-4b7a-9c10-2e5f7a8b9c01" \
-d '{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "references",
"prompt": "Рыжий кот с первого снимка гоняет по кухне клубок со второго снимка.",
"reference_image_urls": [
"https://cdn.example.com/reference-cat.jpg",
"https://cdn.example.com/reference-yarn.jpg"
],
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 8
}
}'
JavaScript / TypeScript:
const response = await fetch("https://bratuha.ru/api/v1/operations", {
method: "POST",
headers: {
Authorization: "Bearer brth_ваш_ключ",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "references",
"prompt": "Рыжий кот с первого снимка гоняет по кухне клубок со второго снимка.",
"reference_image_urls": [
"https://cdn.example.com/reference-cat.jpg",
"https://cdn.example.com/reference-yarn.jpg"
],
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 8
}
}),
});
const data = await response.json();
if (!response.ok) throw new Error(JSON.stringify(data));
console.log(data.id);
Python:
import json
import uuid
import requests
body = json.loads(r'''{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "references",
"prompt": "Рыжий кот с первого снимка гоняет по кухне клубок со второго снимка.",
"reference_image_urls": [
"https://cdn.example.com/reference-cat.jpg",
"https://cdn.example.com/reference-yarn.jpg"
],
"aspect_ratio": "16:9",
"resolution": "720p",
"duration": 8
}
}''')
response = requests.post(
"https://bratuha.ru/api/v1/operations",
headers={"Authorization": "Bearer brth_ваш_ключ",
"Idempotency-Key": str(uuid.uuid4())},
json=body,
timeout=60,
)
response.raise_for_status()
print(response.json()["id"])
cURL:
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a54-8d3e-4b7a-9c10-2e5f7a8b9c01" \
-d '{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "edit",
"prompt": "Замени дневной свет на вечерний, всё остальное оставь как есть.",
"edit_video_url": "https://cdn.example.com/source-video.mp4",
"resolution": "720p"
}
}'
JavaScript / TypeScript:
const response = await fetch("https://bratuha.ru/api/v1/operations", {
method: "POST",
headers: {
Authorization: "Bearer brth_ваш_ключ",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "edit",
"prompt": "Замени дневной свет на вечерний, всё остальное оставь как есть.",
"edit_video_url": "https://cdn.example.com/source-video.mp4",
"resolution": "720p"
}
}),
});
const data = await response.json();
if (!response.ok) throw new Error(JSON.stringify(data));
console.log(data.id);
Python:
import json
import uuid
import requests
body = json.loads(r'''{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "edit",
"prompt": "Замени дневной свет на вечерний, всё остальное оставь как есть.",
"edit_video_url": "https://cdn.example.com/source-video.mp4",
"resolution": "720p"
}
}''')
response = requests.post(
"https://bratuha.ru/api/v1/operations",
headers={"Authorization": "Bearer brth_ваш_ключ",
"Idempotency-Key": str(uuid.uuid4())},
json=body,
timeout=60,
)
response.raise_for_status()
print(response.json()["id"])
cURL:
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2a54-8d3e-4b7a-9c10-2e5f7a8b9c01" \
-d '{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "extend",
"prompt": "Танцор заканчивает движение и кланяется, камера слегка отъезжает.",
"extend_video_url": "https://cdn.example.com/source-video.mp4",
"extend_duration": 4,
"resolution": "720p"
}
}'
JavaScript / TypeScript:
const response = await fetch("https://bratuha.ru/api/v1/operations", {
method: "POST",
headers: {
Authorization: "Bearer brth_ваш_ключ",
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "extend",
"prompt": "Танцор заканчивает движение и кланяется, камера слегка отъезжает.",
"extend_video_url": "https://cdn.example.com/source-video.mp4",
"extend_duration": 4,
"resolution": "720p"
}
}),
});
const data = await response.json();
if (!response.ok) throw new Error(JSON.stringify(data));
console.log(data.id);
Python:
import json
import uuid
import requests
body = json.loads(r'''{
"tool": "gemini-omni-1-2-flash",
"input": {
"generation_type": "extend",
"prompt": "Танцор заканчивает движение и кланяется, камера слегка отъезжает.",
"extend_video_url": "https://cdn.example.com/source-video.mp4",
"extend_duration": 4,
"resolution": "720p"
}
}''')
response = requests.post(
"https://bratuha.ru/api/v1/operations",
headers={"Authorization": "Bearer brth_ваш_ключ",
"Idempotency-Key": str(uuid.uuid4())},
json=body,
timeout=60,
)
response.raise_for_status()
print(response.json()["id"])
После создания ролика на 8 секунд в 720p:
{"id":"123e4567-e89b-42d3-a456-426614174000","status":"queued","tool":"gemini-omni-1-2-flash","cost":32,"balance_after":968,"created_at":"2026-11-07T06:00:00Z"}
После завершения:
{"id":"123e4567-e89b-42d3-a456-426614174000","status":"completed","tool":"gemini-omni-1-2-flash","cost":32,"created_at":"2026-11-07T06:00:00Z","completed_at":"2026-11-07T06:01:30Z","result":{"type":"video","urls":["https://storage.bratuha.ru/results/example.mp4"]},"error":null}
Идентификаторы, баланс, время и адрес результата в этих ответах приведены для примера. Время готовности зависит от задания и разрешения. При failed читайте error: деньги за такую операцию возвращаются на баланс.
Запрашивайте GET /api/v1/operations/{id} по сохранённому идентификатору, например каждые 5-10 секунд:
curl -H "Authorization: Bearer brth_ваш_ключ" \
https://bratuha.ru/api/v1/operations/123e4567-e89b-42d3-a456-426614174000
При queued и processing продолжайте ожидание. При completed прочитайте результат, при failed или cancelled остановите опрос. Новый POST создаёт новую платную операцию, поэтому при обрыве связи сначала проверьте статус уже созданной.
Готовое видео находится в result: type равен video, а urls содержит массив со ссылкой для скачивания. Это MP4 со звуковой дорожкой, в 4K звук изредка отсутствует. Сохраняйте файл у себя после завершения операции.
Цена зависит от разрешения и числа оплачиваемых секунд.
| Разрешение | Цена за секунду | 5 секунд | 15 секунд |
|---|---|---|---|
| 360p | 3 ₽ | 15 ₽ | 45 ₽ |
| 720p | 4 ₽ | 20 ₽ | 60 ₽ |
| 1080p | 6 ₽ | 30 ₽ | 90 ₽ |
| 4K | 12 ₽ | 60 ₽ | 180 ₽ |
Какие секунды оплачиваются:
text, image и references - значение duration;edit - длина исходного видео, округлённая вверх до целой секунды;extend - только значение extend_duration, исходное видео в цену не входит.POST /api/v1/operations создаёт новую операцию при каждом новом Idempotency-Key, выполнение асинхронное.http или https ссылкам.edit и extend - один файл до 15 секунд и до 64 МБ. Более длинный ролик сначала обрежьте.edit длительность результата равна длительности исходника, поле duration там не применяется.extend результат - весь ролик: исходное видео и продолжение одним файлом, в выбранном разрешении. Если итог длиннее 15 секунд, для следующего продления его нужно обрезать.image и references различаются ролью картинки: в первом случае ролик начинается с неё, во втором она показывает, кто или что должно быть в кадре.integer |
| В extend |
| Сколько секунд добавить, целое число от 3 до 10. Если не передано, 5. |
use_negative_prompt | boolean | Нет | Включите true, чтобы применить negative_prompt. |
negative_prompt | string | Нет | Что не должно появиться в ролике, до 500 символов. Работает только вместе с use_negative_prompt: true. |