Pro API: генерация и ретушь изображений

Одно изображение стоит 1 кредит, независимо от режима. Генерация по промпту и ретушь загруженного тобой изображения выполняются через один и тот же маршрут.

POST /images/quote принимает то же тело запроса и возвращает цену, ничего не создавая, всегда { "cost": 1, ... } в этом случае. Это сделано для симметрии с видео, где цена может варьироваться.

Отправить изображение

POST /images

json
{ "prompt": "portrait of a woman in a rainy street at night, neon reflections, cinematic",
  "width": 832, "height": 1216 }
ПолеТипПо умолчаниюОписание
promptstringобязательноеОписание сцены. Английский язык даёт наиболее точные результаты.
width, heightint1024 x 1024Размер в пикселях. Удачные форматы: 1024 x 1024 (квадрат), 832 x 1216 (портрет), 1216 x 832 (альбомный).
modestringgenerationedit, img2img или inpaint, см. ниже. Отсутствие поля означает генерацию по промпту.
image_b64stringИсходное изображение в base64 (PNG или JPEG), обязательно для всех трёх режимов ретуши. Не более 12 МБ после декодирования.
mask_b64stringМаска в base64: обязательна для inpaint, необязательна для edit. Закрась области для ретуши красным цветом, размер совпадает с исходным изображением.
lorastringОбученный персонаж в аккаунте: name, возвращаемый GET /loras. Добавь его trigger в промпт.
lora2, lora2_strengthstring, numberВторой персонаж и его сила (от 0 до 1, по умолчанию 1) для сцены с двумя персонажами.
countint1Количество изображений для рендера в одном запросе, от 1 до 8. Каждое получает свой уникальный сид; при указании seed они используют seed, seed+1, seed+2... Это соответствует селектору Изображений за генерацию в приложении.
seedintслучайныйСид рендера, от 0 до 4294967295. Одинаковый seed, промпт и настройки дают одинаковый результат с очень незначительными отличиями при смене видеокарты. Сохранение seed при изменении промпта позволяет получить вариацию с сохранением композиции.
stepsintдвижокОставь пустым. Движок сам знает своё значение.

Ответ:

json
{ "jobId": "test-79634842-4586-46d4-ad52-d9ea236ae00d", "seed": 178078967, "cost": 1 }

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

Запрос нескольких изображений сразу

При count больше 1 один запрос запускает несколько рендеров, каждый со своим сидом, и ответ содержит их список:

json
{ "count": 4, "requested": 4, "cost_total": 4,
  "jobs": [ { "jobId": "...", "seed": 178078967, "cost": 1 }, { "jobId": "...", "seed": 903412, "cost": 1 } ],
  "errors": [],
  "jobId": "...", "seed": 178078967, "cost": 1 }

Обрати внимание на два момента.

jobId, seed и cost первого рендера продублированы на верхнем уровне. Это сделано для обратной совместимости с клиентами, написанными до поддержки пакетной обработки, а не потому что первый запрос важнее. Опрашивай каждую запись в jobs, а не только её.

И сравнивай count с requested. Отказ в середине процесса из-за нехватки кредитов или превышения дневного лимита ключа остановит пакет на текущем месте: requested это то, что ты запросил, count это то, что реально запустилось, а errors объясняет причину остановки. Клиент, предполагающий равенство этих значений, незаметно теряет рендеры.

POST /images/quote тоже принимает count и рассчитывает стоимость всего пакета. У видео нет count: один запрос, один клип.

Три режима ретуши

Все три работают на одном движке редактирования с поддержкой инструкций, который сохраняет внешний вид исходного изображения. При передаче исходного изображения width и height читаются из самого изображения и не требуют явной передачи.

modeВходные данныеЧто делает движок
editimage_b64 + prompt (+ необязательный mask_b64)Применяет инструкцию ко всему изображению ("добавить солнцезащитные очки", "сделать снег"). С маской изменение сосредотачивается внутри красной области.
inpaintimage_b64 + mask_b64 + promptРегенерирует только красную область маски согласно инструкции. Остальное воссоздаётся пиксель за пикселем.
img2imgimage_b64 + promptПереработка всего изображения по промпту с сохранением его композиции и стиля: вариация.

В режиме edit сервер сам выбирает лучший способ правки, как приложение:

  • с маской: он читает инструкцию и выбирает между заменой содержимого области (другой предмет, другая одежда, лицо: область перерисовывается по тому, что должно в ней появиться) и изменением того, что в ней есть (цвет, материал, свет). С lora персонажа область всегда перерисовывается, включая лицо;
  • без маски, с lora персонажа ("replace the woman with kara..."): сервер находит человека на фото и перерисовывает его в персонажа; если никого не найдено, инструкция применяется ко всему изображению, как раньше.

Цена одна во всех случаях (1 кредит за изображение). Выбор виден в результате, а не в ответе.

bash
IMG=$(base64 -w0 photo.png)
curl -s $B/images -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d "{\"mode\":\"edit\",\"prompt\":\"add a red scarf, keep everything else identical\",\"image_b64\":\"$IMG\"}"

Создание изображения с персонажами, предметами и локацией

Добавь объект multiref в POST /images, и сервер соберёт твоих персонажей (Персонажи), твои предметы и животных и локацию (Объекты) вместе на одном изображении, каждого узнаваемым, как на экране "Создать изображение" в приложении. Вызывай каждого по @Имя в промпте, на английском.

