Розробка live captions на базі ШІ: від ідеї до впровадження

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1564 послуг
Розробка live captions на базі ШІ: від ідеї до впровадження
Середній
від 1 дня до 3 днів
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1358
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1250
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    956
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1188
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    646
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    929

Система 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 місяці. Отримайте консультацію прямо зараз!

Розпізнавання та синтез мовлення: перша лінія проблеми

Ми стикаємося із замовником, який має 40 000 годин записів кол-центру й хоче транскрибувати їх за тиждень — це типова задача розпізнавання мови ASR. Штатний хмарний ASR (Google Speech-to-Text) видає WER 28% на галузевій лексиці, а ціна при таких обсягах стає непідйомною. Завдання — знизити WER нижче 10% і перейти на self-hosted інференс. Така ситуація повторюється в кожному другому проєкті, і ми маємо напрацьований патерн рішення.

Типові технічні проблеми та їх усунення

WER не сходиться до потрібної метрики. Найчастіше винна не архітектура, а дані: шумні аудіо без нормалізації рівня (–23 LUFS замість стандарту), змішані мови в одному каналі, акцент, специфічна доменна лексика. Whisper large-v3 з коробки дає WER 8–12% на чистій українській і провалюється до 25–35% на записах з PSTN-артефактами та вузькосмуговим кодеком G.711.

Діаризація ламається при більш ніж двох спікерах. pyannote/speaker-diarization-3.1 працює стабільно при 2–3 мовцях, але DER (Diarization Error Rate) зростає з 6% до 18–22% при 5+ учасниках конференції. Проблема посилюється перехресними репліками: за замовчуванням min_duration_on=0.1 обрізає короткі вставки. Рішення — збільшити min_duration_on до 0.3 та додати overlap detection через pyannote-overlap-detection.

Клонування голосу — латентність чи якість. XTTS v2 (Coqui) дає натуральний голос, але при потоковій генерації stream_chunk_size=20 перший аудіочанк прилітає через 1.4–2.0 с — неприйнятно для інтерактивних сценаріїв. StyleTTS2 та Kokoro швидші, але вимагають точного підготовки референсного аудіо. Ми навчилися вирішувати цю дилему за допомогою гібридного підходу: на старті використовуємо Silero TTS (50–100 мс TTFB), а після отримання перших 3 секунд аудіо перемикаємо на XTTS для кращої натуральності.

Як вибрати ASR-модель під ваші дані?

Модель WER (українська, чистий запис) WER (PSTN, кодек G.711) Швидкість інференсу (фактор real-time) Вартість інференсу (1 год аудіо, A10G)
Whisper large-v3 8–10% 25–35% ~0.1x (55 с на 40 хв) ~$0.50
Whisper medium 12–15% 30–40% ~0.3x ~$0.15
Wav2Vec2 XLSR-53 15–18% 28–35% ~0.8x ~$0.08
Whisper large-v3 + fine-tune 4–7% 10–15% ~0.1x ~$0.50

faster-whisper (CTranslate2) швидший за оригінальний Whisper у 4 рази при однаковому WER. Для продакшену ми завжди використовуємо його.

Практичний приклад: fine-tuning Whisper на доменній лексиці

Фінтех-компанія з 12 000 дзвінків/день. Початковий WER на українській з банківською лексикою — 22% (Google STT). Після fine-tuning whisper-medium на 200 годинах розмічених записів через Hugging Face transformers + Seq2SeqTrainer з learning_rate=1e-5, warmup_steps=500 — WER впав до 7.3%. Інференс на одній A10G через faster-whisper з compute_type=float16 обробляє 40-хвилинний дзвінок за 55 секунд. Підсумкова вартість інференсу — $0.50 за годину аудіо, що в 6 разів дешевше за хмарне рішення. Проєкт виконано за 6 тижнів, включаючи підготовку даних і валідацію.

Техніка fine-tuning описана в офіційній документації Whisper на Hugging Face.

