Технологии

«Текст входит, звук выходит»: AWS показала потоковый синтез речи на vLLM-Omni в SageMaker

Голосовые агенты, тренажёры и ассистенты не должны отвечать долгими паузами, поэтому AWS собрала пример, в котором речь начинает звучать до того, как модель закончила генерировать ответ. Текст уходит в Qwen3-TTS, аудио возвращается по одному постоянному двунаправленному соединению — полнодуплексному WebSocket поверх HTTP/2 на порту 8443. Контейнер vLLM-Omni при этом умеет не только синтез речи: в нём есть распознавание, аудиогенерация, изображения и видео через OpenAI-совместимые API.

«Текст входит, звук выходит»: AWS показала потоковый синтез речи на vLLM-Omni в SageMaker

Почему схема «запрос — полный ответ» не годится для голоса

Голосовым агентам, интерактивным обучающим приложениям, инструментам доступности и ассистентам поддержки нужно отвечать без долгих пауз молчания. Классическая схема этого не даёт: пока модель не закончит генерировать весь ответ, воспроизводить нечего.

В разобранном AWS примере модель синтеза речи разворачивается на Amazon SageMaker AI так, чтобы начинать воспроизводить речь раньше, чем сгенерирован полный ответ. Для этого используется AWS-контейнер vLLM-Omni Deep Learning Container: текст входит, аудио выходит по одному постоянному двунаправленному соединению, а весь сценарий проходится через приложение на Gradio.

Материал — первая часть серии о специализированных контейнерах, куда помимо vLLM-Omni входят WhisperX и llama.cpp, и посвящён именно потоковой речи. Вторая часть применит тот же контейнер к генерации изображений и видео. Предыдущая публикация серии закрывала входную сторону голосового конвейера: она передавала аудио с микрофона в модель распознавания Voxtral-Mini-4B Realtime и возвращала события транскрипции. Новая работа добавляет выходную сторону — текст уходит в Qwen3-TTS, а синтезированная речь возвращается тем же потоком. Оркестрация между двумя эндпоинтами остаётся за рамками разбора.

Что именно расширяет vLLM-Omni

Проект vLLM-Omni расширяет vLLM за пределы генерации текста на модели, которые обрабатывают или порождают текст, аудио, изображения и видео. Его абстракция гетерогенного конвейера координирует многостадийные рабочие процессы, включая авторегрессионные и диффузионные стадии, а также даёт потоковые выходы и OpenAI-совместимые API. AWS-контейнер упаковывает отслеживаемые релизы vLLM-Omni в свои образы и добавляет промежуточное звено маршрутизации для SageMaker AI.

Спектр модальностей шире, чем синтез речи. В документации контейнера перечислены маршруты и примеры моделей: синтез речи на /v1/audio/speech с Qwen3-TTS-1.7B и CosyVoice3-0.5B, аудиогенерация на /v1/audio/generate со Stable-Audio-Open-1.0, генерация изображений на /v1/images/generations с FLUX.2-klein-4B и ERNIE-Image-Turbo, видео в асинхронном режиме на /v1/videos и в синхронном на /v1/videos/sync с Wan2.1-T2V-1.3B и Wan2.1-VACE-1.3B, а также мультимодальный чат на /v1/chat/completions с Qwen2.5-Omni-3B.

Образы публикуются в двух вариантах: для EC2 и EKS и отдельно для Amazon SageMaker AI, оба слушают порт 8080. Образ собран на Amazon Linux 2023 с постоянным патчингом безопасности. Внутри, помимо самого vLLM-Omni и базового стека из PyTorch, CUDA 13.0, NCCL и Python 3.12, лежат FlashInfer с предкомпилированными cubin для быстрого холодного старта, DeepEP с ядрами экспертного параллелизма для крупных MoE-моделей, LMCache вместе с NIXL для выгрузки KV-кеша и разделённого prefill и decode, runai-model-streamer для потоковой загрузки весов прямо из S3 или GCS, EFA и OpenMPI для многоузловой сети, а также espeak-ng и ffmpeg как системные зависимости для фонемайзера синтеза речи и кодирования аудио и видео.

