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

Коли користувач натискає кнопку відтворення, кожна секунда очікування може коштувати його уваги. Ми інтегруємо AI TTS з вибором голосу у ваші мобільні застосунки, забезпечуючи миттєвий відгук і природне звучання. Наша команда реалізує проєкт під ключ — від підбору провайдера до стрімінгу та кешування, з подальшою підтримкою.

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

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

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

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

Уявіть: користувач натискає кнопку відтворення у вашому додатку для аудіокниг. Між натисканням і першим звуком проходить 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 у ваш додаток — ми забезпечимо низькі затримки та природне звучання.

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

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

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1010
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    903
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1332
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1180
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1107
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    714