LIVE

Задержка latency в голосовых API: почему показатели растут

В голосовом продукте лишние 300–500 мс редко выглядят критично на дашборде. Но в пользовательском флоу они меняют поведение: ассистент отвечает с паузой, человек перебивает воспроизведение, повторяет команду или уходит в другой канал.

Обновлено19 июля 2026 г.
Чтение12 мин
Задержка latency в голосовых API: почему показатели растут

Для IVR это снижает долю успешно завершённых сценариев. Для голосового copilot — доверие к подсказкам. Для приложения с озвучкой контента — конверсию из генерации текста в фактическое прослушивание.

Проблема в том, что «задержка latency в голосовых API» обычно измеряется одной цифрой, хотя продукт переживает несколько разных ожиданий. Время до первого звука, время до готового файла, ожидание свободного слота в очереди, сетевой RTT и буферизация плеера — это разные части одного флоу. Если смешать их в общий response time, команда начинает оптимизировать не то узкое место.

Анатомия задержки: первый звук и готовый результат — не одно и то же

У TTS-синтеза есть минимум два пользовательских режима.

Первый — интерактивный. Пользователь задал вопрос, система сформировала текст и должна быстро начать говорить. Здесь ключевая метрика — время до первого аудиосегмента. В терминологии Azure это first-byte client latency: интервал от запуска синтеза до получения клиентом первого байта аудио. В него уже включена сеть.

Второй режим — пакетный. Сервис озвучивает статью, урок, рекламный ролик или набор реплик для игры. Пользователь либо ждёт готовый файл, либо процесс работает в фоне. Здесь значима finish client latency — время до доставки всего аудиорезультата на клиент.

Разница не терминологическая, а продуктовая. Длинный текст может почти не изменить старт воспроизведения при стриминге, но существенно увеличить момент, когда готов полный файл. Если команда оценивает оба режима по одной средней latency, в отчёте появляется ложная картина: «синтез быстрый», хотя экспорт длинных материалов не укладывается в SLA; или наоборот — «синтез медленный», хотя пользователь слышит начало ответа достаточно быстро.

МетрикаЧто измеряетНа какой флоу влияет
First-byte service latencyВремя внутри сервиса от получения запроса до первого аудиосегментаПроизводительность TTS-провайдера и сложность запроса
First-byte client latencyВремя от старта запроса до первого аудио у клиента, включая сетьОщущение скорости в разговорном интерфейсе
Finish client latencyВремя до получения всего аудио, включая сетьЭкспорт, постобработка, сохранение готового файла
Playback start delayВремя до фактического начала звучания после прихода данныхКлиентский буфер, декодирование, логика плеера
Queue wait timeОжидание до начала обработки на стороне системыПики нагрузки, квоты, собственные очереди

В логе одного запроса полезно видеть не tts_duration=1.8s, а цепочку событий: request_created, connection_ready, provider_request_sent, first_audio_received, playback_started, audio_completed. Тогда становится понятно, где именно распадается флоу.

Например, first-byte service latency стабильна, но first-byte client latency растёт по мобильным сетям. Это не повод менять голосовую модель. Если же первый байт приходит быстро, а playback start задерживается, проблема может лежать в буфере плеера или декодере выбранного формата. А если долго и до первого байта, и до завершения — нужно отдельно проверить соединение, очередь и параметры синтеза.

Пользователь не ждёт «ответ API». Он ждёт первый осмысленный звук — и продуктовая метрика должна фиксировать именно этот момент.

Сеть: latency начинается до нейросетевой обработки

Расхожее объяснение «нейросеть стала медленнее» часто не подтверждается трассировкой. Запрос к TTS API проходит через DNS-разрешение, TCP-handshake, TLS/SSL-handshake, установление HTTP- или WebSocket-сессии, передачу текста, обработку на стороне провайдера и доставку аудиопотока обратно. В каждом звене есть время, которое пользователь воспринимает как одну паузу.

Особенно заметна цена нового соединения. Если backend или клиент создаёт WebSocket для каждого синтеза, он платит за установление транспортного и защищённого соединения, а затем за protocol upgrade. На коротких репликах этот оверхед может оказаться сопоставим с собственно генерацией первого аудиосегмента.

Поэтому persistent connections — не микрооптимизация, а базовое архитектурное решение для realtime-флоу. Документация Azure рекомендует заранее открыть соединение и повторно использовать объект синтезатора, а не создавать новый на каждый запрос. Та же логика применима к любому провайдеру, если его SDK и модель сессий это поддерживают.

