Система live captions реального часу: архітектура, затримка, інтеграція
Субтитри в реальному часі (live captions) — технічний засіб реабілітації за ГОСТ Р 52872-2019 та міжнародним стандартом WCAG 2.1 (критерій 1.2.4). Ми розробляємо системи субтитрування, які працюють із затримкою менше 2 секунд. Це критично для трансляцій, конференцій, телебачення та освітніх платформ. Наша команда — 12 інженерів із сумарним досвідом понад 25 років у галузі STT та NLP. Ми реалізували 10+ інсталяцій для подій із аудиторією до 5000 осіб та забезпечили доступ до інформації для тисяч людей із порушеннями слуху. Впровадження AI-субтитрів дозволяє заощадити до 40% бюджету порівняно з ручним субтитруванням, а окупність настає протягом 2–3 місяців при регулярних трансляціях. Для оцінки вашого проєкту зв'яжіться з нами — ми запропонуємо рішення під ключ.
Проблеми, які вирішуємо
Стандартні субтитри часто відстають від мовлення на 5–10 секунд — це неприйнятно для людей із порушеннями слуху. Типові складнощі:
- Синхронізація тексту та звуку страждає при використанні batch-обробки аудіо.
- Хмарні STT-сервіси не завжди справляються з доменною лексикою (медична, юридична термінологія).
- Інтеграція з платформами на кшталт Zoom та Teams потребує окремого бота та налаштування API.
Ми вирішуємо ці проблеми через вибір streaming-моделі, оптимізацію буферизації та кастомізацію словника. Наприклад, в одному проєкті для конференції з телемедицини ми донавчили Whisper на корпусі медичних термінів — точність розпізнавання зросла з 82% до 95%.
Як забезпечити затримку менше 2 секунд?
Ключ — вибір streaming-моделі та архітектура передачі аудіо. Deepgram Nova-2 видає partial results кожні 200 мс, що дає затримку end-to-end близько 1 секунди — в 2–3 рази швидше, ніж faster-whisper large-v3 у batch-режимі. Для локальних сценаріїв ми використовуємо faster-whisper з VAD-фільтром та буфером 3 секунди, що дає 2.5–4 секунди. Але якщо потрібно < 2 сек — лише хмарний streaming.
Real-time STT стек
Для субтитрів із затримкою < 2 секунд від моменту мовлення використовуємо локальний faster-whisper або хмарний Deepgram Nova-2. Приклад ядра на Python:
import asyncio import websockets from faster_whisper import WhisperModel import numpy as np import sounddevice as sd class RealTimeCaptioner: def __init__(self): self.model = WhisperModel( "large-v3", device="cuda", compute_type="float16" ) self.buffer = [] self.chunk_duration = 3.0 # секунды буферизации self.sample_rate = 16000 async def stream_captions(self, websocket, audio_queue: asyncio.Queue): """Стриминг субтитров через WebSocket""" while True: chunk = await audio_queue.get() self.buffer.append(chunk) buffer_duration = len(self.buffer) * len(chunk) / self.sample_rate if buffer_duration >= self.chunk_duration: audio_data = np.concatenate(self.buffer) self.buffer = [] segments, _ = self.model.transcribe( audio_data, language="ru", vad_filter=True, vad_parameters={"min_silence_duration_ms": 500} ) for segment in segments: caption = { "text": segment.text.strip(), "start": segment.start, "end": segment.end, "confidence": segment.avg_logprob } await websocket.send(json.dumps(caption, ensure_ascii=False)) WebRTC інтеграція для браузера
Клієнтська частина на JavaScript захоплює аудіо з мікрофона та передає на сервер через WebSocket. Сервер повертає субтитри, які відображаються з rolling-вікном.
// Клиентская часть: захват аудио и стриминг на сервер class LiveCaptionClient { constructor(wsUrl) { this.ws = new WebSocket(wsUrl); this.captionDiv = document.getElementById('captions'); } async startCapturing() { const stream = await navigator.mediaDevices.getUserMedia({ audio: { sampleRate: 16000, channelCount: 1, echoCancellation: true } }); const audioContext = new AudioContext({ sampleRate: 16000 }); const processor = audioContext.createScriptProcessor(4096, 1, 1); processor.onaudioprocess = (event) => { const pcmData = event.inputBuffer.getChannelData(0); const int16Array = new Int16Array(pcmData.length); for (let i = 0; i < pcmData.length; i++) { int16Array[i] = Math.max(-32768, Math.min(32767, pcmData[i] * 32768)); } if (this.ws.readyState === WebSocket.OPEN) { this.ws.send(int16Array.buffer); } }; this.ws.onmessage = (event) => { const caption = JSON.parse(event.data); this.displayCaption(caption.text); }; const source = audioContext.createMediaStreamSource(stream); source.connect(processor); processor.connect(audioContext.destination); } displayCaption(text) { // Отображение с rolling-window (последние 2-3 строки) const line = document.createElement('p'); line.textContent = text; line.className = 'caption-line'; this.captionDiv.appendChild(line); // Убираем старые строки while (this.captionDiv.children.length > 3) { this.captionDiv.removeChild(this.captionDiv.firstChild); } // Auto-scroll this.captionDiv.scrollTop = this.captionDiv.scrollHeight; } } Як вибрати STT-модель для субтитрів?
Вибір між локальним та хмарним рішенням:
| Параметр | faster-whisper (локально) | Deepgram Nova-2 (хмара) |
|---|---|---|
| Затримка | 0.3–0.8 сек (інференс) | 0.1–0.3 сек (streaming) |
| Якість | висока (large-v3) | висока (спеціалізована) |
| Конфіденційність | повна | дані йдуть у хмару |
| Вартість | один GPU (~$0.5/год) | $0.004/хв аудіо |
| Підтримка мов | 99+ | 30+ |
Для завдань, де потрібна повна ізоляція даних (медичні, державні) — локальний faster-whisper із Triton Inference Server. Для типових трансляцій — хмарний Deepgram або AssemblyAI. Ми оцінимо проєкт та запропонуємо оптимальний варіант. Замовте попередній аудит — він безкоштовний та займе 30 хвилин.
Вимоги до відображення (WCAG 2.1)
/* Субтитри для людей із порушеннями слуху — WCAG 2.1 критерій 1.4.3 */ .caption-container { background-color: rgba(0, 0, 0, 0.85); color: #FFFFFF; font-size: 1.5rem; /* мінімум 24px */ line-height: 1.6; padding: 12px 20px; border-radius: 4px; max-width: 80%; font-family: Arial, sans-serif; /* висока розбірливість */ } /* Високий контраст (коефіцієнт 7:1 для AA+) */ .caption-line { color: #FFFFFF; text-shadow: 1px 1px 2px #000; } Інтеграція з Zoom/Teams через Bot
# Zoom використовує RTMP для стрімінгу субтитрів import httpx async def push_zoom_captions(meeting_id: str, caption_text: str, seq: int): """Відправляємо субтитри в Zoom через Closed Caption API""" async with httpx.AsyncClient() as client: await client.post( f"https://api.zoom.us/v2/meetings/{meeting_id}/live_streaming/captions", json={"text": caption_text, "seq": seq, "lang": "uk-UA"}, headers={"Authorization": f"Bearer {ZOOM_JWT_TOKEN}"} ) Що таке streaming transcription?
Streaming transcription — це технологія, при якій модель розпізнає мовлення в міру надходження аудіофрагментів, видаючи проміжні результати (partial results) кожні 100-200 мс. Це дозволяє оновлювати субтитри плавно, без пауз на очікування повної фрази. Використовуємо WebSocket для передачі аудіофрагментів та отримання тексту з часовими мітками.
Чек-лист для впровадження
- [ ] Аудит поточних каналів звуку та платформи
- [ ] Вибір STT-моделі (локальна/хмарна)
- [ ] Калібрування під доменну лексику
- [ ] Розробка WebRTC/WebSocket-сервера
- [ ] Інтеграція з Zoom, Teams, YouTube Live, RTMP
- [ ] Інтерфейс керування та ручної корекції
- [ ] Документація та навчання операторів
- [ ] Гарантія 6 місяців
Орієнтовні терміни
Веб-компонент субтитрування — 1–2 тижні. Повна інтеграція з платформами — 2–3 тижні. Для оцінки вашого проєкту зв'яжіться з нами — опишіть сценарій, і ми розрахуємо рішення. Економія бюджету може досягати 40% порівняно з ручним субтитруванням, а окупність — за 2–3 місяці. Отримайте консультацію прямо зараз!







