Коротко
Реализация Qwen3-TTS 1.7B CustomVoice от Nari Labs достигает 10 запросов в секунду (RPS) и p95 времени до первого звука (TTFA) менее 50 мс, при этом сохраняя воспроизведение в реальном времени на одном NVIDIA H100 SXM.
Сравнивались пять реализаций: собственная разработка Nari Labs, vLLM-Omni, SGLang-Omni△, VoxServe и M*, — под открытой пуассоновской нагрузкой. После настройки каждой реализации на низкую задержку потокового вывода только решение Nari Labs достигло p95 TTFA ниже 50 мс. Показатель держится ниже 50 мс вплоть до 10 RPS и остаётся ниже 100 мс даже при 20 RPS.
Система выдаёт около 630 символов в секунду при 10 RPS. При стоимости $4,29 в час за инстанс с одним H100 SXM это соответствует примерно $2 за 1 млн символов при полной загрузке1. Для сравнения, ElevenLabs V3 стоит $100 за 1 млн символов, а Cartesia Sonic 3.5 — $49 за 1 млн при более высоком TTFA.
Реализация и код, а также бенчмарк опубликованы в открытом доступе. Методология описана ниже.
Что такое TTS в реальном времени
Прежде чем перейти к деталям, стоит определить, что должен обеспечивать сервер синтеза речи в реальном времени. Задача разбивается на четыре части:
- Низкий audible TTFA: время от отправки запроса до первого слышимого сэмпла должно быть минимальным.
- Отсутствие underrun'ов: после начала воспроизведения у клиента не должно заканчиваться буферизованное аудио.
- Пропускная способность: пункты 1 и 2 должны выполняться при росте RPS.
- Корректность вывода: речь должна оставаться разборчивой.
Для тестов выбрана модель Qwen3-TTS CustomVoice 1.7B — одна из самых популярных TTS-моделей с разрешительной лицензией.
Исходя из этого определения, цель — низкий p95 audible TTFA без underrun'ов при сохранении высокого RPS на одном NVIDIA H100 SXM.
Все бенчмарки прогонялись по пять минут под открытой пуассоновской нагрузкой, приближающей реальные условия работы — по методике, аналогичной бенчмарку LLM от Fireworks AI. Каждый движок получает полный текст одним HTTP-запросом, при этом аудио выводится потоково. Audible TTFA определяется автоматически, воспроизведение восстанавливается из полученного PCM, а итоговое аудио оценивается с помощью Deepgram STT.
Как справляются другие движки
Таблица ниже показывает исходный/дефолтный результат при 1 RPS для каждого движка. На этом этапе вносились только изменения, необходимые для совместимости.
| Движок | p95 audible TTFA | p95 начальная тишина | Запросы с underrun |
|---|---|---|---|
| vLLM-Omni | 277,883 мс | 90 мс | 100% |
| SGLang-Omni△ | 1140,69 мс | 80 мс | 0% |
| VoxServe | 315,064 мс | 30 мс | 0% |
| M* | 1159,956 мс | 90 мс | 0% |
У этих дефолтных конфигураций есть существенный потенциал для улучшения. Каждый движок настраивался отдельно под свои требования к задержке, непрерывности воспроизведения, качеству и пропускной способности.
1. Удаление начальной тишины
Первый PCM-фрагмент, возвращаемый моделью, может содержать десятки миллисекунд тишины перед началом устойчивого звука. Это отодвигает audible TTFA следующим образом:
Добавлена динамическая обрезка: она определяет устойчивую речь по коротким окнам RMS, удаляет сэмплы до начала звука и передаёт остальное аудио в обычном режиме. Это изменение улучшает TTFA примерно на 80 мс, но не ускоряет сам инференс модели.
2. Настройка накопления фреймов
Также настраивается количество кодек-фреймов, собираемых перед декодированием и отправкой аудиочанка.
Меньшие начальные чанки снижают TTFA, но дают меньше запаса на воспроизведение и требуют более частой работы декодера. Крупные чанки легче батчить, и они делают непрерывное воспроизведение надёжнее, но задерживают первый слышимый вывод. Поэтому оптимальная конфигурация начинается с маленького чанка и постепенно увеличивает размер чанков для последующего вывода.
Конкретные параметры различаются в зависимости от движка: vLLM-Omni предоставляет настройки вроде codec_chunk_frames и codec_chunk_ramp; остальные движки — аналогичные элементы управления чанками или страйдами. Значения подбирались перебором, чтобы найти конфигурацию с наилучшим сочетанием: низкий p95 TTFA, отсутствие underrun'ов и стабильное поведение при росте нагрузки.
Производительность после настройки существующих движков
В таблице ниже — выбранный профиль без underrun'ов для каждого движка после настройки удаления начальной тишины и накопления фреймов.
| Движок | p95 TTFA (1 RPS) | p95 TTFA (6 RPS) |
|---|---|---|
| vLLM-Omni | 56,815 мс | 93,451 мс |
| SGLang-Omni△ | 120,879 мс | 273,700 мс |
| VoxServe | 49,3 мс | 363,2 мс |
| M* | 104,035 мс | 179,501 мс |
VoxServe достигает p95 TTFA ниже 50 мс при 1 RPS, три других движка — нет. К отметке около 6 RPS каждый движок выходит на уровень p95 TTFA порядка 100 мс или выше2.
Как оптимизировали Qwen3-TTS
Для понимания оптимизаций важно представлять архитектуру Qwen3-TTS. Это модель из трёх частей, выполняющая иерархическую генерацию по нескольким кодовым книгам. Talker предсказывает первый токен кодовой книги для каждого аудиофрейма, Code Predictor генерирует оставшиеся 15 токенов кодовых книг, а каузальный Codec преобразует токены кодовых книг в сэмплы волновой формы.
У каждого модуля свой профиль вычислений, поведение при батчинге и требования к задержке. Вместо оптимизации каждого модуля по отдельности команда сосредоточилась на более широком вопросе: как система обслуживания должна координировать эти разнородные задачи?
1. Объединение трёх модулей под одним планировщиком
Большинство реализаций Qwen3-TTS разбиты на два этапа: Talker и Code Predictor работают вместе, а Codec — отдельно. Такое разделение позволяет генерации токенов и декодированию волновой формы перекрываться между запросами.
Здесь пошли дальше. Talker, Code Predictor и Codec представлены как три независимо планируемые задачи. Ключевая идея не просто в разделении на части, а в том, чтобы свести все три модуля на общую поверхность планирования, управляемую одним планировщиком. Этот подход вдохновлён архитектурой M* (arXiv).
При такой схеме планировщик может решить, запустить ли Talker, продвинуть Code Predictor или отдать приоритет задаче Codec, у которой приближается дедлайн воспроизведения. Он также может батчить запросы, ожидающие один и тот же модуль. Вместо фиксированного порядка выполнения работа перестраивается в зависимости от срочности.
Объединение Talker и Code Predictor может показаться более эффективным, поскольку убирает промежуточную границу. Однако объединённая операция способна стать непрерываемым блоком работы, блокирующим более срочные задачи Code Predictor или Codec. Раздельные модули создают более короткие единицы работы и дают планировщику больше возможностей чередовать запросы.
2. Планирование с учётом специфики потоковой речи
У потоковой речи два разных понятия срочности.
До прихода первого аудиочанка каждая миллисекунда увеличивает TTFA, поэтому этот путь нужно приоритизировать. Но как только воспроизведение началось, цель меняется: следующий чанк должен успеть прийти лишь до окончания проигрывания текущего аудио. Более раннее его получение не даёт пользователю никакой видимой выгоды.
Поэтому высокий приоритет получают запросы, ещё не выдавшие первое аудио, тогда как уже установленные потоки становятся срочными только при приближении к дедлайну воспроизведения.
Выполнение каждого срочного запроса в одиночку разрушило бы эффективность батчинга. Вместо этого планировщик выбирает срочный запрос в качестве якоря и заполняет остальную часть батча совместимой работой. Это помогает критичному запросу уложиться в дедлайн, эффективно используя GPU.
Такая политика работает особенно хорошо благодаря тому, что все три модуля используют общую поверхность планирования, позволяя выбирать одновременно и запрос, и этап конвейера для продвижения.
3. Использование регулярной структуры Code Predictor
Code Predictor — авторегрессивный трансформер, но его выполнение необычно регулярно. Он всегда выполняет фиксированное число шагов (15) на кадр, чтобы заполнить оставшиеся аудиокодовые книги.
Эта фиксированная структура используется для предварительного выделения KV-кэша и захвата всего цикла генерации кадра в виде одного CUDA graph. Также применяется специализированное Triton-ядро внимания, оптимизированное под короткий ограниченный контекст.
Замена управляемой хостом последовательности фиксированной GPU-программой снижает задержку и упрощает систему выполнения.
4. Перестройка Codec вокруг кэшированного состояния
Codec Qwen3-TTS состоит из трансформеров и свёрточных сетей. Генерация следующего аудиочанка зависит и от контекста трансформера, и от свёрточного состояния предыдущих чанков.
Наивная реализация заново обрабатывает всю историю фреймов при каждом обновлении, многократно декодируя уже сгенерированное аудио по мере роста высказывания.
Чтобы избежать этого, используется Codec на основе кэша состояния. Каждый запрос хранит контекст трансформера и свёрточное состояние, необходимые для следующего чанка. Инкрементное декодирование затем переиспользует этот кэш и обрабатывает только новые фреймы, не воспроизводя всю историю заново.
Инициализация кэша состояния из первого кадра добавляет накладные расходы и ухудшает TTFA. Поэтому для первого аудио применяется полное декодирование, а затем происходит переключение на инкрементное декодирование с кэшем состояния для эффективного продолжительного воспроизведения.
Аналогичным образом варьируется размер чанков в течение запроса. Меньшие чанки позволяют быстрее начать воспроизведение, а более крупные — повышают эффективность батчинга и использования GPU при продолжительном проигрывании.
5. Дополнительные оптимизации обслуживания
CUDA graph захватываются для заранее определённого набора размеров батча. Если готовая когорта превышает наибольший захваченный размер батча, она разбивается на несколько тактов планирования вместо отката в eager-режим.
Также исключена лишняя синхронизация CPU–GPU. Например, пока EOS подавлен, генерация не может завершиться, поэтому проверка завершения откладывается до момента, когда EOS включён. Это позволяет CPU готовить и отправлять последующую работу, не дожидаясь GPU.
Кроме того, поддерживается потоковый ввод для модульных систем speech-to-speech. По мере генерации токенов вышестоящей LLM модель TTS может начинать синтез речи ещё до получения полного ответа, снижая сквозную задержку.
Что дальше
Qwen3-TTS — только начало работы над мультимодальным инференсом. В планах — расширение на изображения, видео и world-модели, а также на fine-tuning. Конечная цель — воспроизвести мир 1:1 через мультимодальный инференс в реальном времени.
Команда Nari Labs специализируется на исследованиях и инфраструктуре мультимодального ИИ. Их открытая TTS-модель Dia была скачана более двух миллионов раз и занимала первое место на Hugging Face. В команде — бывшие сотрудники YC, KRAFTON и NAVER, публиковавшиеся на NeurIPS и ICLR и завоевавшие три золотые медали IOI и ICPC World Finals. Nari Labs поддерживается Y Combinator.
△ На момент тестирования в середине августа 2026 года поддержка SGLang-Omni со стороны разработчиков была ещё неполной. GitHub
1 Оценка не учитывает сетевые издержки, простой мощностей и операционные накладные расходы.
2 Единственное изменение, внесённое вне конфигурационного файла — обрезка начальной тишины. Несмотря на все усилия, может существовать конфигурация, немного превосходящая полученную здесь.