Lovely RouterДокументация
Получить ключ
Справочник API

Эндпоинты замены людей в видео

Все эндпоинты /v1/videos/replacements — загрузите видео целиком, получите его кадры и людей в нём, сопоставьте каждого человека с персонажем и получите видео обратно с выполненной заменой.

Заменяйте людей в видео целиком — со склейками, несколькими кадрами и несколькими людьми. Загрузите его один раз: в нём будут найдены кадры и все люди ($0.01 за секунду видео). Затем укажите, кто кем становится — сохранённым персонажем, человеком с изображения или никем, — и заменять ли человека целиком или только голову (лицо, волосы и всё, что на ней надето). Каждый кадр с заменённым человеком заново рендерится моделью MiniMax H3; остальные кадры остаются в точности такими, как были; затем кадры склеиваются обратно поверх исходного звука.

Эндпоинты находятся по адресу https://lovelyrouter.com/v1/videos/replacements. Аутентифицируйтесь своим API-ключом в заголовке Authorization: Bearer $LOVELY_API_KEY (Аутентификация). Модели — minimax-h3-character-swap и minimax-h3-aftermidnight, на условиях MiniMax H3: каждая загрузка передаёт consent: true. Попробуйте без кода в песочнице.

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

  1. Загрузка (POST /v1/videos/replacements): видео (или его часть между start и end, до 3 минут) разбивается на кадры, а все люди в нём группируются в состав, у каждого — изображение лица и поясное изображение; каждый человек отслеживается во всех кадрах, поэтому находятся и те, кого видно со спины или кто отвернулся. $0.01 за проанализированную секунду (не менее 5 с), резервируется на балансе при загрузке и списывается, когда статус становится ready; если анализ не удался — ничего. Статус analyzing → ready.
  2. Рендеринг (POST …/{id}/render): сопоставьте участников состава с персонажами. Кадры без сопоставленного человека остаются как есть; остальные заново рендерятся по фрагментам (rendering) и склеиваются обратно (stitching → succeeded). Каждый фрагмент начинается и заканчивается на склейке и длится не меньше примерно 5 с: короткие кадры подряд рендерятся вместе с сохранением склеек (короткий кадр, в котором некого заменять, может быть взят заодно — он остаётся как есть и не оплачивается); разбивается только кадр длиннее 15 с, на почти равные фрагменты.
  3. Скачивание …/{id}/content. Фрагменты можно смотреть по мере готовности (pieces[].url).

Перед рендерингом первого кадра модель компьютерного зрения изучает изображение каждого персонажа и записывает, что на нём есть — волосы, всё, что надето на голову, очки, а в режиме замены целиком и одежду, — и чего нет («без очков, без наушников»), чтобы в каждом кадре рисовался именно этот образ и ничего лишнего. Это оплачивается как вызов чата по вашему ключу (около $0.003 за персонажа).

Перед рендерингом каждого кадра модель смотрит и слушает его, отмечает, кто говорит, и выстраивает мизансцену: где находится каждый заменяемый человек, куда он обращён и как двигается, включая руки, чтобы новый человек сохранил позу и движения исходного. В описании кадра указан говорящий, а заменённый человек, который не говорит, держит рот неподвижно, а не проговаривает чужие реплики. Это оплачивается как вызов по вашему ключу (около $0.03 за кадр).

Кто есть кто, определяется по лицам: в каждом кадре люди, которых ведёт трекер, сопоставляются с составом по лицу, поэтому человек, которого весь кадр видно только со спины, может быть там не найден — тогда этот кадр возвращается без изменений и не оплачивается.

Цены#

Оплачиваются секунды видео, где выполнена замена: секунды фрагментов, в которых кто-то действительно был заменён, — minimax-h3-character-swap $0.20 за секунду, причём каждый фрагмент с заменой считается не меньше чем за 5 секунд (он рендерится на FastH3 Omni, у которой самый короткий рендер — 5 с); minimax-h3-aftermidnight $0.12 за секунду, каждый фрагмент с заменой не меньше чем за 2 секунды, — и любое видео не меньше чем за 3 секунды. Поиск кадров и людей стоит $0.01 за секунду (списывается один раз, при загрузке; повторный запуск и шаблоны повторно не анализируют видео); кадры, оставшиеся без изменений, бесплатны. Максимально возможная стоимость (все фрагменты с сопоставленными людьми) резервируется при запуске рендеринга, а остаток возвращается по завершении.

