Lingvo — кейс
Два продукта на одном backend: синхронный перевод речи и AI-конспекты встреч.
01 Задача
Живой разговор между языками и аналитика встреч живут на одном backend, но у них разные требования к задержке: одному нужен realtime STT → MT → TTS прямо на аудио-пути, другому — структурированные саммари, action items и решения, извлекаемые после звонка. Оба должны работать на общем Django-ядре с единым биллингом и идентичностью.
02 Что сделал
Единый backend на Django + DRF + Celery обслуживает два Next.js-фронтенда (Translator и Meetings). WebRTC-медиа идёт через LiveKit SFU; отдельный Pipecat-агент на GPU-сервере подключается к комнате по WSS и крутит realtime-пайплайн, диспетчеризация — через Redis pub/sub, расход отдаётся обратно в backend. В Meetings добавлен note-taker-пайплайн плюс Celery-задачи на саммари и извлечение action items / решений, а Beat-задача собирает бриф перед встречей через RAG по недавним встречам (эмбеддинги pgvector). Платежи — за адаптерами Cryptomus и YooKassa с идемпотентной монотонной обработкой вебхуков.
- Один Django-backend обслуживает два Next.js-продукта (переводчик + встречи) с общим биллингом и идентичностью
- Realtime STT → MT → TTS через Pipecat-агент на GPU поверх LiveKit SFU, диспетчеризация через Redis pub/sub
- Саммари встреч, action items и решения извлекаются Celery; бриф перед встречей через RAG по pgvector
- Идемпотентные монотонные платёжные вебхуки за адаптерами Cryptomus / YooKassa
03 Аудио-путь в реальном времени
Распознавание речи работает на faster-whisper large-v3 на CUDA. Фраза заканчивается после примерно 0,7 секунды тишины или 25 секунд непрерывной речи, а Silero VAD отбрасывает фрагменты, слишком короткие или тихие, чтобы быть словами. Перевод идёт через OpenRouter, модель по умолчанию — Claude Haiku.
Синтез речи выбирается по языку: Kokoro для английского, XTTS-v2 для русского и других поддерживаемых языков, Edge-TTS — запасной вариант для тайского и остальных. Kokoro отдаёт первый звук примерно за 50–100 мс против 500–700 мс у Edge, и по нашей оценке это сокращает всю цепочку примерно с 2 до 1,5 секунды. Модели делят одну RTX 3070 Ti и занимают около 6,9 ГБ из 8.
04 Управление и устойчивость
Django и агент общаются через каналы Redis: бэкенд публикует события старта, остановки и перенастройки комнаты, агент заходит в комнату как бот и каждые 30 секунд отчитывается о расходе по сервисному токену. Участник может сменить язык посреди звонка, не выходя из комнаты. Если оба говорят на одном языке, комната только транскрибирует и не тратит ресурсы на перевод и синтез.
Обрыв связи не завершает комнату. Запись хранится отдельными дорожками в пронумерованных сегментах, а задача Celery склеивает их в один файл на сессию, так что пропуск остаётся только там, где участник действительно был офлайн.
Остальные функции звонка устроены так же. Участники могут делиться файлами прямо в звонке, а каждый может включить или выключить AI-озвучку для себя, не трогая остальных в комнате. Пакетная озвучка готового текста идёт через отдельный REST-эндпоинт и выполняется задачей Celery, отдельно от пайплайна живых звонков.
05 Память встреч
В Meetings бот-конспектатор транскрибирует звонок молча. Когда комната закрывается, задача Celery пишет саммари и извлекает задачи и решения. Каждую минуту задача Beat ищет встречи, которые начнутся через 10–11 минут, и готовит бриф по недавним встречам того же проекта.
Сообщения транскрипта и записи базы знаний превращаются в векторы размерностью 768 и хранятся в pgvector с индексом HNSW по косинусному расстоянию; модель по умолчанию — Gemini text-embedding-004. Та же модель распознавания обслуживает API транскрибации файлов, деля три слота воркеров между живыми звонками и офлайн-задачами.
06 Аккаунты, оплата и доставка
Пользователь входит через Telegram Login Widget и получает HttpOnly-cookie сессии, а токены доступа LiveKit живут не дольше часа. Тарифы привязаны к продукту: переводчик или встречи. Оплата идёт через Cryptomus (USDT TRC-20) и ЮKassa (СБП и карты): подпись вебхука проверяется, строка платежа блокируется, внешний id уникален в рамках провайдера, сумма и валюта сверяются, а статус может двигаться только вперёд.
Каждый push в main запускает Forgejo Actions и собирает четыре образа: Django, агент Pipecat и два фронтенда. Исследования тоже записаны честно: одно показало, что веб-приложение на iOS не удерживает звонок после блокировки экрана, поэтому фоновые звонки на iPhone требуют нативного приложения.
07 Результат
Один backend аккуратно несёт два продукта с разными realtime-ограничениями; аудио-путь остаётся на LiveKit, а control-plane идёт по Tailscale-mesh, знание о встречах ищется через векторные эмбеддинги. С мая по июль 2026 года проект прошёл 18 спринтов и 216 коммитов, в нём 13 ADR и больше 440 автотестов в бэкенде и агенте. Оба продукта работают в dev-окружении на GPU-сервере; публичный запуск впереди.