ASR / ПУТЬ ЗВУКАЛокальная техническая презентация · 28 октября 2026
Как читать схемы и сравнивать время

Почему batch выглядит медленнее? Здесь разделены сбор фразы, вычисление модели, доставка результата и ожидание предыдущего прогона. Нажмите на блок или стрелку — получите формат данных, границы таймера и ссылку на код. A и B запускаются последовательно. Числа в разных строках могут перекрываться; складывать их без проверки нельзя.

Streaming / batch — сравнить цифры выбранного примера
01 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Один звук, четыре пути к модели

Браузер записывает один PCM. Сначала A распознаёт поступающие окна, затем B повторно подаёт те же байты со скоростью 1× и ждёт готовых фраз. Три модели разделяют worker; LinTO использует свои WS и HTTP endpoints. Результаты остаются диагностикой и не запускают чат или инструменты.

Граница: ASR Compare → текст в браузере
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается01
02 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Почему batch кажется медленнее

Собственный таймер B стартует только после A. Малое время decoder не означает быстрый показ: B сначала собирает речь и тишину, затем вычисляет ответ. Общая шкала включает предшествующий A и показывает именно последовательность, которую наблюдает человек.

Собственный секундомер и общая кнопка запуска
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается02
03 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

До PCM: кто разрешает прогон

Страница получает ограниченный grant, резервирует существующий replay-слот и открывает аудиоклиент. Core закрепляет backend и processing_mode; браузер не может подменить их в PCM. Этот подготовительный интервал измерен целиком, а его отдельные командные RPC видны в экспорте.

HTTPS bootstrap и конечные NATS-команды
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается03
04 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Из микрофона получается PCM16

getUserMedia передаёт браузеру EC, NS и AGC. CaptureController соединяет дорожку с AudioWorklet; локальный energy VAD в Compare выключен. Worklet квантует float32 в 16 бит и передаёт блоки в основной поток. Реальная обработка микрофона зависит от браузера и фиксируется requested/actual.

Один захват, без Opus и без MediaRecorder
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается04
05 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Что именно летит из браузера

PCM не превращается в Base64 на браузерном пути. В начало пакета добавляются 8 байт sequence, затем идут little-endian отсчёты. NATS обрамляет этот payload своим протоколом и передаёт по WebSocket; flush подтверждает доставку брокеру, но не является таймером накопления фразы.

NATS поверх WSS: заголовок последовательности + сырые отсчёты
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается05
06 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Ingress: 48 кГц превращаются в 16 кГц

NatsAudio проверяет sequence и формат, затем подаёт PCM в один PcmFifo. PyAV сохраняет задержку ресемплера между блоками. Выход делится на 320 отсчётов, то есть 20 мс. Замер CPU охватывает feed/resample/enqueue; он не является временем в сети.

Проверка владельца, непрерывный resampler и FIFO
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается06
07 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Как NATS связывает два хоста

Ingress отправляет PCM локальному bridge. Для worker bridge публикует to.inference…, а H100 получает inference… через существующие account imports и leafnode. Обратные события получают префикс from.inference…. Эти отображения не перекодируют звук. Односторонний сетевой интервал здесь не измерен.

Subject mapping, account и leafnode — отдельные участники
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается07
08 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Streaming VAD отдаёт звук до конца фразы

Bridge один раз обрабатывает каждое 32-мс окно Silero. После подтверждения речи он выдаёт pre-roll и последующие окна worker, не ожидая всей фразы. Закрытие по тишине запускает final. Поэтому сбор готовой фразы и начало decoder в streaming перекрываются.

512 samples · 32 мс · подтверждение начала и тишины
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается08
09 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Worker распознаёт растущее окно

Worker принимает кадры и накапливает phrase.audio. Первое окно обычно не меньше 0,5 с, для Russian — 1 с. Scheduler выбирает live раньше replay; текущий native вызов не прерывается. Повторные вызовы могут обрабатывать перекрывающиеся samples, поэтому сумма decoder больше одного batch вызова.