Объект замены#

Атрибуты

idstring

rpl_ и 24 символа.

objectstring

Всегда video.replacement.

statusstring

analyzing, ready, rendering, stitching, succeeded, failed или cancelled.

secondssize` number

Обрабатываемая часть и её размер, после анализа.

shotsarray

{index, start, end, people} — секунды и id участников состава, видимых в кадре, слева направо.

castarray

{id, seconds, shots, appearances, face_url, body_url} — по одной записи на каждого найденного человека (p1, p2, …, сначала те, кто дольше в кадре).

modebackground

Параметры, запрошенные при рендеринге.

piecesarray | null

После начала рендеринга: {index, shot, shots, start, seconds, people, status, swapped, missed, last_retry, url} — shot — первый кадр фрагмента, shots — все кадры в нём, kept — взятые заодно кадры, которые остаются как есть; status — pending, rendering, replaced, unchanged (никто из сопоставленных в нём не найден), kept (никого из сопоставленных в нём не было), failed или retrying. Когда фрагмент готов, swapped и missed перечисляют его сопоставленных людей, которые были и не были найдены, — фрагмент, в котором кого-то пропустили, можно повторить (см. ниже).

progressinteger | null

0–100 во время рендеринга.

replaced_secondsnumber | null

Секунды с заменой (запланированные во время рендеринга, оплаченные по завершении).

holdcharge` number | null
analysis_chargenumber — стоимость поиска людей (0 для повторного запуска)

Зарезервированная сумма в долларах и сумма, списанная после расчёта.

source_urlstring | null

Видео в том виде, в каком вы его загрузили (GET …/{id}/source, вашим ключом), хранится 7 дней после загрузки; затем null.

urlstring | null

Готовый mp4, хранится 7 дней.

rerun_untilinteger | null

Время Unix, до которого POST …/{id}/rerun может повторно запустить завершённую замену (2 дня после загрузки); иначе null.

errorobject | null

{type, message} в случае сбоя.

Замена, ожидающая сопоставления состава
{
  "id": "rpl_5e0c2b9a7f1d4e3b8a6c0d2f",
  "object": "video.replacement",
  "model": "minimax-h3-character-swap",
  "status": "ready",
  "seconds": 32.04,
  "size": "768x1344",
  "shots": [
    { "index": 0, "start": 0, "end": 5.04, "people": ["p1"] },
    { "index": 1, "start": 5.04, "end": 10.04, "people": ["p3", "p2"] }
  ],
  "cast": [
    { "id": "p1", "seconds": 14.2, "shots": [0, 2, 6], "face_url": "https://lovelyrouter.com/v1/videos/replacements/rpl_5e0c…/cast/p1/face", "body_url": "…/cast/p1/body", "appearances": [] },
    { "id": "p2", "seconds": 10, "shots": [1, 4], "face_url": "…/cast/p2/face", "body_url": "…/cast/p2/body", "appearances": [] }
  ],
  "pieces": null,
  "url": null,
  "error": null,
  "powered_by": "MiniMax H3"
}

Загрузка видео#

POST/v1/videos/replacements

Возвращает 202 с объектом замены в статусе analyzing. Опрашивайте его (?wait=), пока он не перейдёт в ready.

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

modelstringОбязательно

minimax-h3-character-swap или minimax-h3-aftermidnight.

videofile | string

MP4, MOV или WebM до 95 МБ: файл в multipart или URL http(s) / data:.

templatestring

Шаблон (rvt_…) вместо video: без загрузки и анализа, бесплатно; замена переходит в ready за несколько секунд.

consentbooleanОбязательно

true означает принятие условий MiniMax H3.

