LTX 2.3 API
LTX 2.3 - видеомодель с пятью режимами в одном вызове. Она снимает ролик по тексту или из картинки (до 20 секунд, вплоть до 4K и 50 кадров в секунду, со звуком), оживляет портрет под готовую озвучку, продлевает уже существующее видео и переснимает выбранный отрезок ролика. Удобна, когда в одной интеграции нужны и генерация, и доработка видео.
Основные сценарии:
- Видео из текста -
generation_type: "text_to_video".
- Видео из изображения -
generation_type: "image_to_video", картинка становится первым кадром, можно задать и последний.
- Говорящее фото -
generation_type: "talking_photo", портрет двигается и говорит под ваше аудио.
- Продление видео -
generation_type: "extend_video", модель досняет ролик в начале или в конце.
- Замена фрагмента -
generation_type: "retake_video", модель переснимает выбранный отрезок видео, звук или и то и другое.
Каждый вызов создаёт асинхронную операцию. После запуска сохраните id и проверяйте статус отдельным запросом.
Создание операции
- Endpoint:
POST /api/v1/operations
- Авторизация:
Authorization: Bearer brth_...
- Выполнение асинхронное: запрос сразу возвращает
id операции и стартовый статус queued.
Режим задаёт параметр generation_type:
text_to_video - видео из текста (prompt_text_image, aspect_ratio_text);
image_to_video - видео из изображения (prompt_text_image, image_url, по желанию end_image_url);
talking_photo - говорящее фото (image_url, audio_url);
extend_video - продление видео (video_url, extend_duration);
retake_video - замена фрагмента (video_url, retake_prompt, retake_start_time, retake_duration).
Какое поле длительности передавать
В режимах text_to_video и image_to_video длительность лежит в одном из трёх полей, в зависимости от модели, разрешения и частоты кадров:
| Модель | Разрешение и FPS | Поле | Значения |
|---|
pro | любые | duration_pro | 6, 8 или 10 |
fast | 1080p и 25 | duration_fast_extended | 6, 8, 10, 12, 14, 16, 18 или 20 |
fast | любое другое сочетание | duration_fast_limited | 6, 8 или 10 |
Поле, которое не подходит к выбранным параметрам, не учитывается: будет взята длительность по умолчанию, 6 секунд. Передавайте чётные значения из таблицы.
Тело запроса
{
"tool": "ltx-2-3",
"input": {
"...": "..."
}
}
tool - slug нейросети, всегда "ltx-2-3".
input - параметры запуска. Все поля передаются прямо внутри этого объекта, без дополнительной вложенности.
- Набор полей зависит от режима: поля чужого режима не учитываются ни в запуске, ни в цене.
Параметры
| Параметр | Тип | Обязательный | Описание |
|---|
generation_type | enum | Да | Режим: text_to_video, image_to_video, talking_photo, extend_video или retake_video. Если поле не передать, используется text_to_video. |
model_tier | enum | Да | Версия модели для text_to_video и image_to_video: fast - быстрее и дешевле, pro - качественнее, в полтора раза дороже. Если не указать - fast. |
prompt_text_image | string | Да, для text_to_video и image_to_video | Что происходит в ролике: сцена, действие, камера, звук. От 3 до 4000 символов. |
image_url | string (url) | Да, для image_to_video и talking_photo | Первый кадр ролика или портрет для говорящего фото. Один файл: jpg, jpeg, png или webp. |
use_end_image | boolean | Нет | Задать последний кадр в режиме image_to_video. По умолчанию false. |
end_image_url | string (url) | Да, если use_end_image: true | Последний кадр ролика. Только в image_to_video и только вместе с use_end_image: true, иначе не учитывается. Форматы те же. |
audio_url | string (url) | Да, для talking_photo | Озвучка для говорящего фото, длиной от 2 до 20 секунд. Форматы: mp3, wav, m4a, aac, flac, ogg, opus. От длины аудио зависят цена и длина ролика. |
prompt_talking_photo | string | Нет | Подсказка для говорящего фото: мимика, эмоции, движения головы. До 4000 символов. |
Ссылки на файлы передавайте как внешние http/https URL с подходящим расширением. Файл должен открываться без авторизации, размер - до 128 МБ.
Примеры запросов
Видео из текста
cURL
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "ltx-2-3",
"input": {
"generation_type": "text_to_video",
"model_tier": "fast",
"prompt_text_image": "Уютная пекарня рано утром, пекарь достаёт из печи противень с круассанами, от выпечки поднимается пар, камера медленно отъезжает",
"resolution": "1080p",
"fps": "25",
"aspect_ratio_text": "16:9",
"generate_audio": true,
"duration_fast_extended": 12
}
}'
JavaScript / TypeScript
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'ltx-2-3',
input: {
generation_type: 'text_to_video',
model_tier: 'fast',
prompt_text_image: 'Уютная пекарня рано утром, пекарь достаёт из печи противень с круассанами, от выпечки поднимается пар, камера медленно отъезжает',
resolution: '1080p',
fps: '25',
aspect_ratio_text: '16:9',
generate_audio: true,
duration_fast_extended: 12,
},
}),
})
const data = await response.json()
Python
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'ltx-2-3',
'input': {
'generation_type': 'text_to_video',
'model_tier': 'fast',
'prompt_text_image': 'Уютная пекарня рано утром, пекарь достаёт из печи противень с круассанами, от выпечки поднимается пар, камера медленно отъезжает',
'resolution': '1080p',
'fps': '25',
'aspect_ratio_text': '16:9',
'generate_audio': True,
'duration_fast_extended': 12,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Видео из текста в 4K без звука
cURL
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "ltx-2-3",
"input": {
"generation_type": "text_to_video",
"model_tier": "fast",
"prompt_text_image": "Аэросъёмка горного озера на рассвете, туман стелется над водой, камера медленно пролетает над берегом",
"resolution": "2160p",
"fps": "50",
"aspect_ratio_text": "9:16",
"generate_audio": false,
"duration_fast_limited": 6
}
}'
JavaScript / TypeScript
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'ltx-2-3',
input: {
generation_type: 'text_to_video',
model_tier: 'fast',
prompt_text_image: 'Аэросъёмка горного озера на рассвете, туман стелется над водой, камера медленно пролетает над берегом',
resolution: '2160p',
fps: '50',
aspect_ratio_text: '9:16',
generate_audio: false,
duration_fast_limited: 6,
},
}),
})
const data = await response.json()
Python
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'ltx-2-3',
'input': {
'generation_type': 'text_to_video',
'model_tier': 'fast',
'prompt_text_image': 'Аэросъёмка горного озера на рассвете, туман стелется над водой, камера медленно пролетает над берегом',
'resolution': '2160p',
'fps': '50',
'aspect_ratio_text': '9:16',
'generate_audio': False,
'duration_fast_limited': 6,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Видео из изображения
cURL
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "ltx-2-3",
"input": {
"generation_type": "image_to_video",
"model_tier": "fast",
"prompt_text_image": "Девушка оборачивается к камере и улыбается, ветер шевелит волосы, на фоне медленно проезжает трамвай",
"image_url": "https://cdn.example.com/source-image-1.jpg",
"resolution": "1080p",
"fps": "25",
"aspect_ratio_image": "auto",
"generate_audio": true,
"duration_fast_extended": 8
}
}'
JavaScript / TypeScript
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'ltx-2-3',
input: {
generation_type: 'image_to_video',
model_tier: 'fast',
prompt_text_image: 'Девушка оборачивается к камере и улыбается, ветер шевелит волосы, на фоне медленно проезжает трамвай',
image_url: 'https://cdn.example.com/source-image-1.jpg',
resolution: '1080p',
fps: '25',
aspect_ratio_image: 'auto',
generate_audio: true,
duration_fast_extended: 8,
},
}),
})
const data = await response.json()
Python
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'ltx-2-3',
'input': {
'generation_type': 'image_to_video',
'model_tier': 'fast',
'prompt_text_image': 'Девушка оборачивается к камере и улыбается, ветер шевелит волосы, на фоне медленно проезжает трамвай',
'image_url': 'https://cdn.example.com/source-image-1.jpg',
'resolution': '1080p',
'fps': '25',
'aspect_ratio_image': 'auto',
'generate_audio': True,
'duration_fast_extended': 8,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Видео из изображения с первым и последним кадром
cURL
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "ltx-2-3",
"input": {
"generation_type": "image_to_video",
"model_tier": "pro",
"prompt_text_image": "Бутон розы медленно раскрывается, капли росы блестят на лепестках, мягкий утренний свет",
"image_url": "https://cdn.example.com/first-frame-1.jpg",
"use_end_image": true,
"end_image_url": "https://cdn.example.com/last-frame-1.jpg",
"resolution": "1440p",
"fps": "24",
"aspect_ratio_image": "9:16",
"generate_audio": false,
"duration_pro": 6
}
}'
JavaScript / TypeScript
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'ltx-2-3',
input: {
generation_type: 'image_to_video',
model_tier: 'pro',
prompt_text_image: 'Бутон розы медленно раскрывается, капли росы блестят на лепестках, мягкий утренний свет',
image_url: 'https://cdn.example.com/first-frame-1.jpg',
use_end_image: true,
end_image_url: 'https://cdn.example.com/last-frame-1.jpg',
resolution: '1440p',
fps: '24',
aspect_ratio_image: '9:16',
generate_audio: false,
duration_pro: 6,
},
}),
})
const data = await response.json()
Python
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'ltx-2-3',
'input': {
'generation_type': 'image_to_video',
'model_tier': 'pro',
'prompt_text_image': 'Бутон розы медленно раскрывается, капли росы блестят на лепестках, мягкий утренний свет',
'image_url': 'https://cdn.example.com/first-frame-1.jpg',
'use_end_image': True,
'end_image_url': 'https://cdn.example.com/last-frame-1.jpg',
'resolution': '1440p',
'fps': '24',
'aspect_ratio_image': '9:16',
'generate_audio': False,
'duration_pro': 6,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Говорящее фото
cURL
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "ltx-2-3",
"input": {
"generation_type": "talking_photo",
"image_url": "https://cdn.example.com/portrait-1.jpg",
"audio_url": "https://cdn.example.com/speech-1.mp3",
"prompt_talking_photo": "Спокойная дружелюбная мимика, лёгкие кивки головой, взгляд в камеру"
}
}'
JavaScript / TypeScript
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'ltx-2-3',
input: {
generation_type: 'talking_photo',
image_url: 'https://cdn.example.com/portrait-1.jpg',
audio_url: 'https://cdn.example.com/speech-1.mp3',
prompt_talking_photo: 'Спокойная дружелюбная мимика, лёгкие кивки головой, взгляд в камеру',
},
}),
})
const data = await response.json()
Python
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'ltx-2-3',
'input': {
'generation_type': 'talking_photo',
'image_url': 'https://cdn.example.com/portrait-1.jpg',
'audio_url': 'https://cdn.example.com/speech-1.mp3',
'prompt_talking_photo': 'Спокойная дружелюбная мимика, лёгкие кивки головой, взгляд в камеру',
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Продление видео
cURL
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "ltx-2-3",
"input": {
"generation_type": "extend_video",
"video_url": "https://cdn.example.com/source-video-1.mp4",
"extend_duration": 4,
"extend_mode": "end",
"extend_prompt": "Человек заканчивает фразу, машет рукой и выходит из кадра"
}
}'
JavaScript / TypeScript
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'ltx-2-3',
input: {
generation_type: 'extend_video',
video_url: 'https://cdn.example.com/source-video-1.mp4',
extend_duration: 4,
extend_mode: 'end',
extend_prompt: 'Человек заканчивает фразу, машет рукой и выходит из кадра',
},
}),
})
const data = await response.json()
Python
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'ltx-2-3',
'input': {
'generation_type': 'extend_video',
'video_url': 'https://cdn.example.com/source-video-1.mp4',
'extend_duration': 4,
'extend_mode': 'end',
'extend_prompt': 'Человек заканчивает фразу, машет рукой и выходит из кадра',
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Замена фрагмента
cURL
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "ltx-2-3",
"input": {
"generation_type": "retake_video",
"video_url": "https://cdn.example.com/source-video-1.mp4",
"retake_prompt": "Вместо чашки кофе в руке у человека букет жёлтых тюльпанов",
"retake_start_time": 2,
"retake_duration": 3,
"retake_mode": "replace_video"
}
}'
JavaScript / TypeScript
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'ltx-2-3',
input: {
generation_type: 'retake_video',
video_url: 'https://cdn.example.com/source-video-1.mp4',
retake_prompt: 'Вместо чашки кофе в руке у человека букет жёлтых тюльпанов',
retake_start_time: 2,
retake_duration: 3,
retake_mode: 'replace_video',
},
}),
})
const data = await response.json()
Python
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'ltx-2-3',
'input': {
'generation_type': 'retake_video',
'video_url': 'https://cdn.example.com/source-video-1.mp4',
'retake_prompt': 'Вместо чашки кофе в руке у человека букет жёлтых тюльпанов',
'retake_start_time': 2,
'retake_duration': 3,
'retake_mode': 'replace_video',
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Примеры ответов
Ответ после создания
{
"id": "op_uuid-123",
"status": "queued",
"tool": "ltx-2-3",
"cost": 72,
"balance_after": 928,
"created_at": "2026-09-30T19:51:58.703026+00:00"
}
Ответ после завершения
{
"id": "op_uuid-123",
"status": "completed",
"tool": "ltx-2-3",
"cost": 72,
"created_at": "2026-09-30T19:51:58.703026+00:00",
"completed_at": "2026-09-30T19:53:37.956264+00:00",
"result": {
"type": "video",
"urls": [
"https://storage.bratuha.ru/results/ltx-2-3/video-1.mp4"
]
},
"error_message": null
}
Ответ при ошибке
Если модель не смогла выполнить задачу, операция завершается со статусом failed, в result приходит null, а причина - в error_message. Списанная сумма возвращается на баланс. Например, так выглядит продление на 1 секунду:
{
"id": "op_uuid-123",
"status": "failed",
"tool": "ltx-2-3",
"cost": 18,
"created_at": "2026-09-30T19:51:19.675509+00:00",
"completed_at": "2026-09-30T19:51:26.963661+00:00",
"result": null,
"error_message": "Входное значение должно быть не меньше 2."
}
Проверка статуса
Сохраните id из ответа на создание и проверяйте операцию по нему:
GET /api/v1/operations/{id}
curl -H "Authorization: Bearer brth_ваш_ключ" \
https://bratuha.ru/api/v1/operations/op_uuid-123
async function waitForResult(id: string) {
while (true) {
const response = await fetch(`https://bratuha.ru/api/v1/operations/${id}`, {
headers: { Authorization: 'Bearer brth_ваш_ключ' },
})
const operation = await response.json()
if (operation.status === 'completed' || operation.status === 'failed') {
return operation
}
await new Promise((resolve) => setTimeout(resolve, 5000))
}
}
Продление на 2 секунды в пробном запуске заняло около 100 секунд, ролики из текста и изображения на 10-20 секунд и в 4K делаются дольше, до нескольких минут. Одну операцию можно опрашивать не чаще раза в секунду, разумный интервал - 5-10 секунд.
Формат результата
После завершения в result приходит одно видео:
{
"type": "video",
"urls": [
"https://storage.bratuha.ru/results/ltx-2-3/video-1.mp4"
]
}
type - всегда "video".
urls - массив с одной ссылкой на MP4.
- В режимах из текста и изображения длина ролика равна выбранной длительности, разрешение и FPS - выбранным. Звуковая дорожка есть при
generate_audio: true.
- Говорящее фото длится столько же, сколько аудио.
- Продление возвращает весь ролик целиком: исходное видео вместе с досьёмкой. В пробе 5-секундное видео с
extend_duration: 2 вернулось файлом на 7 секунд в 1920x1080 и 24 кадра в секунду, хотя исходник был 1310x720.
- Замена фрагмента тоже возвращает всё видео, в котором переснят только выбранный отрезок.
Ценообразование
Цена считается за секунду. Ставка зависит от режима, а в режимах из текста и изображения - ещё от модели и разрешения. FPS и звук на цену не влияют.
Видео из текста и из изображения, оплачивается выбранная длительность:
| Модель | 1080p | 1440p | 2160p |
|---|
fast | 8 ₽/сек. | 16 ₽/сек. | 32 ₽/сек. |
pro | 12 ₽/сек. | 24 ₽/сек. | 48 ₽/сек. |
Примеры: fast в 1080p на 6 секунд - 48 ₽, на 20 секунд - 160 ₽; pro в 2160p на 10 секунд - 480 ₽.
Говорящее фото, продление и замена фрагмента - 18 ₽ за секунду:
| Режим | За что платите | Пример |
|---|
talking_photo | длина аудио, округлённая вверх до целой секунды | аудио 5,3 сек. - 6 сек. - 108 ₽ |
extend_video | extend_duration, длина исходного видео не важна | продление на 4 сек. - 72 ₽ |
retake_video | retake_duration | замена 3 сек. - 54 ₽ |
Короткие правки обходятся дешевле всего: продление на 2 секунды или говорящее фото с аудио на 2 секунды стоят по 36 ₽. Ролик из текста или картинки - от 48 ₽ (fast, 1080p, 6 секунд). Полная сумма списывается при создании операции и видна в поле cost.
Ограничения и практические заметки
POST /api/v1/operations не идемпотентен: каждый повторный запрос создаёт новую платную операцию. Если ответ на создание потерялся, не отправляйте запрос вслепую ещё раз.
- Операция выполняется асинхронно: сначала приходит
queued, результат забирайте через GET /api/v1/operations/{id}.
- Ссылки на файлы - только внешние
http/https URL. Адреса localhost и внутренних сетей не принимаются. Картинки - jpg, jpeg, png, webp; аудио - mp3, wav, m4a, aac, flac, ogg, opus; видео - mp4, mov, webm.
- Модель строго проверяет содержимое. Самая частая ошибка в режимах из текста и изображения - «Ваш запрос не прошел модерацию». Проверка смотрит и на задание, и на картинку, поэтому при такой ошибке меняйте формулировку или файл, а не повторяйте тот же запрос.
- Длительность в режимах из текста и изображения передавайте в поле, которое подходит к модели, разрешению и FPS (таблица в разделе «Создание операции»). Длинные ролики, от 12 до 20 секунд, доступны только в
fast, 1080p и 25 FPS.
- Говорящее фото принимает аудио от 2 до 20 секунд, более короткое или длинное API отклонит с
400 validation_error.
- Продление короче 2 секунд модель не делает:
extend_duration меньше 2 API отклонит с 400 validation_error ещё до создания операции.
- В продлении контекст не может быть длиннее исходного видео, а контекст вместе с досьёмкой ограничен по числу кадров. Если модель пишет, что видео слишком короткое или кадров слишком много, уменьшите
extend_context или extend_duration, а проще - не передавайте extend_context вовсе.
- В замене фрагмента
retake_start_time плюс retake_duration не должны выходить за конец видео, иначе операция завершится ошибкой.
- Файл видео должен быть целым и читаемым: битые или нестандартные файлы модель не открывает.