Очередь live/replay, snapshot и один decoder lock
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается09
10 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Whisper Turbo: что входит в decoder

Модель получает float32 массив 16 кГц. transcribe возвращает ленивые segments, поэтому таймер охватывает и list(segments). Сборка текста и диагностических оценок следуют за вычислением. Фильтры avg_logprob, no_speech_prob и compression_ratio выключены; непустые слова не отбрасываются этими оценками.

CT2 / faster-whisper: transcribe + потребление generator
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается10
11 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Whisper Russian: тот же транспорт, иная первая порция

Russian идёт через тот же worker и те же PCM/RPC контракты. Для первого streaming вызова требуется 1 с контекста; speculative partial ограничен бюджетом токенов. Final и batch сохраняют обычные настройки декодирования. Это существующее поведение, в текущей задаче оно не изменено.

Первый partial ждёт больше акустического контекста
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается11
12 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

GigaAM: PCM превращается в tensor и RNNT-текст

GigaDecoder получает тот же float32 массив, проверяет форму и создаёт tensor на CUDA. Acoustic encoder и RNNT greedy decoder возвращают текст. Whisper-оценок у этого backend нет: отсутствие avg_logprob здесь объяснимо устройством модели и не означает нулевую уверенность.

Тот же worker, другой модельный адаптер
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается12
13 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Batch сначала собирает готовую фразу

CompareBatch раз в 1 секунду аудио повторно проверяет весь накопленный буфер. ready_ranges выпускает все найденные фразы лишь после 500 мс тишины за последней; более ранняя фраза может ждать завершения следующей. В двухфразовом примере первая фраза ждала 10,81–10,82 с. collection включает это ожидание, а vad_ms — только вычисления: складывать их нельзя.

Время речи + тишина + период проверки + вычисление VAD
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается13
14 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Worker batch: WAV переносится частями через RPC

Bridge оборачивает готовую фразу в WAV и передаёт begin, затем последовательные chunk, затем recognize. Base64 увеличивает размер частей примерно на треть. Worker проверяет размер, SHA и WAV, декодирует один раз и отвечает JSON. Отдельный cancel освобождает upload owner после ответа.

Base64 появляется здесь, не на входе браузера
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается14
15 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

WorkerSamples: ожидание и вычисление раздельно

Загруженный WAV ещё не означает начало распознавания. WorkerSamples ждёт освобождения live и inference_lock, проверяет и преобразует WAV, затем запускает decoder в thread. Чистое время берётся внутри этой thread; подготовка и RPC измеряются отдельно. Все интервалы сохраняют собственные границы.

Полная фраза → один native вызов
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается15
16 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

LinTO streaming: PCM идёт в WebSocket

После streaming VAD bridge открывает LinTOPhrase. Через CONNECT создаётся WebSocket /streaming: сначала JSON config, затем бинарный PCM16LE, в конце EOF. LinTO может многократно декодировать внутренние окна; его native total берётся из ответа. Первая передача в сокет не выдаётся за точное начало decoder.

Bridge закрывает фразу; LinTO владеет внутренними окнами
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается16
17 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

LinTO batch: один WAV по HTTP

Для целой фразы используется отдельный HTTP endpoint LinTO. Bridge сначала получает существующий файловый lock, затем через CONNECT отправляет multipart WAV и ждёт JSON. HTTP interval включает upload, backend и ответ. Внутренняя подготовка LinTO не измерена отдельно и не заменяется разностью случайных часов.

FileJobLock → multipart → native → release
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается17
18 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

CONNECT — туннель байтов, отдельный от ASR RPC

aiohttp_socks открывает HTTP CONNECT к существующему requester. Внутри туннеля проходят WebSocket либо multipart HTTP к LinTO. NATS subjects соединяют requester и receiver через inference account. Исходники текущего dtorry/nats-proxy недоступны в исследованных checkout: внутренний frame layout и timing отдельных hops остаются неизвестными.