startend` number

Секунды: обрабатываемая часть, до 3 минут. По умолчанию — всё видео (до 3 минут).

waitinteger

0–300 секунд удержания запроса, пока идёт анализ.

cURL
curl https://lovelyrouter.com/v1/videos/replacements \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -F model=minimax-h3-character-swap -F consent=true \
  -F video=@party.mp4 -F start=12 -F end=72

Рендеринг#

POST/v1/videos/replacements/{id}/render

Запускает замену для объекта в статусе ready и возвращает его в статусе rendering. Отправляйте JSON или multipart с cast в виде текстового поля JSON и изображениями в виде файлов.

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

castobjectОбязательно

Id участника состава → {"character_id": "chr_…"} (сохранённый персонаж), {"image": "<http(s) or data: URL>"} (изображение — в multipart "file:<part name>") или "keep". Неуказанные люди остаются как есть. До 8 человек.

modestringПо умолчанию person

person: человек заменяется целиком — лицо, волосы, тело, одежда. face: только голова — лицо, волосы и всё, что на ней надето (очки, наушники, головные уборы); тело и одежда сохраняются.

backgroundstringПо умолчанию keep

keep: каждый кадр сохраняет место действия. new (только в режиме person): каждый кадр заново придумывается в обстановке scene.

scenestring

При background: "new": где происходит действие. До 2 000 символов.

promptstring

Дополнительный текст для каждого кадра. До 2 000 символов.

modelstring

Рендерить другой моделью замены (по умолчанию — моделью загрузки).

seedinteger

Для воспроизводимых результатов.

addedarray

Люди, которых анализ пропустил (видны только со спины, слишком мелкие): [{shot, x, y, time}] — индекс кадра, где они находятся (доли кадра) и когда (секунды в той же шкале, что и в shots; по умолчанию — середина кадра). Они по порядку получают id x1, x2, …: сопоставляйте их в cast, как и всех остальных. Найти их можно в GET …/{id}/preview.

skipobject

Кадры, которые нужно пропустить для конкретного человека: {"p1": [3, 7]} — индексы кадров, где анализ отнёс к этому участнику состава кого-то другого (проверяйте appearances каждого человека). Для него эти кадры остаются как есть и не оплачиваются.

curl https://lovelyrouter.com/v1/videos/replacements/RPL_ID/render \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "cast": {"p1": {"character_id": "chr_3b9e1f0c7a2d4e58b6c1a9f2"}, "p2": "keep"},
    "mode": "face"
  }'

Повтор кадра#

POST/v1/videos/replacements/{id}/pieces/{n}/retry

Повторный рендер одного фрагмента завершённой замены — для фрагмента, в котором кого-то пропустили (pieces[].missed) или заменили не того человека. В течение 2 дней после загрузки (retry_until).

  • search string, optional Кого искать, в нескольких простых словах ("man in a black suit", не больше 60 символов), вместо любого человека. Только в режиме замены целиком.
  • points array, optional [{person, x, y, time}] — указание на сопоставленного человека: x, y — доли кадра, time — секунды от начала видео (по умолчанию — середина фрагмента). Человек под этой точкой отслеживается на протяжении фрагмента.

Цена фрагмента резервируется; она списывается, только если кто-то был заменён. Пока фрагмент рендерится, видео остаётся доступным для скачивания (status rendering, затем succeeded с новым фрагментом). Повтор, который никого не нашёл или завершился сбоем, сохраняет прежнюю версию и не оплачивается (pieces[].last_retry.outcome: swapped, none или failed).

cURL
curl https://lovelyrouter.com/v1/videos/replacements/RPL_ID/pieces/0/retry \
  -H "Authorization: Bearer $LOVELY_API_KEY" -H "Content-Type: application/json" \
  -d '{"search": "man in a black suit", "points": [{"person": "p2", "x": 0.18, "y": 0.43, "time": 1.4}]}'

Повторный запуск#

POST/v1/videos/replacements/{id}/rerun

Новая замена на основе завершённой (succeeded, failed или cancelled): та же загрузка, сопоставление состава, изображения, режим, фон, обстановка и промпт, но с новым seed — новые дубли каждого фрагмента. Ничего не загружается и не анализируется повторно; рендеринг начинается сразу, а цена, резерв и списание такие же, как у любого рендеринга. В течение 2 дней после первой загрузки (rerun_until). Без тела запроса.

Отвечает новым объектом замены (status rendering). Первая замена остаётся как есть. Для завершённого задания, проанализированное видео которого больше не хранится, возвращается 410: загрузите видео снова.

cURL
curl -X POST https://lovelyrouter.com/v1/videos/replacements/RPL_ID/rerun \
  -H "Authorization: Bearer $LOVELY_API_KEY"

Сохранение как шаблона#

POST/v1/videos/replacements/{id}/save

Сохраните проанализированное видео как шаблон, чтобы позже делать из него новые замены — заменять других людей, использовать других персонажей — без повторной загрузки и оплаты анализа. При сохранении копируются его кадры, состав и треки людей; это бесплатно, шаблон хранится, пока вы его не удалите, — до 20 на аккаунт. Сохраните в течение 2 дней после загрузки (столько хранится проанализированное видео). Тело: name (необязательно, до 80 символов; по умолчанию — имя файла).

Отвечает 202 с шаблоном в статусе saving, затем статус становится ready (от нескольких секунд до минуты). Используйте шаблон через template в POST /v1/videos/replacements.

Объект шаблона

idstring

rvt_….

namestatus` string

