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

> Потокова транскрипція на Whisper: нарізка аудіо, VAD, faster-whisper і WebSocket-сервер на VDS.

Звичайний Whisper приймає готовий файл і віддає текст за кілька секунд чи хвилин — цього достатньо для розшифровки запису дзвінка, але не для субтитрів на льоту чи голосового асистента. Потокова транскрипція обробляє звук шматками у міру надходження і показує текст із затримкою в частки секунди. Розберемо, як зібрати такий конвеєр на власному VDS.

## Чим потокова транскрипція відрізняється від пакетної

Базова установка Whisper, описана у статті про [транскрипцію аудіо та відео на VPS](https://www.zevshost.net/uk/kb/whisper-ai-transkriptsiya/), працює з цілим файлом: модель бачить весь контекст одразу і видає найточніший результат. Потік же приходить без кінця — мікрофон, дзвінок, ефір — і чекати повний запис не можна.

Рішення — різати потік на короткі сегменти по 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 ядрами модель розміру `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="uk", 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](https://www.zevshost.net/uk/kb/localai-nastroika/), об'єднавши розпізнавання мовлення і генерацію відповіді в одному API. Для контролю затримки у проді корисно підключити [моніторинг AI-сервісів](https://www.zevshost.net/uk/kb/ai-monitoring-vps/) і відстежувати час обробки кожного чанка окремою метрикою.

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

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

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

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

---

Джерело: https://www.zevshost.net/uk/kb/whisper-potokovaya-transkripciya/