Отдельно стоит отметить маршрутизацию: образ для SageMaker дополнительно содержит промежуточное звено, которое через заголовок CustomAttributes направляет /invocations на маршруты конкретной модальности — синтез речи, изображения, видео и так далее. Версия контейнера v1.5 добавляет метку возможности двунаправленного стриминга и ту самую маршрутизацию, которую требует SageMaker AI.

Как устроен путь запроса

Двунаправленный стриминг SageMaker поднимает полнодуплексный WebSocket, транспортируемый поверх HTTP/2. Клиент подключается к эндпоинту SageMaker Runtime на порту 8443, а боковой контейнер вывода перенаправляет соединение на нативный WebSocket-маршрут внутри контейнера.

Пример использует маршрут /v1/audio/speech/stream — один из нативных WebSocket-маршрутов, которые предоставляет vLLM-Omni. По одному соединению клиент отправляет конфигурацию сессии и текстовые события, а Qwen3-TTS возвращает события жизненного цикла аудио и отдельные чанки. Аудиособытия и куски PCM с частотой 24 кГц идут обратно по тому же соединению.

Клиентская сторона выглядит как три последовательных сообщения: сначала конфигурация сессии с голосом, языком, форматом ответа pcm и включённым stream_audio, затем событие с текстом и, наконец, событие завершения ввода. Компонент Gradio проигрывает каждый чанк по мере поступления, а в поле статуса показывается число чанков и суммарный объём аудио в байтах.

Инстанс-пулы: как не упереться в квоты и в счёт

В конфигурации эндпоинта используются инстанс-пулы SageMaker. Пул задаёт упорядоченный по приоритету список совместимых типов инстансов для одного продакшен-варианта: сначала SageMaker пробует ml.g6.xlarge, а при отсутствии ёмкости откатывается на ml.g6e.xlarge, ml.g5.xlarge или ml.g4dn.xlarge. При этом выделяется один инстанс, а не по одному на каждую запись пула.

У этой гибкости есть две цены, о которых AWS предупреждает прямо. SageMaker проверяет квоту для каждой записи пула при создании эндпоинта, поэтому квота нужна на каждый включённый тип, и почасовая стоимость может измениться, если будет выбран другой инстанс. Чтобы этого избежать, в примере есть параметр, ограничивающий пул типами, которые укладываются в квоту, цену и требования по производительности.

Что нужно для запуска и о чём не забыть после

Список предварительных условий довольно конкретный: аккаунт AWS с настроенными учётными данными для AWS CLI или SDK, Git, Python 3.12 или новее, роль исполнения SageMaker AI, права на создание и вызов эндпоинтов, квота хотя бы на один тип инстанса из пула, boto3 версии 1.40.0 или новее и HTTP/2-клиент SageMaker Runtime версии 0.4.0. Разбор ведётся в регионе Северная Вирджиния, а URI образа и адрес эндпоинта собираются из переменной с регионом.

Первое развёртывание занимает время, потому что инстанс скачивает образ контейнера и артефакты модели. Дождавшись состояния InService, можно запускать клиент Gradio и открывать его локально на порту 6006: опция публичной ссылки по умолчанию выключена и включается только при необходимости.

Скрипт развёртывания проходит всю цепочку ресурсов сам: он создаёт модель SageMaker из контейнера, конфигурацию эндпоинта и реальный эндпоинт. Какую именно модель загружать в контейнер, определяется переменной окружения SM_VLLM_MODEL. Тот же скрипт прогоняет дымовой тест потоковой передачи и сохраняет результат в файл validation-output.wav.

Есть две настройки, которые легко упустить и на которых сценарий ломается. Настройка AMI для вывода обязательна для бокового контейнера SageMaker, который обрабатывает HTTP/2 WebSocket. А путь вызова модели нужно указывать без ведущей косой черты, потому что SageMaker добавляет её сам, прежде чем переслать запрос.

Завершается разбор уборкой ресурсов. Процесс Gradio останавливают, а затем удаляют эндпоинт, его конфигурацию и модель отдельной командой. Если процесс прервался до конца уборки, ресурсы удаляют через консоль или API, потому что работающий GPU-эндпоинт продолжает начислять стоимость.

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

Первоисточники

  1. AWS Machine Learning Blog — «Build real-time voice applications with vLLM-Omni on SageMaker AI – Part 1» (28 сентября 2026)
  2. AWS Deep Learning Containers — «Multimodal Serving using vLLM-Omni DLC»