Як донавчити Whisper на доменних даних?

Коли загальна модель не справляється, fine-tuning — перший інструмент. Мінімальний датасет для помітного покращення — 20–30 годин розміченого аудіо в цільовому домені. Розмітку можна отримати через ітеративний процес: прогнати через базову модель → вручну виправити 10–15% помилок → перенавчити → повторити.

training_args = Seq2SeqTrainingArguments(
    per_device_train_batch_size=16,
    gradient_accumulation_steps=2,
    learning_rate=1e-5,
    warmup_steps=500,
    max_steps=5000,
    fp16=True,
    predict_with_generate=True,
    generation_max_length=225,
)

При fine-tuning обов’язково заморожуйте encoder перші 1000 кроків (model.freeze_encoder()), інакше акустичні ознаки роз’їдуться раніше, ніж decoder адаптується до нової лексики.

Синтез мовлення: що обрати для вашого сценарію?

Модель Латентність (TTFB) Натуральність MOS Клонування Мови
XTTS v2 1.2–2.0 с 4.1–4.3 Так, 3 с референсу 17
StyleTTS2 0.3–0.6 с 4.0–4.2 Так, вимагає адаптації en, + fine-tune
Kokoro-82M 0.08–0.15 с 3.7–3.9 Ні en, ja
Silero TTS 0.05–0.1 с 3.4–3.6 Ні ru, en, de, та ін.
Edge-TTS ~0.4 с (cloud) 4.0 Ні 100+

Для інтерактивних ботів з вимогою TTFB < 300 мс — Silero або Kokoro. Для озвучення контенту, де важлива натуральність — XTTS v2 з потоковою віддачею через WebSocket. Ми гарантуємо, що підібрана модель відповідатиме вашим вимогам до латентності та якості — це підтверджено на 50+ реалізованих проєктах.

Наш досвід та гарантії

10+ років досвіду в NLP та speech processing. 50+ успішних проєктів для fintech, telecom, медицини. Сертифіковані моделі (Model Card + bias audit). Ми гарантуємо зниження WER до цільового рівня, інакше повертаємо кошти.

Що входить у роботу з нами?

Клієнт отримує:

  • Документацію: model card, інструкцію з розгортання, API-специфікацію (OpenAPI 3.0)
  • Код: готові скрипти для інференсу, пайплайни обробки (Docker Compose + Kubernetes маніфести за потреби)
  • Доступи: до self-hosted інстансів, графіки моніторингу (Grafana + Prometheus)
  • Навчання: 2 сесії для вашої команди (налаштування, експлуатація, troubleshooting)

Ми також надаємо сертифікат відповідності моделі (Model Card + bias report), що підсилює довіру до рішення.

Процес роботи та терміни

  1. Аудит-сесія – беремо 2–4 години ваших записів, проганяємо через кілька моделей, вимірюємо WER/CER, дивимося на розподіл помилок (лексичні, акустичні, мова). Займає 1–2 дні.
  2. Вибір архітектури – під ваш throughput: один GPU для 1000 хв/день або кластер з балансувальником для 100 000+ хв/день.
  3. Реалізація – Docker-контейнер з FastAPI або Triton Inference Server для батчованого інференсу. Інтеграція з чергою Kafka.
  4. Тестування – A/B тест на продакшн-даних, порівняння з baseline (Google/Azure STT).
  5. Деплой – CI/CD (GitHub Actions + ArgoCD), моніторинг (Grafana + WER/CER алерти).

Терміни:

  • Базова інтеграція готової моделі – 1–2 тижні.
  • Fine-tuning з підготовкою даних та валідацією – 4–8 тижнів.
  • Повна розробка голосового пайплайну (ASR + діаризація + TTS + моніторинг) – 2–4 місяці.

Зв'яжіться з нами для безкоштовної консультації — оцінимо ваш проєкт за 2 дні. Або замовте пілотний fine-tuning на 20 годинах ваших даних і отримайте перші результати вже за 2 тижні.