Реалізація синтезу мови (Text-to-Speech) у мобільному додатку
Синтез мови — одна з небагатьох мобільних AI-функцій, де нативні API забезпечують прийнятну якість з коробки без зовнішніх залежностей. iOS AVSpeechSynthesizer та Android TextToSpeech працюють на пристрої, підтримують російську мову і не потребують інтернету. Основна робота — правильна інтеграція, керування чергою і вибір голосу.
AVSpeechSynthesizer на iOS
Базовий випадок — три рядки коду. Реальне виробництво складніше.
let synthesizer = AVSpeechSynthesizer()
let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "ru-RU")
utterance.rate = 0.5 // 0.0–1.0, default = 0.5
synthesizer.speak(utterance)
Голоси на iOS діляться на «компактні» (вбудовані, ~50 МБ) та «розширені» (вища якість, ~300 МБ завантаження). Розширені голоси використовують нейромережевий синтез. Якщо пристрій їх не завантажив — AVSpeechSynthesisVoice(identifier: "com.apple.voice.enhanced.ru-RU.Milena") повертає nil. Перевірте та поверніться до компактних.
let enhanced = AVSpeechSynthesisVoice(identifier: "com.apple.voice.enhanced.ru-RU.Milena")
utterance.voice = enhanced ?? AVSpeechSynthesisVoice(language: "ru-RU")
Керування AVAudioSession обов'язкове. TTS повинен працювати навіть якщо додаток переключив сесію для запису мікрофона або відтворення музики. Використовуйте категорію .playback з mixWithOthers або .duckOthers залежно від вимог.
Android TextToSpeech: ініціалізація та керування чергою
TextToSpeech потребує асинхронної ініціалізації — поширена помилка: викликати speak() перед тим, як onInit(status) повертає SUCCESS.
val tts = TextToSpeech(context) { status ->
if (status == TextToSpeech.SUCCESS) {
tts.language = Locale("ru", "RU")
// тільки тепер можна викликати speak()
}
}
QUEUE_FLUSH — перериває поточне висловлювання і починає нове. QUEUE_ADD — додає до черги. Для послідовних сповіщень (наприклад, пошагова навігація), використовуйте QUEUE_ADD. Для відповідей помічника використовуйте QUEUE_FLUSH, щоб запобігти накопленню черги при швидкому вводі.
UtteranceProgressListener — відстежує початок і кінець висловлювання:
tts.setOnUtteranceProgressListener(object : UtteranceProgressListener() {
override fun onStart(utteranceId: String) { /* показати індикатор */ }
override fun onDone(utteranceId: String) { /* приховати індикатор */ }
override fun onError(utteranceId: String) { /* обробити помилку */ }
})
Кожен виклик speak() повинен отримати унікальний utteranceId — інакше callbacks не спрацюють правильно.
Керування швидкістю та паузами
SSML (мова розмітки синтезу мови) підтримується на iOS з версії 14.0:
let ssml = "<speak><prosody rate='slow'>Увага</prosody>, <break time='500ms'/>наступна зупинка.</speak>"
let utterance = AVSpeechUtterance(ssmlRepresentation: ssml)
На Android підтримка SSML залежить від рушія (Google TTS підтримує, Samsung TTS — частково). Для критичних випадків розділіть текст на кілька викликів speak() з паузами через playSilentUtterance.
Регулювання швидкості для доступності: надайте користувачам контроль rate в налаштуваннях додатку. Старші користувачі часто віддають перевагу 0.35–0.4 замість 0.5 за замовчуванням.
Терміни
Базова інтеграція TTS з керуванням чергою та обробкою голосів — 2–3 робочих дні. Вартість розраховується індивідуально.







