Real-Time AI Speech Translation in Mobile Applications
Переклад мови в реальному часі — це pipeline з трьох незалежних затримок: захват аудіо → трансгрипція → переклад → синтез голосу. Наскрізна затримка від кінця фрази до звуку перекладу в хорошій реалізації — 1,5–3 секунди. В поганій — 8–15 секунд, та це вже неюзабельно для живого розговору.
Архітектура pipeline
Мікрофон → VAD → буфер 2-3 сек → STT API → вихідний текст
↓
Translation API → перекладений текст
↓
TTS API → аудіо → динамік
Кожен блок можна паралелити. Поки TTS синтезує перше речення, STT вже обробляє наступний фрагмент. Це називається pipeline parallelism та знижує наскрізну затримку вдвічі.
Вибір STT для стрімінгу
Whisper — ні. Deepgram Nova-2 або Google Speech-to-Text v2 з interim_results — так. Для перекладу мови потрібен потоковий STT, інакше доведеться чекати повної паузи.
Deepgram з interim_results=true та utterance_end_ms=1200 дає текст у течение 300–500 мс після закінчення фрази. Це робоче вікно для запуску перекладу.
Реалізація на iOS
class SpeechTranslationPipeline {
private let deepgramStreamer: DeepgramStreamer
private let translator: TranslationService
private let tts: AVSpeechSynthesizer
func handleFinalTranscript(_ text: String, sourceLang: String, targetLang: String) async {
// Запуск перекладу одразу після отримання кінцевого utterance
async let translated = translator.translate(text, from: sourceLang, to: targetLang)
// Паралельно показуємо вихідний текст в UI
await MainActor.run { sourceLabel.text = text }
let translatedText = try? await translated
guard let result = translatedText else { return }
await MainActor.run { targetLabel.text = result }
// TTS
let utterance = AVSpeechUtterance(string: result)
utterance.voice = AVSpeechSynthesisVoice(language: targetLang)
utterance.rate = 0.52
tts.speak(utterance)
}
}
AVSpeechSynthesizer — системний TTS на iOS. Для російського голосу якість прийнятна, але заметно гірше ElevenLabs чи OpenAI TTS. Якщо потрібен природний голос — заміняємо блок TTS на хмарний з кешуванням.
Управління аудіосесією
При одночасному захваті мікрофона та воспроизведенні перекладу — конфлікт AVAudioSession. Потрібна категорія .playAndRecord з опцією .defaultToSpeaker:
try AVAudioSession.sharedInstance().setCategory(
.playAndRecord,
mode: .voiceChat,
options: [.defaultToSpeaker, .allowBluetooth]
)
Режим .voiceChat активує еховідподавлення. Без нього переклад з динаміка попадає обратно в мікрофон та йде на другий круг трансгрипції.
Реалізація на Android
class SpeechTranslationPipeline @Inject constructor(
private val deepgramStreamer: DeepgramStreamer,
private val translationRepo: TranslationRepository,
private val tts: TextToSpeech
) {
fun start(sourceLang: String, targetLang: String) {
deepgramStreamer.onFinalTranscript = { text ->
coroutineScope.launch {
val translated = translationRepo.translate(text, targetLang)
withContext(Dispatchers.Main) {
sourceTextView.text = text
targetTextView.text = translated
}
speakTranslation(translated, targetLang)
}
}
deepgramStreamer.start()
}
private fun speakTranslation(text: String, lang: String) {
tts.language = Locale.forLanguageTag(lang)
tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, null)
}
}
AudioManager.MODE_IN_COMMUNICATION + AudioRecord з джерелом VOICE_COMMUNICATION — для коректної роботи AEC (Acoustic Echo Canceler) на Android. Інакше на пристроях без апаратного AEC буде эхо.
Проблема перекриття фраз
Поки TTS вимовляє переклад, користувач може говорити наступну фразу. Якщо VAD це не урахує, мікрофон підхопить голос з динаміка. Рішення:
- Пауза VAD на час воспроизведення TTS
- Або додаткова фільтрація: ігнорувати interim-результати під час відтворення аудіо
На практиці другий варіант надійніше, не створює невловких пауз.
Провайдери під різні мовні пари
| Напрямок | STT | Translation | TTS |
|---|---|---|---|
| ru → en | Deepgram Nova-2 | DeepL | OpenAI TTS (alloy) |
| en → ru | Deepgram Nova-2 | DeepL/Google | Yandex SpeechKit |
| zh → en | Google STT | Google Translate | Google TTS |
| ar → en | AssemblyAI | GPT-4o | ElevenLabs |
Для російського синтезу голосу Yandex SpeechKit заметно кращий за Google TTS та OpenAI за природністю. Це не думка — це перевіряється на тестовому наборі з 50 фраз.
Офлайн-варіант
Для пристроїв без стабільного інтернету: Whisper on-device (whisper.cpp через CoreML на iOS, ONNX на Android) + ML Kit Translate + системний TTS. Затримка 3–6 секунд замість 1,5, але працює без мережі.
Whisper tiny/base на iPhone 13 через CoreML — близько 2 секунд на 5-секундний фрагмент. Прийнятливо для туристичного сценарію.
Сроки
Потоковий переклад мови з хмарними сервісами на одній платформі — 2–4 тижні. Це включає інтеграцію STT, translation, TTS, управління аудіосесією, обробку обриву мережі, базовий UI. Кросс-платформенна реалізація на Flutter з нативними аудіо-мостами — 3–5 тижнів.







