py_faster_whisper
мост ASR, файловый WebUI и диаризация
Репозиторий принимает живой PCM-поток или аудио/видео файл, вызывает внешние модели распознавания речи и разделения по говорящим, затем возвращает текст через NATS или HTTP/WebUI.
Deployment · 04.10.2026 · проверенная поставка
Chat-agent и voice поставляются отдельно
chat-agent.gis-master.ru
Стэк web-rtc-komaroff: Frontend, Core, Agent, LLM, workflow runtimes, PostgreSQL и общий NATS. Каталог документации остаётся здесь.
voice.gis-master.ru
Стэк py_faster_whisper: один live ASR bridge, пять file UI, диагностика, lock, пять H100 requesters и три CPU sidecars.
Оба host используют OAuth2 для UI, API и WebSocket. Voice подключён к общему NATS. Live ASR: streaming через NATS/H100 worker. Файловый ASR: LinTO HTTP. Subjects, H100, Ollama и TURN сохраняются.
Postgres volume сохраняется; benchmark и summary используют прежний whisper_bench_jobs на gis-master.ru. Сначала поставляется chat, затем voice после освобождения file lock.
Deployment runbook · Проверка всех 29 сервисов · source/CI/runtime/live проверяются отдельно. Следующие датированные измерения описывают прежние запуски.
Система связывает интерфейсы с моделями. Сами модели — отдельные сервисы
Инициаторы
Voice-chat передаёт живой аудиопоток; оператор загружает файл через WebUI.
Внешнее владение
Voice владеет своим public ingress и requesters. Общий NATS принадлежит chat; H100 модели и receivers находятся снаружи.
Внутри репозитория нет LLM, agent workflow, собственной БД или WebRTC media server.
Историческая причина разделения ownership по репозиториям из исходников не устанавливается.
Один entry point включает два независимых runtime-контура
Stream bridge
ASR_MODE=streamingPCM по NATS → CPU VAD → H100 worker → partial/final/rejected/error. LinTO HTTP остаётся в batch и файловом пути.
python -m src.stt_whisper_to_nats
WebUI + file runner
WEBUI_ENABLEDaiohttp страницы, upload API, автоматические и staged jobs, diagnostics, snapshots и downloads.
Хотя бы один контур должен быть включён.
| Page mode | Назначение | Главный результат |
|---|---|---|
diarize / transcribe_only | Автоматическая обработка одного файла | Plain text; при healthy backend — speaker transcript |
staged | Раздельно запускать ASR, diarization и combine | Повторно используемые cached artifacts и timings |
bench / solution / case | Сравнивать сохранённые конфигурации и прогоны | results.jsonl, timing/RTF/quality proxies |
summary / diagnostics | Сводка прогонов и health/smoke checks | Наблюдаемое состояние зависимостей |
Код организован вокруг orchestration, WebUI и трёх sidecar-моделей
src/stt_whisper_to_nats.pyentry point, NATS stream bridge, automatic file workersrc/webui/server.pyaiohttp routing, upload/download, lock, page selectionsrc/webui/file_mode.pymedia normalization, chunks, LinTO calls, transcript mergesrc/webui/staged_jobs.pyfilesystem artifacts и независимые этапы staged pipelinesrc/{diarization,diarization_syntax}.pyHTTP contract, word attribution, speaker turns, optional syntax passsrc/*_diarization_server.pypyannote, sherpa-onnx, NeMo Sortformer HTTP sidecarssrc/webui/static/single-page clients, NATS WebSocket client, stylesstack/ · docker/ · .gitlab-ci.ymlimages, Dry Stack deployment, CI/CDtests/file/diarization flows, transports, health и diagnostics contractsHotspot: несколько orchestration-файлов превышают тысячу строк. Это подтверждает широкую область изменений, но не объясняет, почему границы выбраны именно так.
Файлы и batch связывают HTTP-модели с событиями NATS
Живой поток: PCM16 превращается в короткие фразы
State
Буферы в памяти на output subject/session. После restart не восстанавливаются.
Transport
Live streaming передаёт речь H100 worker по NATS. LinTO CONNECT используется отдельно для файлов и batch.
Ошибки
Sequence gaps и ошибки активного stream дают события; session/stream ID отсекают устаревшие результаты.
Файл: ASR и разделение по говорящим сходятся по timestamps
Upload и normalize
Файл сохраняется в job directory; ffmpeg создаёт mono 16 kHz WAV и audio-only artifact.
ASR chunks
По умолчанию 300 s, overlap 15 s, последовательно, с двумя повторами; нужны word timestamps.
Diarization параллельно
После healthy preflight backend получает тот же звук. При недоступности остаётся plain transcript.
Combine
Слово относится к speaker по midpoint/overlap; соседние слова становятся speaker turns.
Один active automatic job на процесс. Новый job отменяет прежний; внешний lock добавляет межпроцессную сериализацию.
Staged mode отделяет вычисления от combine
prepare
Один upload создаёт reusable audio artifacts.
Этапы можно запускать и повторять независимо. Результаты сохраняются на файловой системе.
combine
Не вызывает модели повторно; читает готовые JSON/text artifacts.
Bench layer
Сохраняет прогоны в results.jsonl и считает timing, RTF и quality proxies. Это не WER/DER.
Основное состояние — память процесса и локальная файловая система
Live
ephemeralPCM buffers, VAD state, active phrase tasks.
Consistency boundary: один процесс bridge. Restart сбрасывает незавершённые фразы.
Automatic file job
filesystemstate.json, input, normalized audio, chunks, transcript и diarization payloads.
Terminal job directory планируется к удалению через 30 s.
Staged / bench
reusableArtifacts переживают отдельные вызовы этапов; bench дописывает results.jsonl.
Зависимые artifacts инвалидируются при повторе upstream step.
Model cache
Docker volumeHF / Torch / NeMo caches принадлежат sidecar containers.
В репозитории нет schema, migrations, ORM или application database.
Практический эффект: HTTP snapshot — резервный канал состояния, но automatic artifacts имеют короткое окно после завершения; staged artifacts рассчитаны на повторный анализ.
HTTP surface состоит из UI API и двух модельных контрактов
WebUI API
POST /api/file-transcribe | combined automatic job |
POST /api/file-prepare | staged upload + media artifacts |
POST /api/file-{transcribe|diarize|combine}-step | independent stage |
GET /api/file-job | snapshot / heavy artifacts |
GET /health | WebUI liveness |
Model API
POST /transcribe | multipart file → text or JSON with word timestamps |
POST /diarize | multipart audio → speakers, segments, exclusive_segments |
GET /healthz | ready/model metadata; 200 or 503 |
Contract-sensitive
Имена полей и timestamps используются Python merge logic и JavaScript renderers. Менять producer, consumer и tests нужно вместе.
NATS несёт live audio, результат и прогресс; файл передаётся по HTTP
| Канал | Payload / роль |
|---|---|
ASR_IN_PREFIX + suffix | [meta_len][meta JSON][pcm16] |
ASR_OUT_PREFIX + suffix | Streaming: version 1 partial/final/rejected/error, session_id/stream_id/phrase_id. Batch: legacy pending/final/error. |
| file job subjects | progress и result envelopes для браузера |
| NATS WebSocket | быстрые UI updates; HTTP polling остаётся fallback |
to.inference.linto.* | HTTP CONNECT transport через nats-proxy |
Wire validation
Размер metadata, JSON и PCM frame проверяются до обработки.
Browser boundary
При настроенном NATS сервер внедряет WS credentials в HTML meta. Это функциональный контракт и security-sensitive boundary.
Событие progress не доказывает доставку самого media к модели. Нужны requester, matching receiver, upstream health и итоговый result.
Три sidecar реализуют один HTTP-контракт, но имеют разные runtime-профили
| Service | Модель / исполнение | Особенности | Общий контракт |
|---|---|---|---|
| pyannote | speaker-diarization-community-1CPU/GPU по DEVICE | HF gated token; exclusive diarization; pipeline lock | GET /health[z]POST /diarizesegments exclusive_segments speaker_count timings |
| sherpa-onnx | segmentation + 3D-Speaker embeddings CPU-oriented | Загрузка ONNX artifacts; explicit readiness | |
| Sortformer | NeMo diar_streaming_sortformer_4spk-v2.1 | До 4 speakers; окна и stitching для длинных файлов; Triton runtime compile |
Progress
Sidecar может публиковать hook-based NATS events, если переданы job metadata и NATS config.
Serialization
Model invocation защищён lock: запросы внутри процесса не исполняются одновременно.
Fallback
Automatic file mode продолжает ASR без speakers, если preflight diarization не проходит.
Production model traffic может идти через HTTP CONNECT поверх NATS
Fail closed
Если proxy URL задан, код не переключается на прямой HTTP при ошибке proxy.
Ownership
Этот stack владеет всеми voice UI, diagnostics, lock, requesters, ASR bridge и CPU sidecars. Public routes — в voice stack; matching H100 receivers и модели остаются снаружи.
Current runtime evidence
04.10.2026: WebUI, streaming ASR, H100 requesters, три CPU backend и внутренние admin targets — OK. Direct H100 probe остаётся INFO FAIL.
Source → build-labels images → Dry Stack runtime
Deployed services in this stack
Один bridge, пять file UI, diagnostics, lock, пять requesters, три CPU sidecars и gateway.
Streaming checks обязательны. Полная unit suite проверена локально. Selective build использует diff предыдущего SHA; image revision и manual deploy проверяются отдельно.
Локальные tests широкие; production E2E требует отдельного runtime evidence
Локальный unittest run
Выполнен 04.10.2026. Покрыты orchestration, streaming NATS, contracts, locks, transports, diagnostics и sidecar helpers.
VERIFIED this checkoutЧто доказывают tests
Поведение Python-кода с локальными HTTP/NATS stubs, merge logic, retries, readiness и error shaping.
Чего они не доказывают
Загрузку реальных GPU-моделей, внешний NATS receiver, ingress и named production behavior.
Live smoke
На WAV 9.32 s проверены transcription, staged, четыре H100 cases и три CPU backends: два говорящих. Status/smoke OK; снимок 04.10.2026.
Green build или merge — не подтверждение rollout. Для поставки нужны раздельные доказательства: commit/CI → image → stack health → пользовательский сценарий.
Основные следы эволюции видны в документации, зависимостях и границах модулей
| Evidence | As-is вывод | Практический риск |
|---|---|---|
| Chat и voice разделены | Voice владеет 16 services и зависит от общего NATS | Перед prune проверять полный состав, сеть и storage |
stt_whisper_to_nats.py, file_mode.py, server.py очень крупные | INFERRED: широкие change surfaces | Изменение контракта затрагивает несколько concerns |
dtorry/nats-proxy:latest | Floating runtime dependency | Одинаковый source может получить другой proxy image |
NeMo dependency указывает на Git main | Непинованный upstream | Воспроизводимость Sortformer build ограничена |
| Streaming checks обязательны; full suite локальная | CI gate покрывает streaming protocol и integration | File UI и модели требуют отдельной функциональной приёмки |
UNKNOWN: почему эти компромиссы приняты. Git и code показывают состояние, но не подтверждают rationale.
Чтобы добавить возможность, меняйте контракт на его реальной границе
Новый diarization backendреализовать /healthz + /diarize → добавить image/stack → contract testsНовое WebUI действиеroute в server.py → orchestration/job artifact → JS state/render → HTTP testsНовое поле result eventPython payload producer → NATS/HTTP snapshot → browser consumer → backwards-compat testsДругой model transportmodel_transport.py → environment contract → stack requester/receiver → cold/warm smokeНовая benchmark metricbench.py calculation → result schema → summary renderer; назвать proxy честноИная retention policyautomatic cleanup scheduler и staged store lifecycle → download/snapshot UX → disk evidenceСначала
Зафиксировать producer/consumer и ownership данных.
Потом
Проверить source, image, stack и live behavior как четыре разных уровня.
Пять областей, где локальная правка легко становится межсервисной
| Если меняется | Проверь вместе | Последствие пропуска |
|---|---|---|
| Wire packet / NATS subject | voice producer, bridge, consumer, JS WS client | Тихая потеря audio или result events |
| Word timestamps / diarization JSON | LinTO response parser, attribution, sidecars, downloads | Неверные speaker turns |
| Job lifecycle / cleanup | runner, store, lock, polling, download window | Пропавшие artifacts или конфликт jobs |
| Proxy route | requester, NATS subject roots, external receiver, upstream health | Progress без фактической доставки media |
| Stack service/image | build labels, registry path, Dry Stack, external network | Source и runtime расходятся |
Один active automatic file job на процесс.
Horizontal scale требует общего lock и продуманного artifact ownership.
Целевой SLA и допустимая retention не заданы.
Как войти в проект без чтения всех файлов подряд
Запуск и flags
Начать с _main_async и settings в stt_whisper_to_nats.py.
Выбрать flow
Live → stream service. File → runner + file_mode.py. Staged → staged_jobs.py.
Найти boundary
HTTP route, NATS subject, artifact или Dry Stack service.
Доказать изменение
Узкий test → full suite → runtime smoke по затронутому маршруту.
Технический итог
- Репозиторий — orchestration layer, а не единая ASR-модель.
- Live и file flows используют общие model contracts, но разное state.
- Filesystem artifacts — часть API поведения, особенно в staged mode.
- Runtime ownership пересекает этот repo, WebRTC stack и H100 stack.
- Любое утверждение о production требует проверки всей цепочки.
Навигация: ← → / PgUp PgDn / Space · Home End · F fullscreen · swipe