Реалізація AI Text-to-Speech з вибором голосу у мобільному додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Реалізація AI Text-to-Speech з вибором голосу у мобільному додатку
Простий
~2-3 дні
Часті запитання

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

Етапи розробки

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

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

AI Text-to-Speech з вибором голосу в мобільному додатку

Системний TTS на iOS та Android — AVSpeechSynthesizer та TextToSpeech — вирішує базову задачу, але звучить роботизовано. AI TTS від ElevenLabs, OpenAI або Yandex SpeechKit — це голоси, які складно відрізнити від живих. Інтеграція вимагає продуманого кешування та стрімінгового воспроизведення, інакше затримка 2–4 секунди перед першим словом убиває UX.

Провайдери та їхні особливості

OpenAI TTS — 6 голосів (alloy, echo, fable, onyx, nova, shimmer), моделі tts-1 (швидка) та tts-1-hd (якісна). Підтримує стріммінг. Російський — добре. Вартість: $15/млн символів для tts-1-hd.

ElevenLabs — велика бібліотека голосів, voice cloning, multilingual v2. Стріммінг через WebSocket. Найкраще якість серед усіх провайдерів.

Yandex SpeechKit — найкращі російськомовні голоси, включаючи alena, filipp. REST або gRPC. SSML для управління інтонацією, паузами, наголосом.

Системний TTS — безплатно, офлайн, нульова затримка, але роботизовано. Хорош як fallback.

Стріммове воспроизведення

Найважливіше в реалізації TTS — не чекати повної відповіді. 500 символів тексту на tts-1-hd синтезується ~2 секунди. Зі стрімінгом користувач чує перші слова через 300–500 мс.

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, який подає чанки аудіоданих по мері їхнього отримання. Це ~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 — дорогий. Один і той же текст з тими ж налаштуваннями голосу не повинен синтезуватися двічі.

// Android: кеш на диску з ключем 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.

UI вибору голосу

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

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

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

SSML для тонкої настройки

Yandex SpeechKit та Google TTS підтримують SSML:

<speak>
  Добро пожаловать в <emphasis level="strong">наш сервис</emphasis>.
  <break time="500ms"/>
  Ваш заказ <say-as interpret-as="cardinal">12345</say-as> готов к выдаче.
</speak>

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

Сроки

Базова інтеграція одного провайдера з UI вибору голосу — 4–6 днів. Стріммове воспроизведення + кеш на диску + fallback на системний TTS — ще 5–7 днів.