Интеграция OpenAI TTS для генерации речи в мобильном приложении
Голосовой синтез (text-to-speech) — технология преобразования текста в речь. Мобильное приложение озвучивает длинные тексты — новости, аудиокниги, голосовые подсказки. Без оптимизации пользователь ждёт 3–5 секунд перед началом воспроизведения. OpenAI TTS решает эту задачу, но только если правильно настроить стриминг и кэширование. Мы расскажем, как добиться задержки менее секунды на iOS и Android.
В этой статье разберём архитектуру интеграции: от простого REST-запроса до потокового воспроизведения с ExoPlayer и AVAudioPlayer. Покажем, как кэшировать синтезированное аудио и обрабатывать тексты длиннее 4096 символов. В результате — готовое решение, которое можно внедрить за 3–10 дней.
Какие проблемы решаем?
Мы решаем три ключевые проблемы. Во-первых, высокая задержка: без стриминга приходится ждать полной загрузки файла. Во-вторых, расходы: каждый повторный синтез одного и того же текста — лишние затраты на API. В-третьих, ограничение длины: OpenAI TTS принимает до 4096 символов, поэтому длинный текст нужно разбивать. Все эти проблемы мы устраняем с помощью кэша, стриминга и разбивки по предложениям.
Как устроен API OpenAI TTS?
POST https://api.openai.com/v1/audio/speech Authorization: Bearer {api_key} Content-Type: application/json { "model": "tts-1-hd", "input": "Ваш текст здесь", "voice": "nova", "response_format": "mp3", "speed": 1.0 } Согласно документации OpenAI, доступны две модели. tts-1 — быстрее, чуть хуже качество, дешевле ($15/млн символов). tts-1-hd — выше качество, медленнее на ~30%, дороже ($30/млн символов). Голоса: alloy (нейтральный), echo (мужской мягкий), fable (британский), onyx (мужской глубокий), nova (женский живой), shimmer (женский спокойный). Для русского языка nova и shimmer звучат наиболее естественно. Параметр speed от 0.25 до 4.0, дефолт 1.0; значения выше 1.3 начинают ломать просодию.
| Характеристика | tts-1 | tts-1-hd |
|---|---|---|
| Качество | Стандартное | Высокое |
| Задержка | Минимальная | Небольшая |
| Стоимость | Экономичная | Премиальная |
| Рекомендация | Короткие фразы | Длинные тексты |
| Голос | Пол | Стиль | Рекомендация для русского |
|---|---|---|---|
| alloy | нейтральный | умеренный | нет |
| echo | мужской | мягкий | да |
| fable | мужской | британский | нет |
| onyx | мужской | глубокий | да |
| nova | женский | живой | да (лучший) |
| shimmer | женский | спокойный | да |
Почему кэширование критично для UX?
Каждый запрос к API занимает время и стоит денег. Кэширование позволяет избежать повторных синтезов одного и того же текста. Для UI-фраз приложения (приветствие, подсказки) мы предгенерируем аудио при первом запуске и кэшируем навсегда. Оценка экономии: при активном использовании кэш позволяет сократить расходы на API до 40%.
// iOS: кэш синтезированного аудио class TTSCache { private let cacheURL: URL init() { cacheURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] .appendingPathComponent("tts_cache") try? FileManager.default.createDirectory(at: cacheURL, withIntermediateDirectories: true) } func key(text: String, voice: String) -> String { let input = "\(text)|\(voice)" return SHA256.hash(data: Data(input.utf8)).hexString } func get(_ key: String) -> Data? { let url = cacheURL.appendingPathComponent(key + ".mp3") return try? Data(contentsOf: url) } func set(_ key: String, data: Data) { let url = cacheURL.appendingPathComponent(key + ".mp3") try? data.write(to: url) } } Перед каждым TTS-запросом — проверка кэша. Попадание в кэш = мгновенное воспроизведение.
Реализация без стриминга (для коротких текстов)
// iOS: загрузка и воспроизведение 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 = TTSSpeechRequest(model: "tts-1", input: text, voice: voice, responseFormat: "mp3") request.httpBody = try JSONEncoder().encode(body) let (data, _) = try await URLSession.shared.data(for: request) audioPlayer = try AVAudioPlayer(data: data) audioPlayer?.play() } Для коротких фраз (до 100 символов) на tts-1 задержка ~300–500 мс — приемлемо без стриминга. Для длинных текстов нужен стриминг.
Пример стримингового воспроизведения на Android (ExoPlayer)
class OpenAITTSStreamer(private val apiKey: String, private val context: Context) { private val exoPlayer = ExoPlayer.Builder(context).build() fun speak(text: String, voice: String = "nova") { val requestBody = JSONObject().apply { put("model", "tts-1") put("input", text) put("voice", voice) put("response_format", "mp3") }.toString().toRequestBody("application/json".toMediaType()) // Используем OkHttp как DataSource через кастомный MediaSource val call = OkHttpClient().newCall( Request.Builder() .url("https://api.openai.com/v1/audio/speech") .header("Authorization", "Bearer $apiKey") .post(requestBody) .build() ) call.enqueue(object : Callback { override fun onResponse(call: Call, response: Response) { // Пишем поток во временный файл, одновременно начинаем воспроизведение val tempFile = File(context.cacheDir, "tts_${System.currentTimeMillis()}.mp3") response.body!!.byteStream().use { input -> tempFile.outputStream().use { output -> val buffer = ByteArray(8192) var bytes: Int var firstChunk = true while (input.read(buffer).also { bytes = it } != -1) { output.write(buffer, 0, bytes) if (firstChunk && tempFile.length() > 32768) { firstChunk = false // Начинаем воспроизведение после первых 32 KB Handler(Looper.getMainLooper()).post { exoPlayer.setMediaItem(MediaItem.fromUri(tempFile.toUri())) exoPlayer.prepare() exoPlayer.play() } } } } } } override fun onFailure(call: Call, e: IOException) { /* обработка ошибки */ } }) } } ExoPlayer поддерживает воспроизведение из файла, который ещё пишется — ProgressiveMediaSource читает данные по мере их поступления. Задержка до первого звука — 400–700 мс.
Как обрабатывать длинные тексты?
OpenAI TTS принимает до 4096 символов за запрос. Для длинных текстов — разбивка по предложениям:
func splitBySentences(_ text: String, maxLength: Int = 1000) -> [String] { var chunks: [String] = [] var current = "" for sentence in text.components(separatedBy: CharacterSet(charactersIn: ".!?\n")) { let trimmed = sentence.trimmingCharacters(in: .whitespaces) if trimmed.isEmpty { continue } if current.count + trimmed.count > maxLength { if !current.isEmpty { chunks.append(current) } current = trimmed } else { current += (current.isEmpty ? "" : ". ") + trimmed } } if !current.isEmpty { chunks.append(current) } return chunks } Куски синтезируем параллельно через TaskGroup, воспроизводим последовательно — так общая задержка меньше, чем при последовательной обработке.
Что входит в интеграцию
- Анализ требований и проектирование архитектуры
- Реализация REST- и стриминговых запросов к OpenAI TTS
- Настройка кэширования на устройстве (LRU-кэш с хешированием)
- Обработка длинных текстов (разбивка по предложениям)
- Интеграция плеера (AVAudioPlayer / ExoPlayer) с поддержкой фонового воспроизведения
- Учёт требований App Store Review Guidelines (Section 4.2) и настройка AVAudioSession для iOS
- Тестирование на реальных устройствах (iOS 15+ / Android 10+)
- Документация по эксплуатации и инструкция по получению API-ключа
- Поддержка в течение 2 недель после сдачи
Процесс работы
- Аналитика — изучаем ваше приложение, определяем места вызова TTS, замеряем текущие задержки.
- Прототипирование — создаём MVP на одном экране, показываем стриминг с кэшем.
- Интеграция — встраиваем готовые модули в вашу кодовую базу.
- Тестирование — проверяем на нагрузке, корректируем под ваши кейсы.
- Деплой — публикация в App Store / Google Play, мониторинг.
Сроки и стоимость
Базовая интеграция (REST + кэш) — 3–4 дня. Расширенная (стриминг + обработка длинных текстов + UI) — 7–10 дней. Точную стоимость рассчитываем после аудита вашего проекта — напишите нам, и мы оценим. Для точной оценки стоимости вашего проекта — свяжитесь с нами.
Опыт команды
Мы более 5 лет занимаемся мобильной разработкой. Реализовали 15+ проектов с интеграцией AI-сервисов, включая OpenAI, Google Cloud Speech и Yandex SpeechKit. Наши разработчики сертифицированы Apple и Google. Гарантируем стабильную работу и прозрачное сотрудничество.
Получите консультацию по интеграции голосового синтеза в ваше приложение — свяжитесь с нами.







