AI-генерація аватарів за фото: реалізація в мобільному додатку
Наш типовий запит: «Хочу, щоб користувач завантажив селфі та отримав 10 стилізованих аватарів за 10 секунд». Звучить як стандартне завдання, але на практиці впирається у вибір моделі (Stable Diffusion + LoRA проти спеціалізованих API), керування чергами, прийнятний час очікування та роботу з фото-роздільністю. Ми реалізували такі проєкти під ключ — з нуля до App Store і Google Play. Оцінимо ваш проєкт, зв'яжіться для консультації.
Чому не варто генерувати аватари on-device?
Stable Diffusion 1.5 у FLOAT16 важить ~2,5 GB. Apple ML Stable Diffusion Swift package дозволяє запустити його на iPhone 14 Pro — 20 кроків DDIM на 512×512 займають близько 8 секунд. Це на топовому пристрої. На iPhone 12 або середньобюджетному Android — нереально. Серверна генерація через спеціалізовані сервіси — єдиний розумний шлях для продакшену.
| Сервіс | Підхід | Час | Якість |
|---|---|---|---|
| Replicate (SDXL + IP-Adapter) | REST API | 15–40 сек | Висока |
| Fal.ai | REST + WebSocket | 5–15 сек | Висока |
| Leonardo.ai | REST API | 10–30 сек | Дуже висока |
| Astria.ai | Fine-tune + генерація | 10–30 хв (fine-tune) + 15 сек | Максимальна |
Для аватарів «схожих на користувача» найкращий результат дає IP-Adapter або InstantID — вони зберігають риси обличчя без повноцінного fine-tune LoRA. Якщо потрібна максимальна точність (як у Lensa App) — Dreambooth LoRA з 10–20 фото користувача, але це займе 10–20 хвилин обробки.
Як ми організовуємо асинхронний флоу на клієнті?
Генерація займає час — користувачеві потрібен зрозумілий feedback. Наш флоу на iOS з polling та експоненційною затримкою:
// iOS: запуск генерації та polling статусу class AvatarGenerationService { private let apiClient: APIClient func generateAvatar(photo: UIImage, style: AvatarStyle) async throws -> [UIImage] { // 1. Compress + upload photo let photoData = photo.jpegData(compressionQuality: 0.85)! let uploadURL = try await apiClient.uploadPhoto(data: photoData) // 2. Start generation job let jobId = try await apiClient.startGeneration( photoURL: uploadURL, style: style.rawValue, count: 6 ) // 3. Poll with exponential backoff return try await pollJobResult(jobId: jobId) } private func pollJobResult(jobId: String) async throws -> [UIImage] { var delay: TimeInterval = 2.0 for _ in 0..<30 { try await Task.sleep(nanoseconds: UInt64(delay * 1_000_000_000)) let status = try await apiClient.checkJob(id: jobId) switch status.state { case .completed: return try await downloadResults(urls: status.resultURLs) case .failed: throw AvatarError.generationFailed(status.error) case .pending, .processing: delay = min(delay * 1.5, 8.0) } } throw AvatarError.timeout } } На Android аналогічно через Kotlin Coroutines + kotlinx.coroutines.delay. Ми гарантуємо стабільну роботу — наш досвід включає проєкти з 5+ років на ринку та понад 50 успішних релізів.
Підготовка фото: що перевірити перед відправкою?
Якість аватара безпосередньо залежить від вхідного фото. Ми виконуємо валідацію на клієнті:
- Обличчя детектовано (iOS:
VNDetectFaceRectanglesRequest, Android: ML KitFaceDetector) - Освітлення прийнятне — перевіряємо середнє значення яскравості через
CIAreaAverage - Роздільність мінімум 512×512
- Одне обличчя в кадрі (якщо кілька — показуємо попередження)
Фото компресуємо до 1024×1024 JPEG 85% перед відправкою — надлишкова роздільність не покращує результат, але збільшує час завантаження та вартість.
Як організувати кешування та галерею результатів?
Згенеровані аватари зберігаємо в FileManager з метаданими в Core Data (iOS) або Room (Android). Це дозволяє не генерувати повторно при кожному відкритті. Важливий момент: якщо додаток іде в бекграунд під час генерації — polling переривається. Ми вирішуємо це збереженням jobId у UserDefaults / SharedPreferences і перевіркою статусу незавершених завдань при наступному запуску.
Push-сповіщення про готовність
Чекати 20–40 секунд з відкритим додатком — непогано. Але якщо користувач згорнув додаток — потрібен push. Сервер надсилає FCM/APNs-сповіщення після завершення генерації. На клієнті — UNNotificationAction з deep link в галерею аватарів.
Права та конфіденційність
App Store Review (Section 5.1) вимагає декларувати збір фотографій. Якщо фото йде на сервер — це Photos data type, usage: App Functionality. У проєкті ми обов'язково:
- запитуємо явну згоду користувача
- зберігаємо вихідне фото не довше 24 годин і видаляємо після генерації
- не передаємо дані третім сторонам для навчання без згоди
На Android з targetSdk 33+ запитуємо READ_MEDIA_IMAGES замість застарілого READ_EXTERNAL_STORAGE. Наші інженери мають сертифікати та досвід публікації в обох сторах — це гарантія відповідності гайдлайнам.
Що входить у роботу?
- Аналіз і вибір AI-провайдера під ваші завдання
- Розробка клієнтського SDK: завантаження, валідація, polling, кешування
- Серверна інтеграція (REST/GraphQL) з чергами та push
- Тестування на реальних пристроях (iOS 15+, Android 10+)
- Підготовка документації та супровід під час публікації
Строки та вартість
Базовий флоу (завантаження фото, API виклик, polling, показ результатів) — 3–5 днів. З валідацією обличчя, галереєю, push-сповіщеннями та підтримкою кількох стилів — 2–3 тижні. Вартість розраховується індивідуально і залежить від платформи (iOS/Android/обидві) та обраного AI-провайдера. Зв'яжіться з нами — оцінимо ваш проєкт, відповімо на питання.







