Ми стикалися із завданням: call-центр на 50 операторів, потрібні субтитри в реальному часі для супервайзера. Batch STT давав затримку 5 секунд — пропускав важливі моменти діалогу. На живих субтитрах конференції затримка в 2 секунди вже неприйнятна, а в голосовому асистенті кожна зайва мілісекунда погіршує UX. Рішення — streaming STT з частковими результатами через WebSocket. За 5 років ми вибудували архітектуру, яка тримає latency 100-500 мс при будь-яких навантаженнях.
Які проблеми вирішує streaming STT?
- Затримка: Без часткових результатів користувач чекає завершення фрази. Streaming видає попередню транскрипцію кожні 200-400 мс. Для call-центру це означає можливість миттєвої реакції — супервайзер бачить текст через 200 мс після вимовляння.
- Паузи та накладання: VAD + endpointing коректно обробляють тишу та overlapping speech. Налаштування aggressiveness=2 відсікає 90% пауз без втрати сенсу.
- Точність у реальному часі: Моделі з низькою latency (Deepgram Nova-2) показують WER <5% навіть при 200 мс. Вартість Deepgram Nova-2 становить $0.0043/хв, що на 40% дешевше Google STT.
Як ми будуємо streaming pipeline?
Типова архітектура, яку ми запускали в production:
Microphone → WebSocket (WSS) → FastAPI → STT Engine → NLP → Response
Ключові компоненти реалізовані на Python з асинхронними сокетами.
WebSocket сервер на FastAPI
from fastapi import FastAPI, WebSocket
from faster_whisper import WhisperModel
import numpy as np
import asyncio
app = FastAPI()
model = WhisperModel("medium", device="cuda", compute_type="float16")
@app.websocket("/stream")
async def stream_stt(websocket: WebSocket):
await websocket.accept()
audio_buffer = bytearray()
try:
while True:
chunk = await websocket.receive_bytes()
audio_buffer.extend(chunk)
if len(audio_buffer) >= 32000 * 2: # 2 sec @ 16kHz 16-bit
audio_array = np.frombuffer(audio_buffer, dtype=np.int16).astype(np.float32) / 32768.0
segments, _ = model.transcribe(audio_array, language="ru")
partial_text = " ".join([s.text for s in segments])
await websocket.send_json({"type": "partial", "text": partial_text})
audio_buffer = bytearray()
except Exception:
await websocket.close()
VAD (Voice Activity Detection)
VAD підключаємо до накопичення буфера: відсікаємо тишу, зменшуючи кількість транскрипцій.
import webrtcvad
vad = webrtcvad.Vad(2)
def is_speech(audio_chunk: bytes, sample_rate: int = 16000) -> bool:
return vad.is_speech(audio_chunk, sample_rate)
Для endpointing тримаємо ковзне вікно тиші 500-800 мс.
Налаштування WebRTC VAD
`aggressiveness=2` дає найкращий баланс чутливості та хибно-позитивних спрацьовувань. При менших значеннях пропускається більше мовлення, при більших – зростає кількість хибних відсічок.Клієнтська частина
const socket = new WebSocket('wss://api.example.com/stream');
const mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(mediaStream, { mimeType: 'audio/webm;codecs=opus' });
recorder.ondataavailable = (event) => {
if (socket.readyState === WebSocket.OPEN) socket.send(event.data);
};
recorder.start(250); // 250ms chunks
Чому VAD критичний для streaming?
Без VAD двигун обробляє весь аудіопотік, включаючи тишу. Це збільшує токенну вартість і затримку. На практиці ми бачили зростання latency p99 на 30% при відсутності попереднього VAD.
Як вибрати STT двигун?
Вибір між хмарою та self-hosted залежить від навантаження, вимог до конфіденційності та бюджету. Згідно з офіційною документацією Deepgram, Nova-2 має latency 180 мс при p95.
| Двигун | Latency p95 | Підтримувані мови | Вартість |
|---|---|---|---|
| Deepgram Nova-2 | 180 мс | 30+ | $0.0043/хв |
| Google STT Streaming | 250 мс | 125+ | $0.006/хв |
| Azure Speech | 280 мс | 100+ | $0.01/хв |
| faster-whisper (self) | 350 мс | 99 | ~$0.001/хв |
| Vosk (self, CPU) | 500 мс | 20+ | ~$0/хв |
Self-hosted рішення економлять до 80% при обсягах >1000 годин на місяць. Наприклад, faster-whisper на GPU коштує близько $0.001/хв. Для мультимовних проєктів Google та Azure кращі через широту покриття.
Як забезпечити latency p99 < 400 мс?
Ключові фактори: вибір двигуна з низькою latency, оптимізація VAD та налаштування буферизації. Для self-hosted використовуємо faster-whisper з CUDA та INT8-квантизацію — це знижує latency на 30% без втрати точності. Плюс попередня сегментація аудіо через VAD, щоб не транскрибувати тишу.
Які метрики моніторити?
- p99 latency — не більше 400 мс для self-hosted, 300 мс для хмарних рішень.
- CPU/GPU utilization — щоб уникнути перевантаження під піковим навантаженням.
- WER (Word Error Rate) — відстежуємо на вибірці.
- Кількість активних сесій — важливо для auto-scaling.
Процес реалізації під ключ
- Аналіз: Визначаємо мову, кількість спікерів, очікуваний RPS, вимоги до endpointing.
- Проєктування: Будуємо діаграму потоків, обираємо двигун, VAD та метод диспетчеризації.
- Розробка: Кодимо WebSocket сервер, інтегруємо STT, налаштовуємо auto-scaling.
- Тестування: Генеруємо синтетичні RTP потоки, вимірюємо latency p99, витоки пам'яті.
- Деплой: Розгортаємо в k8s з Helm, підключаємо моніторинг (Prometheus + Grafana).
- Передача: Документація, навчання команди, кодова база з коментарями.
Що входить у роботу
- Архітектурна схема та обґрунтування вибору
- Репозиторій з Docker-контейнерами та Helm-чартом
- API документація (OpenAPI)
- Інтеграція з клієнтськими SDK (Web, iOS, Android — опціонально)
- План тестування під навантаженням
- Підтримка 1 місяць
Терміни та вартість
| Етап | Термін |
|---|---|
| Базовий WebSocket стример | 3–4 дні |
| Self-hosted з VAD/endpointing | 1 тиждень |
| Повний pipeline | 2 тижні |
| Повний pipeline + клієнтські SDK | 2–4 тижні |
Вартість розраховується індивідуально під задачу. Отримайте оцінку проєкту — напишіть нам.
Наш досвід
Ми впровадили streaming STT для 10+ проєктів: від call-центрів до живих субтитрів. Наш досвід включає інтеграцію з глибоким фреймворком діалогів та налаштування під високе навантаження (до 1000 одночасних сесій). Гарантуємо latency p99 < 400 мс для self-hosted рішень на базі NVIDIA A10G. Сертифіковані по CUDA (NVIDIA).
Готові реалізувати streaming STT під ключ. Зв'яжіться для консультації — обговоримо вашу задачу та підберемо оптимальну архітектуру.







