uncloth.app Гайды

Как добавить adult-фильтры для фото в своё приложение

Добавить adult-фильтр для фото в продукт выглядит как задача про изображения, а оказывается задачей про обвязку. Работу модели вы покупаете одним вызовом. Спринт съедает всё остальное: загрузки, которые отваливаются по таймауту; задачи, которые завершились, пока никто не слушал; ретраи, которые тихо списывают деньги дважды; и очередь в поддержку с вопросом, куда делся результат. Ниже — интеграция от начала до конца и места, где время теряется стабильно.

Из чего на самом деле состоит интеграция

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

  1. Отправить фото и нужный пресет, получить идентификатор задачи.
  2. Следить за задачей — опросом статуса или подпиской на события.
  3. Забрать готовое изображение, когда задача сообщит об успехе.
  4. Обработать ошибки и ретраи — здесь и лежит основная работа.

Шаг первый: постановка задачи

Отправка — это multipart-запрос с изображением, идентификатором пресета и подтверждением, что у вас есть права и согласие на обработку фото. Приложите к нему ключ идемпотентности. Один этот заголовок отделяет чистую интеграцию от проблемы в поддержке, а стоит он ровно ничего.

curl -X POST https://api.example/api/v1/jobs \
  -H "X-API-Key: $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F image=@photo.jpg \
  -F feature=bikini \
  -F consent=confirmed

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

Шаг второй: отслеживание прогресса

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

Считайте WebSocket оптимизацией, а опрос — источником правды. Команды, которые делают наоборот, получают задачи, идеально завершившиеся на сервере и навечно зависшие в клиенте, потому что единственное важное событие пришло, пока сокет переподключался.

Шаг третий: получение результата

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

Шаг четвёртый: ошибки, ретраи и ловушка двойного списания

Интересна не та ошибка, когда API вернул код ошибки. Интересна неопределённость: запрос ушёл, сеть отвалилась, и вы не знаете, создалась задача или нет. Наивный ретрай — и вы заплатили дважды и сделали два результата на одно действие пользователя.

Это и решает ключ идемпотентности. Повторите запрос с тем же ключом — и получите исходную задачу, а не новую, сколько бы раз ретрай ни сработал. Генерируйте ключ в момент действия пользователя, храните его вместе с записью задачи и переиспользуйте при каждом ретрае того же действия — а не создавайте новый на каждую попытку, это убивает весь механизм.

Где интеграции обычно застревают

  • Валидация загрузки только на клиенте. Проверяйте файл на сервере по содержимому, а не по расширению, до того как тратить на него вызов API.
  • Весь поток сделан синхронно — и потом выясняется, что мобильные клиенты рвут соединение задолго до конца генерации.
  • WebSocket как единственный канал прогресса, без фолбэка на опрос.
  • Локально не хранится ничего, и рестарт теряет связь между вашими пользователями и задачами в работе.
  • Забыли, что результаты временные, и ждут от API роли постоянного хранилища.

Разумный порядок работ

Прогоните одно фото по всему пути через curl до того, как напишете хоть строку кода приложения: отправка, опрос, скачивание. Потом свяжите те же четыре вызова со своим бэкендом и сохранением состояния. WebSocket добавляйте последним — чисто как улучшение прогресс-бара поверх системы, которая и без него работает. В таком порядке интеграция занимает день; в обратном — две недели отладки.

Частые вопросы

Сколько выполняется запрос?

Генерация асинхронна и завершается в фоне. Стройте интерфейс вокруг состояния прогресса, а не вокруг блокирующего вызова — и точная длительность перестанет влиять на вашу архитектуру.

Нужен ли WebSocket, чтобы работать с API?

Нет. Всё работает по одному REST. WebSocket нужен, чтобы прогресс выглядел живым; опрос эндпоинта задачи даёт ту же информацию.

Что будет, если отправить один и тот же запрос дважды?

С тем же ключом идемпотентности вы получите исходную задачу, вторая генерация не выполняется и не тарифицируется.

Разрабатывайте на uncloth.app

Один REST-эндпоинт, одиннадцать пресетов, результат приходит на ваш бэкенд. Расскажите, что вы делаете, и мы вышлем доступы.

Запросить доступ

Все руководства