Інтеграція AI TTS з вибором голосу в iOS та Android

Уявіть: користувач натискає кнопку відтворення у вашому додатку для аудіокниг. Між натисканням і першим звуком проходить 3–4 секунди. Це не просто затримка — це втрата користувача. Ми вирішували цю проблему в проєкті аудіогіда: перейшли на ElevenLabs з WebSocket-стрімингом та дисковим кешем, знизивш

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Інтеграція AI TTS з вибором голосу в iOS та Android
Простий
~2-3 дні

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    896
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    598

Уявіть: користувач натискає кнопку відтворення у вашому додатку для аудіокниг. Між натисканням і першим звуком проходить 3–4 секунди. Це не просто затримка — це втрата користувача. Ми вирішували цю проблему в проєкті аудіогіда: перейшли на ElevenLabs з WebSocket-стрімингом та дисковим кешем, знизивши час першої відповіді з 2,8 с до 350 мс. Різниця у 8 разів — і користувачі залишаються. У цій статті я розповім, як інтегрувати AI TTS з нульовими затримками, використовуючи стріминг, кешування та правильний вибір провайдера.

Як вибрати AI TTS провайдера для вашого проєкту?

Вибір провайдера визначає якість та затримку. Порівняємо основних гравців:

Провайдер Голоси Українська/російська мова Стріминг
OpenAI TTS 6 (alloy, echo, fable, onyx, nova, shimmer) Добре Так
ElevenLabs Велика бібліотека, voice cloning Відмінно WebSocket
Yandex SpeechKit 10+ російськомовних (Альона, Філіп) Найкращий REST/gRPC
Системний TTS (iOS/Android) Залежить від пристрою Середньо Ні

Для російськомовного проєкту рекомендуємо Yandex SpeechKit — найкращі голоси та підтримка SSML. Для глобального — OpenAI TLS з балансом якості та ціни. Yandex SpeechKit, у свою чергу, забезпечує на 30% менший час початку відтворення порівняно з OpenAI при російському тексті.

Чому стріминг критичний для UX?

Без стрімінгу користувач чекає повного завершення синтезу. 500 символів на tts-1-hd генеруються ~2 секунди — це вічність у мобільному інтерфейсі. Зі стрімингом перші слова звучать через 300–500 мс. Різниця в 4–6 разів — саме вона відділяє «робота» від «живого» спілкування. Стріминг окупається за рахунок утримання користувачів.

Як інтегрувати стріминг: покрокова інструкція

  1. Виберіть провайдера та отримайте API-ключ.
  2. Налаштуйте стрімінгове відтворення: на iOS використовуйте AVPlayer з кастомним AVAssetResourceLoaderDelegate, на Android — ExoPlayer з кастомним DataSource для POST-запитів.
  3. Реалізуйте дисковий кеш з ключем sha256, щоб уникнути повторного синтезу.
  4. Додайте UI для вибору голосу з попереднім прослуховуванням.
  5. Налаштуйте fallback на системний TTS при відсутності мережі.

iOS: стріминг через AVPlayer

