К основному содержимому

Потоковая транскрипция Whisper в реальном времени на сервере

AI-агенты на VDS · 29.09.2026

Обычный Whisper принимает готовый файл и отдаёт текст через несколько секунд или минут — этого достаточно для расшифровки записи звонка, но не для субтитров на лету или голосового ассистента. Потоковая транскрипция обрабатывает звук кусками по мере поступления и показывает текст с задержкой в доли секунды. Разберём, как собрать такой конвейер на своём VDS.

Чем потоковая транскрипция отличается от пакетной

Базовая установка Whisper, описанная в статье про транскрипцию аудио и видео на VPS, работает с целым файлом: модель видит весь контекст сразу и выдаёт наиболее точный результат. Поток же приходит без конца — микрофон, звонок, эфир — и ждать полную запись нельзя.

Решение — резать поток на короткие сегменты по 2-5 секунд, распознавать каждый почти независимо и склеивать результат. Плата за скорость — модель видит меньше контекста, поэтому точность на границах сегментов немного ниже, чем при пакетной обработке.

Нарезка аудио и определение речи (VAD)

Резать поток строго по таймеру плохо: слово может оказаться разрезанным пополам между двумя чанками. Voice Activity Detection (VAD) находит паузы в речи и режет именно по ним. Библиотека silero-vad определяет границы фраз за миллисекунды и не требует GPU.

pip install silero-vad faster-whisper sounddevice numpy
python3 -c "import torch; model, utils = torch.hub.load('snakers4/silero-vad', 'silero_vad')"

Типичная схема: буфер накапливает аудио, VAD отмечает конец фразы, накопленный кусок сразу уходит в модель распознавания, буфер очищается.

faster-whisper в потоковом режиме

Для потоковой обработки лучше подходит faster-whisper — реализация на CTranslate2, которая распознаёт короткие сегменты в 2-4 раза быстрее оригинального PyTorch-кода Whisper. На CPU-сервере с 8 ядрами модель size small обрабатывает 3-секундный чанк примерно за 0.5-0.8 секунды — этого достаточно для субтитров без заметной задержки.

from faster_whisper import WhisperModel

model = WhisperModel("small", device="cpu", compute_type="int8")
segments, info = model.transcribe("chunk.wav", language="ru", beam_size=1)
for seg in segments:
    print(seg.start, seg.end, seg.text)

beam_size=1 и модель размера small или base — обязательный компромисс для потока: полноразмерный large-v3 с большим beam search даёт задержку в несколько секунд на чанк, что рушит идею реального времени.

Сервер на WebSocket для приёма звука

Клиент — браузер или приложение — шлёт аудио кусками через WebSocket, сервер копит буфер, режет по VAD и отдаёт текст обратно тем же соединением. Минимальный сервер на websockets и asyncio:

import asyncio, websockets

async def handle(ws):
    buffer = bytearray()
    async for chunk in ws:
        buffer.extend(chunk)
        if len(buffer) > 48000 * 2 * 3:  # ~3 секунды звука 16-бит
            text = transcribe_chunk(bytes(buffer))
            await ws.send(text)
            buffer.clear()

asyncio.run(websockets.serve(handle, "0.0.0.0", 8765).__aenter__())

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

Задержка против точности: что выбрать

Размер чанкаЗадержкаТочностьКогда использовать
1-2 секминимальнаяниже, рвутся словаживые субтитры, ассистент
3-5 секумереннаяхорошаязвонки, совещания
8-10 секзаметнаявысокаялекции, подкасты
весь файлпосле записимаксимальнаяархивная расшифровка

Для большинства задач субтитров в реальном времени разумный компромисс — чанк 3 секунды с моделью small на CPU или medium на GPU.

Куда встроить готовый транскрипт

Текст в реальном времени пригождается в трёх сценариях: субтитры на трансляции, голосовой ввод в чат-бота и поиск по звонкам. Если транскрипт нужен как вход для LLM-агента — например, чтобы бот отвечал голосом на вопрос из речи — удобно отдавать результат в OpenAI-совместимый эндпоинт через LocalAI, объединив распознавание речи и генерацию ответа в одном API. Для контроля задержки в проде полезно подключить мониторинг AI-сервисов и отслеживать время обработки каждого чанка отдельной метрикой.

  • Живые субтитры — WebSocket-сервер плюс VAD плюс модель small/base.
  • Голосовой ввод для бота — тот же конвейер, но с накоплением до конца фразы перед отправкой в LLM.
  • Поиск по звонкам — можно вернуться к пакетной обработке: задержка не критична, важна точность.

Чек-лист запуска потоковой транскрипции

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

  • Определите допустимую задержку сценария: 1-2 сек для ассистента, 5-10 сек для субтитров лекции.
  • Выберите размер модели под ресурс: base/small на CPU, medium+ на GPU.
  • Настройте VAD, а не резку по таймеру — так меньше рваных слов на стыках.
  • Добавьте переподключение и восстановление буфера при обрыве WebSocket.
← Назад в базу знаний Задать вопрос поддержке