Факторы сетевой задержки TTS обычно выглядят так:

  • Высокий RTT до региона провайдера. Для интерактивного аудио Microsoft использует ориентир RTT до 200 мс; при значениях выше 500 мс задержка уже может быть заметной пользователю. Это не универсальный норматив для любого TTS API, но полезная граница для диагностики.
  • Потери пакетов и повторные передачи. В логах это может выглядеть как случайные всплески p95 и p99 при стабильном среднем значении.
  • Wi‑Fi и мобильная сеть. Нестабильность канала увеличивает jitter и вынуждает клиент держать более крупный буфер воспроизведения.
  • Неудачная география. Приложение в одном регионе, TTS в другом, а конечный пользователь — в третьем. В такой схеме путь аудио становится длиннее, чем кажется на диаграмме инфраструктуры.
  • Тяжёлый аудиоформат. Несжатый 24 kHz mono PCM может передаваться со скоростью 384 кбит/с, тогда как MP3 в конфигурации 24 kHz и 48 кбит/с — в восемь раз меньшим потоком. На узком канале это влияет на доставку результата.

Последний пункт требует аккуратности. Низкий битрейт не гарантирует меньшую end-to-end latency: кодирование и декодирование тоже имеют стоимость. Но для сценария, где сеть является подтверждённым bottleneck, объём аудиоданных нельзя игнорировать.

Практически это означает, что формат надо выбирать не по принципу «самое высокое качество по умолчанию», а под конкретный момент потребления. В живом диалоге ценность первых секунд выше, чем студийная прозрачность сигнала. В офлайн-экспорте логика обратная: можно принять более длинную обработку ради нужного качества и совместимости.

Длина текста и SSML: не вся сложность видна до отправки

Длинный prompt — не всегда причина медленного старта синтеза. По данным Azure, first-byte latency не зависит от длины текста так же напрямую, как finish latency: сервис может начать отдавать первые сегменты, пока дальнейшая часть ещё генерируется. Это главный аргумент в пользу потоковой выдачи для длинных ответов.

Но длинный запрос всё равно расширяет поверхность риска. Он увеличивает полный объём работы, размер передаваемых данных, вероятность упереться в лимит и стоимость повторной попытки при ошибке. У разных поставщиков различаются и сами границы: Google Cloud Text-to-Speech ограничивает запрос текстом или SSML размером до 5 000 байт, а Amazon Polly принимает до 3 000 тарифицируемых и 6 000 суммарных символов в SynthesizeSpeech. У Polly длительность результата также ограничена десятью минутами.

Для команды это означает, что чанкинг нельзя оставлять на усмотрение случайного middleware. Он должен быть отдельной функцией продукта с понятными правилами:

1. Резать текст по семантическим границам. Абзац, предложение, реплика диалога, пауза между смысловыми блоками. Разрыв внутри числа, URL, имени или сокращения ухудшает произношение и создаёт заметный стык в аудио.

2. Держать первый чанк коротким. В realtime-сценарии его задача — как можно раньше запустить воспроизведение. Последующие сегменты могут генерироваться параллельно или с упреждением.

3. Не путать текстовую генерацию и TTS-буфер. LLM может отдавать токены постепенно, но отправлять в синтез каждый обрывок по 5–10 слов — плохой флоу. Результат будет дробным, с неестественными интонационными границами и лишними API-вызовами.

4. Сохранять контекст произношения. При разбиении нужно не потерять язык, голос, словарь, стиль, глобальные SSML-настройки и правила нормализации чисел.

5. Отдельно тестировать edge-кейсы. Даты, валюты, артикулы, смешение русского и английского, названия моделей, аббревиатуры, номера версий и длинные списки часто ломают не только качество дикции, но и стабильность пайплайна.

SSML тоже не бесплатен. Он полезен, когда продукту нужна управляемая пауза, акцент, произношение или темп. Но сложная разметка добавляет ветвления в обработку, а отдельные конструкции у провайдера имеют подтверждённое влияние на скорость.

У Amazon Polly, например, размер pronunciation lexicon влияет на latency SynthesizeSpeech. Один лексикон может содержать до 40 000 символов, а к одному запросу можно применить до пяти словарей. Если команда прикрепляет полный корпоративный словарь к каждой короткой реплике, она получает предсказуемую, но неочевидную деградацию.

Отдельный риск — <prosody amazon:max-duration>. Polly прямо указывает, что этот тег способен увеличить время возврата синтезированного аудио; эффект зависит от текста и его длины. Внутри такого тега допускается не более 1 500 символов, а ускорение речи ограничено пятикратной нормальной скоростью. Это хороший пример того, почему настройку «уложить реплику в N секунд» нельзя рассматривать как декоративный параметр. Она меняет вычислительный путь.

В TTS-пайплайне SSML — это часть исполнения запроса, а не слой оформления поверх готовой речи.

Полезная практика — профилировать не только голоса, но и шаблоны SSML. Отдельно измерять p50, p95 и error rate для plain text, стандартной разметки, запроса с лексиконом и запроса с жёстким ограничением длительности. Так продукт видит цену функции до того, как она станет дефолтом во всех сценариях.