class StreamingTTSPlayer { private var player: AVPlayer? private var playerItem: AVPlayerItem? func speak(text: String, voice: String = "nova") async throws { var request = URLRequest(url: URL(string: "https://api.openai.com/v1/audio/speech")!) request.httpMethod = "POST" request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") let body = ["model": "tts-1", "input": text, "voice": voice, "response_format": "mp3"] request.httpBody = try JSONEncoder().encode(body) // AVPlayer вміє стрімити з HTTP-відповіді через resourceLoader // Використовуємо кастомний AVAssetResourceLoaderDelegate let asset = StreamingAudioAsset(request: request) playerItem = AVPlayerItem(asset: asset) player = AVPlayer(playerItem: playerItem) player?.play() } } 
Детальніше про реалізацію AVAssetResourceLoaderDelegate Для повноцінного стрімінгового відтворення потрібен `AVAssetResourceLoaderDelegate`, який подає чанки аудіоданих у міру їх отримання. Це ~100 рядків коду, але це єдиний спосіб почати відтворення до отримання повного файлу на iOS. Альтернатива — використовувати `AudioStreamer` бібліотеки або `AVPlayer` з data URI через pipe. На практиці найпростіше — `AVAudioPlayerNode` + `AVAudioEngine` з ручною подачею декодованих PCM-буферів.

Android: ExoPlayer зі стрімингом

class StreamingTTSPlayer(private val context: Context) { private val exoPlayer = ExoPlayer.Builder(context).build() fun speak(text: String, voice: String = "nova") { val url = "https://api.openai.com/v1/audio/speech" // ExoPlayer підтримує стріминг нативно через MediaSource val dataSourceFactory = DefaultHttpDataSource.Factory().apply { setDefaultRequestProperties(mapOf( "Authorization" to "Bearer $apiKey", "Content-Type" to "application/json" )) } // Для POST-запитів використовуємо кастомний DataSource val mediaItem = MediaItem.fromUri(buildCachedUri(text, voice)) exoPlayer.setMediaItem(mediaItem) exoPlayer.prepare() exoPlayer.play() } } 

ExoPlayer нативно підтримує прогресивний стріминг MP3/AAC. Для POST-запитів потрібен кастомний DataSource, який робить POST і віддає InputStream — ExoPlayer сам буферизує і починає відтворення після перших кількох секунд аудіо.

Як уникнути подвійних витрат на синтез за допомогою кешування?

TTS — дорогий. Одна і та ж фраза не повинна синтезуватися двічі. Використовуємо дисковий кеш з ключем sha256:

class TTSCache(private val cacheDir: File) { fun getKey(text: String, voice: String): String = MessageDigest.getInstance("SHA-256") .digest("$text|$voice".toByteArray()) .joinToString("") { "%02x".format(it) } fun get(key: String): File? { val file = File(cacheDir, "$key.mp3") return if (file.exists()) file else null } fun put(key: String, data: ByteArray) { File(cacheDir, "$key.mp3").writeBytes(data) } } 

TTL кешу — 30 днів для статичного контенту (UI-фрази, навчальний текст), без TTL для користувацького. Обмеження розміру кешу — 50–100 МБ, LRU eviction. Кешування знижує витрати на API вдвічі при високій повторюваності запитів.

Порівняння стратегій кешування:

Стратегія Переваги Недоліки
LRU (витіснення давно невикористаних) Ефективно при повторюваності Дорогий пошук при великому розмірі
TTL (час життя) Гарантує свіжість Може видаляти часто запитувані
Комбінована (LRU + TTL) Найкращий баланс Складніше реалізувати

Коли варто використовувати SSML?

SSML стане в нагоді, коли потрібен точний контроль вимови: паузи між реченнями, наголоси в складних словах, зміна темпу мовлення. Це особливо важливо для голосових помічників та озвучення інструкцій. Yandex SpeechKit та Google TTS підтримують SSML, OpenAI TTS — ні. Ось приклад розмітки:

<speak> Ласкаво просимо до <emphasis level="strong">нашого сервісу</emphasis>. <break time="500ms"/> Ваше замовлення <say-as interpret-as="cardinal">12345</say-as> готове до видачі. </speak> 

Використовуйте <break>, <prosody rate="slow">, <say-as> для чисел і дат — це відрізняє природне звучання від роботизованого.

UI вибору голосу: як дати користувачеві почути

Користувач повинен почути голос перед вибором. Патерн:

  1. Список голосів з ім'ям та коротким описом.
  2. Кнопка «Прослухати» — відтворює 5-секундний приклад (кешуємо попередньо записані семпли, не синтезуємо на льоту).
  3. Вибраний голос зберігається в UserDefaults / SharedPreferences.

Для ElevenLabs — /v1/voices повертає список доступних голосів з метаданими: preview_url для попереднього прослуховування. Не потрібно синтезувати — просто відтворюй готовий preview.

Що входить у роботу

  • Аудит поточного проєкту та вибір провайдера.
  • Інтеграція вибраного TTS API з підтримкою стрімінгу.
  • Налаштування кешування на диску з LRU-алгоритмом.
  • Розробка UI для вибору та попереднього прослуховування голосів.
  • Реалізація fallback на системний TTS при відсутності мережі.
  • Тестування на реальних пристроях (iOS 15+ / Android 10+).
  • Передача документації по API та архітектурі.

Строки та вартість

Базова інтеграція одного провайдера з UI вибору голосу — 4–6 днів. Стрімінгове відтворення + кеш на диску + fallback на системний TTS — ще 5–7 днів. Вартість розраховується індивідуально залежно від складності. Оцінимо ваш проєкт безкоштовно — зв'яжіться для консультації. Замовте інтеграцію TTS у ваш додаток — ми забезпечимо низькі затримки та природне звучання.