Публичный браузерный WSS и внутренний proxy не смешиваются
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается18
19 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Как результат попадает на экран

Bridge отправляет события Core, который сохраняет ограниченный diagnostic buffer и добавляет replay_sequence. Ingress передаёт их только владельцу events.audio. Страница удаляет дубли и обновляет DOM не чаще 10Гц. После END одна сверка восстанавливает пропущенное; heartbeat не является механизмом накопления текста.

Push, один владелец и одна сверка после END
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается19
20 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Конец речи, final и конец прогона — три момента

Стоп сначала досылает хвост worklet и flush. Ingress завершает resampler и добавляет служебную paced silence минимум 1 с, чтобы VAD успел закрыть фразу. Затем подтверждает idle, заканчивает transport и освобождает replay-слот. Это время не относится к native decoder; final часто приходит раньше release.

Почему после PCM остаётся примерно секунда и более
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается20
21 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Замеры на одном исходном PCM

Числа ниже — экспорт реального браузерного прогона, а не оценка по длительности файла. Каждый метод получает тот же исходный PCM; сервер дополнительно сверяет 16 кГц hash. Native — сумма вызовов; RPC, сбор и общий результат имеют другие границы и не складываются как независимые этапы.

Выберите прогон: цифры на блоках и стрелках меняются
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается21
22 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Как рассчитывается каждый интервал

performance.now используется только внутри браузера; time.monotonic — внутри соответствующего сервиса. Разность часов разных машин не применяется. Неполученный показатель остаётся неизвестным. Ошибка «вычесть decode из всего и назвать остаток сетью» исключена: в остатке есть ожидание речи, VAD, RPC и cleanup.

Локальные часы, аудиошкала и вложенные интервалы
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается22
23 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Где ограничивается память и заканчивается владение

Compare хранит максимум 30 с звука и ограниченный журнал. Новая телеметрия хранит только 1600 пар координат и времени; PCM не копируется. Скрытие страницы отменяет прогон. Native вызов завершается своим путём; нельзя освободить слот и одновременно оставить за ним незавершённую модель.

Наблюдения не должны добавлять безграничную очередь
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается23
24 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Куда идти в коде за конкретным этапом

Frontend владеет захватом, повтором и отрисовкой. Chat ingress владеет транспортом и resampler; Core — допуском и принадлежностью результата. ASR bridge выбирает VAD и путь модели. Worker владеет планированием и native decode; LinTO и proxy имеют собственные границы наблюдаемости.

Одна карта модулей вместо скрытых абстракций
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается24
25 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

От кнопки до побочного эффекта

Ветка A открывает захват или повторяет PCM, B всегда повторяет готовый sample. Развилка processing_mode происходит в bridge после общего ingress. У модели меняется способ подачи аудио, а не критерии принятия результата. Тестовая страница не записывает новое сообщение чата.

Выборочное дерево вызовов для A и B
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается25
26 / 26 · СХЕМА ВЗАИМОДЕЙСТВИЙ

Что подтверждено, а где граница замера

Все утверждения о маршрутах опираются на приведённые исходники; фактические цифры — на приложенные экспорты тестов. Отдельные сетевые hops и внутренняя подготовка LinTO не измерены, поэтому на схеме так и подписано. Прогон синтетического PCM проверяет полный транспорт, но не физический микрофон и не универсальный WER.

Source, CI, runtime и браузер — разные доказательства
━━ Вызов / передача┄┄ Событие / поток··· Владение / зависимость? Нет отдельной точки замера
VERIFIED / SOURCE · цифры: выбранный реальный прогон · время разных часов не вычитается26
← → / PgUp PgDn · Home End · перетаскивание фона · +/− для масштаба
Автономный HTML: данные, графы и JavaScript встроены. Презентация ничего не отправляет и не запускает диагностику. Ссылки на исходники открываются только по нажатию. UNKNOWN не заменяется предположением или нулём.

Служебные вложения доступны в исходном архиве.