Нагрузка, очереди и троттлинг: почему проблема проявляется не сразу

Голосовой API может выглядеть быстрым в локальном тесте и деградировать после запуска кампании, подключения нового канала или утреннего пика звонков. Причина — не обязательно падение сервиса. Часто система просто встречает нагрузочный профиль, которого не было на стенде.

Облачные провайдеры масштабируются автоматически, но масштабирование не происходит мгновенно. Azure прямо предупреждает: при резком росте параллельной нагрузки может увеличиваться время ожидания в очереди либо появляться HTTP 429. Это связанные, но разные симптомы. Очередь увеличивает latency успешных запросов. 429 означает, что запрос ограничен и требует отдельной стратегии retry или деградации.

У Amazon Polly квоты зависят от типа голоса. Для SynthesizeSpeech в документации указаны 8 TPS для generative, long-form и neural voices против 80 TPS для standard voice. Для neural voice приводится лимит до 18 одновременных запросов, для generative и long-form — до 26. Эти значения могут меняться, поэтому их нельзя зашивать как вечную константу. Но сам принцип неизменен: выбор более сложного типа голоса меняет не только качество и цену, но и capacity planning.

Типовой анти-паттерн выглядит так: команда знает лимит в TPS, запускает ровно столько запросов в секунду, но не учитывает длительность их жизни. При длинных фрагментах или нестабильной сети растёт число одновременно висящих операций. Затем включается троттлинг, retry-логика создаёт дополнительный трафик, очередь увеличивается, а p99 уходит в секунды.

Для диагностики нагрузки полезнее разложить графики, чем смотреть единый latency chart:

  • входящий RPS и фактический TPS к провайдеру;
  • число одновременных синтезов;
  • время в собственной очереди до отправки;
  • распределение first-byte и finish latency;
  • коды 429, 5xx, отмены по таймауту;
  • число повторных попыток и их доля в общем трафике;
  • длина текстовых фрагментов по перцентилям;
  • распределение по голосам, регионам, форматам и SSML-профилям.

Если p50 стабилен, а p95 и p99 растут после всплеска RPS, это чаще похоже на очередь или сеть, чем на равномерное замедление модели. Если одновременно падает доля успешных запросов и растёт 429, нужно ограничивать admission rate до провайдера, а не бесконечно увеличивать ретраи.

Retry не должен превращаться в усилитель аварии

В голосовом интерфейсе агрессивный retry особенно опасен. Пользователь уже мог произнести новую команду, закрыть экран или перебить ассистента. Если старый запрос повторно оживает через несколько секунд, система начинает воспроизводить неактуальную реплику и ломает turn-taking.

Для интерактивных сценариев разумнее использовать короткий ограниченный retry только для идемпотентных запросов и обязательно привязывать его к cancellation token текущего диалогового хода. Если интент изменился или пользователь заговорил, старый синтез должен быть отменён. Это снижает нагрузку, экономит квоту и улучшает восприятие скорости сильнее, чем попытка во что бы то ни стало озвучить устаревший текст.

Стриминг как продуктовая архитектура, а не транспортная настройка

Стриминг уменьшает воспринимаемую задержку, потому что клиент начинает воспроизводить аудио после первого сегмента, не дожидаясь полного результата. Серверный слой при этом может пересылать сегменты дальше по мере получения. Для latency в реальном времени это базовая модель.

Но подключить streaming API недостаточно. Нужна согласованная архитектура от генерации ответа до плеера.

Сначала LLM или бизнес-логика формирует текст. Затем агрегатор собирает достаточный для естественного произнесения фрагмент: не один токен, но и не целый абзац. После этого TTS возвращает аудиосегменты. Клиент буферизует минимальный объём, достаточный для устойчивого старта, и начинает playback. Одновременно система продолжает получать следующие сегменты.

На каждом шаге возможна скрытая задержка:

  • LLM слишком долго ждёт окончания полного ответа вместо ранней отправки первого завершённого предложения;
  • агрегатор текста держит слишком крупный буфер;
  • TTS SDK буферизует поток до полного файла из-за неверной конфигурации;
  • backend ждёт весь аудиорезультат, хотя протокол уже позволяет проксировать куски;
  • клиент ставит чрезмерно большой prebuffer;
  • аудиоформат требует декодирования, которое выполняется на перегруженном main thread;
  • interruption barge-in не отменяет старое воспроизведение и новые реплики встают за ним в очередь.

OpenAI в Create speech поддерживает stream_format со значениями sse и audio; при этом SSE не поддерживается для моделей tts-1 и tts-1-hd. Это не оценка качества конкретной модели, а пример важного ограничения: выбранная модель и транспортный режим могут не совпасть. Поэтому матрицу «голос × формат × streaming × регион × клиентская платформа» надо проверять на этапе интеграции, а не после запуска.

