Живое видео
Бесконечное видео, которое продолжается, пока вы смотрите: POST /v1/videos/live передаёт потоком фрагменты по ~5 с, каждый продолжает предыдущий, а вы в любой момент меняете то, что произойдёт дальше. События, управление, цены и ограничения.
POST /v1/videos/live запускает живое видео: поток server-sent events, который каждые несколько секунд выдаёт новый mp4-фрагмент длиной ~5 с. Каждый фрагмент продолжает последнюю секунду предыдущего — вместе с движением, а не просто с неподвижного кадра, — так что, проигранные подряд, они складываются в один непрерывный план. При этом фрагмент следует текущему промпту, который можно менять на ходу. Дайте видео первый кадр, с которого оно начнётся, и режиссёра — чат-модель, которая пишет каждый следующий план и принимает ваши указания во время воспроизведения. Попробуйте без кода в песочнице, где первый кадр может нарисовать и модель изображений.
Модели#
| Модель | Цена | Что создаёт |
|---|---|---|
ltx-live | $0.019 за секунду созданного видео, не меньше $0.42 за сессию | LTX-2.5, 704×384 горизонтально или 384×704 вертикально, 24 fps, со звуком. Рендерит быстрее реального времени: фрагмент в 5 с занимает около 3 с. Сохраняет людей и место из первого кадра на протяжении всего потока. |
Модель работает на наших собственных GPU в группе каналов creative-hosted и подпадает под условия LTX: каждый запрос передаёт consent: true, тем самым принимая эти условия и ответственность за их соблюдение.
Запуск потока#
curl -N https://lovelyrouter.com/v1/videos/live \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{"model": "ltx-live", "prompt": "A fox trots through fresh snow at dusk, the camera tracking beside it", "seconds": 120, "consent": true}'Тело запроса (JSON или multipart с image в виде файла)
modelstringОбязательноltx-live.
promptstringОбязательноЧто на экране и что происходит: объект, действие, место, свет, камера. До 1000 символов; короткие промпты рендерятся быстрее всего.
secondsnumberПо умолчанию 60Максимальная длительность видео, 5–600. На ней поток заканчивается — или раньше, если вы его остановите или закроете соединение.
sizestringПо умолчанию 704x384704x384 (горизонтально) или 384x704 (вертикально).
imagefile or stringПервый кадр, с которого начнётся видео: файл, URL http(s) или data: URL. PNG, JPEG или WebP, до 15 МБ; обрезается до size от центра. Создайте его любой моделью изображений и передайте файл. Он же остаётся эталоном для всего потока: лица, одежда и помещение сохраняются такими, как на нём, сколько бы поток ни длился (без него эталоном служит первый фрагмент).
directorstring or objectЧат-модель, которая пишет промпт каждого следующего фрагмента: её идентификатор или {"model": "…", "instructions": "…"} с пожеланиями по стилю и сюжету (до 2000 символов). См. Режиссёр.
voicefile or stringГолос говорящего: аудиоклип (WAV, MP3, M4A, Ogg, FLAC или WebM, до 15 МБ) в виде файла, URL http(s) или data: URL. Используются первые ~5 секунд речи; этим голосом говорит каждый фрагмент. См. Голос.
keep_voicebooleanПо умолчанию trueБез voice: голос из первого фрагмента с речью сохраняется для всех последующих. false: каждый фрагмент создаёт свой.
camerastringПо умолчанию freefixed — один статичный план: камера не двигается и не переключается, место остаётся тем же. См. Неподвижная камера.
seedintegerВоспроизводимые фрагменты: фрагмент n использует seed + n.
consentbooleanОбязательноtrue: вы принимаете условия LTX.
События#
| Событие | Когда | Данные |
|---|---|---|
session | первым | объект сессии, а также seconds_per_chunk, price_per_second и price_min (минимум, который оплачивает сессия) |
status | каждые ~10 с, пока запускается GPU (state: "starting"), пишет режиссёр ("directing") или фрагмент рендерится долго ("rendering"); один раз при сбое режиссёра ("director_error", видео продолжает идти по последнему промпту) | state, chunk, waiting_s, error |
next | когда режиссёр написал промпт для очередного фрагмента | index, prompt, by |
chunk | одно на каждые ~5 с видео | index, url (mp4), prompt (которому он следовал), by (director или you), seconds, total_seconds, render_s, charge_usd (на текущий момент) |
end | последним | reason (max_seconds, stopped, client_left, insufficient_quota, error), error, seconds, charge_usd |
Если «тёплого» GPU нет, первый фрагмент приходит дольше: до минуты, пока GPU запускается, и всё это время приходят события status. Дальше фрагменты приходят чуть быстрее, чем проигрываются. Накопите два фрагмента, прежде чем начинать воспроизведение, и запускайте каждый, когда закончится предыдущий: два чередующихся элемента <video> проигрывают поток без пауз.
URL фрагментов не требуют API-ключа (у каждого свой неугадываемый путь) и хранятся 7 дней.
Режиссёр#
С director промпт каждого фрагмента пишет чат-модель: пока рендерится один фрагмент, она пишет следующий, как будто ей сказали «продолжай», опираясь на ваш prompt (сюжет), уже снятое видео (до 15 последних планов, с вашими указаниями там, где вы их давали) и всё, что вы сказали с тех пор. Она сохраняет тех же людей, место и стиль и понемногу продвигает действие с каждым планом. Каждый промпт описывает, что на экране, что происходит, что делает камера и что мы слышим — звук модель тоже создаёт. Реплики пишутся в кавычках с указанием, кто говорит, примерно по 10 слов на фрагмент (столько умещается в ~5 с); длинная речь продолжается в следующих фрагментах с того места, где оборвалась последняя реплика. Вызовы режиссёра идут через ваш ключ, как любой вызов чат-модели: оплачиваются по цене этой модели и видны в ваших логах. Быстрой и дешёвой модели вполне достаточно. За один вызов она пишет два плана, и на каждый вызов у неё около 10 секунд (два фрагмента), иначе видео встаёт на паузу, пока она не закончит; claude-haiku-5.5 укладывается примерно в 6 с. Режиссёр пишет на несколько фрагментов вперёд: пока готовый фрагмент ждёт воспроизведения, следующий вызов ждёт, пока этот фрагмент начнётся, а новое указание сразу приводит к переписыванию ещё не снятых планов, так что ваши указания видны через считаные секунды.
curl -N https://lovelyrouter.com/v1/videos/live \
-H "Authorization: Bearer $LOVELY_API_KEY" -H "content-type: application/json" \
-d '{"model": "ltx-live", "prompt": "A woman walks home through a rainy city at night", "seconds": 300,
"director": {"model": "claude-haiku-5.5", "instructions": "Slow, moody, film noir"}, "consent": true}'Скажите, что должно произойти, прямо во время воспроизведения:
curl https://lovelyrouter.com/v1/videos/live/LIVE_ID/direct \
-H "Authorization: Bearer $LOVELY_API_KEY" -H "content-type: application/json" \
-d '{"message": "A stray dog starts following her"}'Указание учитывается в следующем промпте, который напишет режиссёр. После этого оно остаётся в уже снятом видео там, где вы его дали, поэтому то, что оно меняет, продолжает действовать (новое место, настроение или язык), а событие происходит один раз. Если указание пришло после того, как промпт уже написан, этот промпт переписывается до начала его фрагмента. Сессия принимает до 100 указаний; они перечислены в объекте сессии.
Неподвижная камера#
С "camera": "fixed" весь поток — один статичный план: для человека, говорящего в камеру, комнаты, вида из окна. Режиссёру сообщается, что камера никогда не двигается и не переключается, а место не меняется, что бы ни говорили сюжет или ваши указания, — двигаются только люди. Каждый промпт, отправляемый модели, заканчивается фразой «Static camera, locked-off shot.», если в нём этого ещё нет, — и промпты режиссёра, и ваши собственные (POST …/prompt). События chunk сообщают промпт в том виде, в каком он был отправлен.
На длинном статичном плане фон постепенно деградировал бы: каждый фрагмент начинается там, где закончился предыдущий, и мелкие потери накапливаются. С неподвижной камерой комната, с которой начинается каждый фрагмент, очищается: человек и всё, что изменилось, сохраняются, а остальное берётся из чистой копии комнаты, снятой в начале. Само видео не затрагивается, поэтому в комнате сохраняются её собственные мелкие движения. Если меняется кадрирование, чистая копия снимается заново.
Голос#
Каждый фрагмент создаёт свой звук, поэтому у говорящего человека голос менялся бы каждые несколько секунд. По умолчанию сохраняется голос из первого фрагмента с речью: каждый следующий фрагмент получает этот клип как голос говорящего. Передайте voice, чтобы выбрать голос самостоятельно: около 5 секунд чёткой речи одного человека. "keep_voice": false отключает это поведение.
Как изменить то, что произойдёт дальше#
curl https://lovelyrouter.com/v1/videos/live/LIVE_ID/prompt \
-H "Authorization: Bearer $LOVELY_API_KEY" -H "content-type: application/json" \
-d '{"prompt": "It starts to snow harder; the fox stops and looks up"}'Следующий запускаемый фрагмент дословно следует новому промпту (тот, что рендерится сейчас, сохраняет свой); с режиссёром видео затем продолжается с этого места. LIVE_ID — это id из события session или заголовка x-lovely-request-id.
POST /v1/videos/live/LIVE_ID/stop завершает сессию после текущего фрагмента. Закрытие соединения тоже её завершает.
Сессия#
GET /v1/videos/live/LIVE_ID возвращает объект сессии: id, object: "video.live", model, status (live, stopping, ended), prompt, size, seconds (создано на текущий момент), max_seconds, chunks (все URL фрагментов на текущий момент), camera, voice (keep, upload или off), director, directions, end_reason, error, charge_usd (после завершения).
Цены#
Вы платите за каждую секунду созданного видео, но не меньше минимальной суммы за сессию ($0.42 для ltx-live, около 22 секунд видео: столько нам стоит запустить GPU и держать его наготове). Вызовы режиссёра оплачиваются отдельно, как вызовы чат-модели. При старте сессии на балансе резервируется её максимальная стоимость — seconds × цена (но не меньше минимума) — или меньше, если баланса не хватает; в этом случае поток заканчивается с insufficient_quota, когда зарезервированная сумма израсходована. Резерв снимается при завершении сессии, а созданные секунды списываются одним вызовом, который виден в ваших логах. Сессия, завершившаяся из-за нашей ошибки, оплачивает только созданное видео, без минимума.
Ограничения#
- Одна открытая сессия на аккаунт. Вторая отклоняется с
429, пока не завершится первая. - Каждую модель обслуживает небольшое число GPU; если все они заняты потоками, новая сессия получает
503сretry-after. - Сессия длится до 600 с. Чтобы продолжить, запустите новую и передайте последний кадр последнего фрагмента как
image, чтобы продолжить тот же план.