status: saving, ready или failed (с error.message).

fromstring

Замена, из которой он сохранён.

secondswidth
castarray

[{id, seconds, shots, face_url, body_url}] — те же id участников состава, что и в исходной замене.

  • GET …/templates — ваши шаблоны, сначала новые.
  • GET …/templates/{id} — один шаблон; PATCH с {"name"} переименовывает его; DELETE удаляет его (замены, сделанные из него, сохраняют собственную копию).
  • GET …/templates/{id}/cast/{person}/face (или /body) — изображения участников состава.
cURL
curl -X POST https://lovelyrouter.com/v1/videos/replacements/RPL_ID/save \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "Content-Type: application/json" -d '{"name": "Party, take 1"}'

curl https://lovelyrouter.com/v1/videos/replacements \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "minimax-h3-character-swap", "consent": true, "template": "RVT_ID"}'

Получение, список и удаление#

GET/v1/videos/replacements/{id}

Объект замены; ?wait=1–300 удерживает запрос, пока он не изменится (смена этапа или готовый фрагмент). GET /v1/videos/replacements выводит ваши замены, сначала новые (?limit=1–100, ?after=<id>).

  • GET …/{id}/content — готовый mp4 (поддерживаются запросы Range).
  • GET …/{id}/pieces/{n}/content — один фрагмент с заменой, пока рендерятся остальные.
  • GET …/{id}/source — видео в том виде, в каком вы его загрузили (отправленная часть, под исходным именем файла), в течение 7 дней.
  • GET …/{id}/cast/{p}/face и …/body — изображения участника состава (JPEG).
  • GET …/{id}/preview — проанализированная часть в виде небольшого видео (640 px, со звуком) на той же шкале времени, что и shots, чтобы найти пропущенного анализом человека; хранится 2 дня.
  • POST …/{id}/outfit — во что одет один человек, вырезанный из кадра проанализированного видео (бесплатно; чтобы нарисовать вашего персонажа в его наряде). Тело {"person": "p3"} (необязательно "shot": один из его кадров) или {"added": {"shot", "x", "y", "time"}} → 202 {"call", "shot", "shots"}: использованный кадр и все кадры, где он виден, сначала лучшие (люди переодеваются между кадрами). Затем опрашивайте GET …/{id}/outfit/{call}: 202, пока идёт обработка (~10 с; ~40 с, если нужно запустить GPU), затем JPEG — только этот человек, по его собственной маске, на белом фоне, без головы (головной убор сохраняется). 422: в этом кадре его плохо видно — попробуйте другой.
  • DELETE …/{id} — до рендеринга: отбрасывает замену (больше ничего не списывается; завершённый анализ остаётся оплаченным). Во время рендеринга: останавливает его; уже заменённые фрагменты оплачиваются. После завершения: удаляет файл.
cURL
curl "https://lovelyrouter.com/v1/videos/replacements/RPL_ID?wait=60" \
  -H "Authorization: Bearer $LOVELY_API_KEY"

curl https://lovelyrouter.com/v1/videos/replacements/RPL_ID/content \
  -H "Authorization: Bearer $LOVELY_API_KEY" -o swapped.mp4

Как получить хороший результат#

  • Люди различаются по лицам: участника состава, разделённого надвое (профиль в одном кадре, анфас в другом), можно дважды сопоставить с одним и тем же персонажем.
  • Для mode: face лучше всего подходит изображение головы персонажа; для mode: person — изображение в полный рост или референс-лист с разворотом.
  • Кадры короче 2 секунд тоже обрабатываются (они рендерятся чуть длиннее и затем обрезаются).