Оптимизация скорости синтеза речи в этой модели начинается не с поиска «самого быстрого голоса». Сначала стоит убрать ожидания, которые приложение создаёт самостоятельно. На практике это часто даёт больший эффект, чем точечная смена поставщика.

Как построить измерения, которые приводят к решению

Универсального нормального latency в миллисекундах для Azure, Google Cloud, Amazon Polly, OpenAI и других платформ нет. Провайдеры по-разному определяют метрики, работают в разных регионах, используют разные модели и квоты. Сравнение «у API A 700 мс, у API B 900 мс» без единого сценария мало что означает.

Нужен собственный измерительный контракт. Он должен отражать бизнес-флоу, а не удобство инженерного лога.

Для голосового ассистента минимальный набор будет таким:

1. Time to first audible audio. От нажатия пользователем кнопки или окончания VAD до первого реально воспроизводимого звука. Это North Star для диалогового UX.

2. TTS first-byte latency. От отправки готового текстового фрагмента в API до первого байта аудио у клиента или прокси.

3. Finish latency. Отправка запроса до полного аудиофайла. Нужна для длинных ответов и пакетной озвучки.

4. Interruption success rate. Доля кейсов, в которых пользователь смог перебить речь, а старый аудиопоток остановился в заданном окне.

5. Stale audio rate. Доля аудио, которое начало или продолжило играть после смены интента, отмены запроса или нового пользовательского хода.

6. 429 и retry rate. Это ранний сигнал того, что нагрузочная модель не соответствует квотам.

7. p50, p95, p99 по сегментам. Среднее значение маскирует проблемы, которые видит именно наиболее нетерпеливая часть аудитории.

Нагрузочный тест тоже должен быть похож на реальность. Нельзя отправить тысячу одинаковых коротких строк из одного дата-центра и сделать вывод о готовности голосового продукта. В тесте нужны разные длины реплик, реальный SSML, словари произношения, типичные регионы пользователей, постепенный ramp-up concurrency и сценарии отмены. Постепенное наращивание нагрузки позволяет отделить естественную производительность от эффекта масштабирования и троттлинга.

Отдельно стоит ввести budget latency на весь путь. Не «TTS должен отвечать быстро», а конкретное распределение: столько-то допустимо на распознавание конца реплики, столько — на генерацию первого текстового фрагмента, столько — на TTS first byte, столько — на транспорт и старт воспроизведения. Если общий бюджет не сходится уже на бумаге, подбором SDK проблему не исправить.

Что менять в первую очередь

Последовательность действий зависит от симптома, но обычно работает такой порядок.

Сначала разделить first-byte, finish, сеть, очередь и playback в телеметрии. Затем проверить, переиспользуются ли соединения и есть ли стриминг до клиента. После этого — пересмотреть чанкинг текста и тяжёлые SSML-конструкции. Только затем имеет смысл обсуждать смену модели, формата или провайдера.

Для пакетной озвучки приоритет другой: допустимы более крупные чанки, асинхронные очереди и фоновая генерация. Здесь важнее предсказуемая пропускная способность, корректное восстановление после ошибок и контроль стоимости. Для диалоговой системы главные враги — лишние round trip, ожидание полного текста, устаревшее аудио после смены интента и непредсказуемые хвосты p95/p99.

Рост latency — не единая техническая неисправность. Это сигнал, что пользовательский путь перестал быть согласованным с инфраструктурой: сеть, транспорт, синтез, очереди и плеер начинают ждать друг друга. Команда, которая измеряет эти этапы отдельно, может управлять задержкой. Команда, которая видит только одну цифру response time, будет долго оптимизировать не тот участок флоу.

Частые вопросы

Почему время ответа API не совпадает с тем, что слышит пользователь?
Пользователь воспринимает задержку как совокупность сетевого времени, ожидания в очереди, обработки на стороне провайдера, декодирования и работы клиентского плеера, а не только как время генерации аудио.
Как размер текста влияет на скорость синтеза?
First-byte latency слабо зависит от длины текста, так как сервис может начать отдавать аудиопоток до завершения генерации всего текста, однако длинные запросы увеличивают общую нагрузку и вероятность ошибок.
Влияет ли использование SSML на задержку?
Да, сложная разметка SSML и использование внешних словарей произношения увеличивают время обработки запроса, так как требуют дополнительных вычислительных ресурсов.
Что делать, если API возвращает ошибку 429?
Ошибка 429 означает, что система достигла лимита запросов в секунду или параллельных операций; в этом случае необходимо ограничить входящий поток запросов, а не увеличивать частоту повторных попыток.
Почему важно использовать persistent connections при работе с TTS?
Установление нового соединения для каждого запроса создает оверхед, который на коротких репликах может быть сопоставим со временем самой генерации аудио.