json
{ "prompt": "@Mia hands a cup of coffee to @Tom on a sunny terrace, both smiling",
  "multiref": {
    "characters": [
      { "character_id": "chr_8f3a...", "name": "Mia", "view": 1 },
      { "character_id": "chr_21bc...", "name": "Tom", "lora": "tom_v1", "strength": 1.0, "lora_pass": 0.55 }
    ],
    "subjects": [ { "subject_id": "sub_...", "name": "Mug" } ],
    "location": { "subject_id": "sub_...", "name": "Terrace" }
  },
  "width": 1344, "height": 768, "seed": 42, "count": 1 }
Поле multirefЧто делает
characters[].character_id, nameПерсонаж из GET /characters; name: слово, которое пишется после @ (буквы, цифры, _).
characters[].viewРакурс его character sheet, который его представляет, от 1 до 5 (по умолчанию 1, бюст анфас).
characters[].sheet_idНеобязательно: используемый character sheet (по умолчанию самый последний).
characters[].loraНеобязательно: его LoRA для изображений, имя из списка image в GET /loras. Тогда персонажа передаёт его LoRA, а не его ракурс.
characters[].strengthСила LoRA, от 0 до 1,5 (по умолчанию 1).
characters[].lora_passДоля изображения, перерисовываемая его проходом LoRA, от 0,3 до 0,9 (по умолчанию 0,55); полезно при нескольких объектах.
characters[].descriptionНеобязательно, на английском: одежда, возраст...
subjects[]Предметы и животные из /subjects: subject_id, name (по умолчанию первое слово его названия), description, image (какое из его изображений, по умолчанию 1).
locationЛокация из /subjects (subject_id, name) или разовый фон: background_b64 и background_description.
count1 или 2: изображения рендерятся одно за другим.
  • Не более 4 объектов (персонажи, предметы и животные). Без LoRA, только по изображениям: не более 4 референсов, включая локацию. Сервер выбирает метод по референсам и размещает каждый в порядке characters, затем subjects, слева направо.
  • @Имя, не соответствующее ни одному референсу, отклоняется (unknown_mention); референс, отсутствующий в промпте, всё равно передаётся.
  • Цена: один проход стоит как одно изображение (1 кредит). Простое изображение: 1 проход; несколько персонажей, переданных через LoRA: 1 плюс один проход на каждую LoRA (не более 4); только по изображениям: один проход на каждый референс после первого; смешанный вариант: и то и другое. Итог (проходы x count) резервируется при отправке и списывается один раз, при финальном изображении: ошибка или отмена ничего не стоят. POST /images/quote с тем же телом запроса даёт точную цену, метод и его проходы, ничего не запуская.
  • Ответ 202: { "jobId": "mri_...", "seed", "cost", "method", "passes", "billed_passes" } (при count 2: jobs и cost_total). Опрос статуса, загрузка и отмена идут через обычные маршруты ниже; во время рендера progress показывает текущий проход ("2/3"). Создание изображения занимает от 1 до 3 минут.
  • Финальное изображение доступно 1 час, и 10 минут после первой загрузки. Неудавшийся проход даёт status: "failed" с reason: "render_failed"; отмена: reason: "cancelled".
  • Ошибки: invalid_count, invalid_view, invalid_lora_pass, invalid_subject_image, invalid_size, character_not_ready, а также ошибки Multi-Ref (unknown_character, unknown_subject, unknown_lora, unknown_mention, multiref_too_many_references, invalid_strength...). См. Лимиты и ошибки.

Опрос статуса

GET /images/{jobId}

ОтветЗначение
{ "status": "pending", "phase": "IN_QUEUE" }В очереди
{ "status": "pending", "phase": "IN_PROGRESS" }Рендерится
{ "status": "completed", "cost": 1, "file_url": "/pro/v1/images/{jobId}/file", ... }Готово, файл доступен
{ "status": "failed", "detail": "..." }Ошибка, ничего не списывается

Опрашивай каждые 3 секунды, не чаще: очередь общая.

Загрузка

GET /images/{jobId}/file

Сам PNG-файл в теле ответа (Content-Type: image/png). Доступен сразу после получения статуса completed, и вернёт 404 media_unavailable после удаления рендера. Загружай сразу, файлы не архивируются.

Отмена

POST /images/{jobId}/cancel

Отменяет рендер в очереди или выполняющийся. Возвращает { "ok": true }. Ничего не списывается, и зарезервированная стоимость возвращается обратно в дневной лимит ключа.

Windows · Mac · облако или локально

Генерируй приватно. Уже сегодня вечером.

Скачай tendre.AI бесплатно и генерируй без ограничений, приватно, на своём собственном GPU.

OS Windows 10/11GPU NVIDIA 8ГБ+VRAM 12ГБ рекомендуетсяДиск 20ГБ

Mac: Apple silicon (M1 или новее), macOS 13 или новее. Intel Mac не поддерживаются.

Для локальной генерации изображений на Mac нужен M4 с 24 ГБ памяти, либо M2 или M3 Pro, Max или Ultra с 24 ГБ. Если у тебя устройство послабее, всё работает онлайн через кредиты. Ретушь и видео на Mac пока тоже работают только онлайн.

Всё о tendre.AI для Mac

Нет видеокарты NVIDIA? Начни на 100% в облаке: 5 бесплатных изображений и 1 бесплатное видео каждый день. Карта NVIDIA (от 8 ГБ) открывает безлимитную локальную генерацию.