Голосовые системы

Monitor 1.8.1: поставка и проверка

Состояние на 27.10.2026, 00:36 МСК: функционал поставлен, 30-минутный прогон и заключительная приёмка новой фразы активной записи прошли. Все три тестовых микрофона выключены, три записи подтверждены полными. Отдельный FAIL остаётся у внешнего пути LinTO (linto_stream_error); остальные проверенные backend работают.

Что изменено

  • Живой режим включён по умолчанию, включая старые ссылки. Пауза фиксирует снимок и сохраняется как live=0. Короткие уведомления после commit передают только ID через существующую подписку Monitor. Обновления объединяются за 250 мс; одновременно выполняется одна сверка и хранится один флаг необходимости повторить её. Независимые видимые ресурсы внутри сверки читаются параллельно; очередь уведомлений не накапливается.
  • Списки обновляются на месте. Фильтры, раскрытые секции, положение чтения и плеер сохраняются. Скрытая вкладка снимает подписки; возврат и восстановление связи вызывают одну сверку. Графики и результаты ограничены по объёму; свёрнутые графики не рисуются.
  • Полный UUID сессии переносится в левой колонке. Вернулись User-Agent, начало, последняя активность, число событий и индикатор подключения. Ширина колонок меняется мышью и клавиатурой, сохраняется локально, сбрасывается двойным нажатием. На узком экране колонки располагаются последовательно.
  • Удалены полосы локальной навигации и дублирующие блоки событий сообщения / вызовов модели внутри повтора. Технические данные доступны в существующем выполнении, журнале и JSON. Секции получили одинаковые рамки, полосы заголовков и отступы в обеих темах.
  • Завершение архива повторяется ограниченно и идемпотентно; ошибка не проглатывается. Фоновая сверка проверяет финальный манифест, завершение владельца, последовательности, размеры, координаты и хеши всех блоков. Только подтверждённый recording_owner_lost исправляется автоматически; прочие ошибки сохраняются.
  • Доступность фразы и её настроек отделена от завершения всего потока. Проверяются выбранные блоки и контекст; недописанный правый контекст требует ожидания. Полный replay разрешён для завершённой проверенной записи.
  • Захват сохраняет полный requested/actual. Неуказанное requested обозначено «По умолчанию браузера», неизвестное actual — «Браузер не сообщил». Включение/выключение показано как состояние захвата.
  • Loader показывает этап, объём и процент, поддерживает отмену, ошибку и повтор. Waveform рисуется независимо от PCM. Совместимый параметр batch_bytes ограничен 128 КиБ; каждый исходный блок проверяется. Длинная запись начинает с 4 секунд, затем читается порциями. Запоздалые ответы игнорируются, Blob URL освобождаются.
  • input_list выполняет один сбор на вызов; повторная доставка использует сохранённый результат. Повторная сериализация убрана, DOM-ссылки коллектора освобождаются, служебные карты ограничены без удаления сохранённой истории.

Новых сервисов, таблиц, постоянных счётчиков, соединений NATS и AudioContext не добавлено. Инфраструктура, DNS, SSH и PostgreSQL не перенастраивались.

Проверки

Проверка Результат / доказательство
Python PASS: 247 тестов, 13 subtests; 99 интеграционных сценариев пропущены в unit-job, необходимые интеграционные тесты проверены отдельным job
Frontend PASS: 60 файлов, 429 тестов, TypeScript, build и runtime
Пять обязательных CI checks PASS на 13efe271 — pipeline 5410
Архив с PostgreSQL и NATS PASS: поздний манифест, повторное завершение, потерянный finalize, owner_lost, повреждённые блоки, активная фраза и ожидание правого контекста; job 23869, 80 интеграционных тестов, включая 13 storage-тестов
Реальные текстовые запросы при 0 / 1 / 3 потоках PASS: c0ed749e…, 1d0a4b51…, f65352aa… появились без ручного обновления и остановки микрофона. На финальном Gateway повторено: afeec8f7… при трёх потоках
Контексты вкладок PASS: A вернула 2 поля, B — 3 поля; общая история содержит источник страницы
Три одновременных подключения PASS: единый серверный снимок содержит два stream_id с одной session_id и третий с другой session_id
Историческая запись пользователя PASS: 5d531bae… стала полной после проверки; фраза 1839876f… доступна в диапазоне 118.520–120.448 с, настройки показаны
Пауза / возврат в live PASS: запрос ee1bfc93… отсутствовал в фиксированном снимке и появился после возобновления
Завершение одного потока при продолжающихся соседних PASS на финальном Gateway: 301a1a1e… завершён, 283,709 с, запись «Полная»; 69353e7e… продолжает принимать и сохранять PCM. production-finalize-isolation.txt
Живой экран PASS: уровни, waveform, счётчики каналов и длина архива обновляются при работающем микрофоне
90 мс, 1 с, 3 с, повтор и границы порций PASS в реальном Chrome: шесть сценариев; после остановки за 1,8 с — 0 timeupdate и 0 записей currentTime
Loader, отмена, повтор PASS в production; запоздалые ответы и смена источника также проверены тестами
Навигация и компоновка PASS: старые ссылки, Back/Forward, очистка выбора при смене сессии; resize 340→350 px клавиатурой, 340→444 px мышью, сброс до 340; обе темы при viewport 390 px без горизонтального переполнения
30-минутный прогон PASS: 1800 с, 60 циклов открытия аудио, 2569 обновлений; после закрытия 0 подписок, таймеров, RAF и Blob URL
Физическая речь и повтор активной фразы PASS на финальном Gateway: новая фраза fd3b76d6… появилась без ручного обновления. Аудио 1787,416–1789,760 с и настройки доступны при статусе «Идёт запись». Replay с контекстом 5,344 с завершён за 10,01 с при трёх живых подключениях; слот освобождён. production-new-active-voice-replay.json и .txt
Завершение трёх длинных записей PASS: 69353e7e… — 1943,237 с; a23be5d5… — 1576,596 с; d43e6424… — 1861,462 с. Все три — «Полная»; активных подключений 0, кнопки микрофонов выключены

Модели: отдельно от интерфейса

При трёх подключённых микрофонах replay одной и той же фразы с контекстом 4,928 с завершился:

Backend Итог Время всего Что измерялось
Whisper Turbo PASS 11,87 с Подготовка 0,88 с; предзагрузка/подключение 4,58 с; PCM 4,93 с; завершение 1,30 с
Whisper Russian PASS 11,69 с Подготовка 0,87 с; предзагрузка/подключение 4,37 с; PCM 4,93 с; завершение 1,32 с
GigaAM v3 RNNT PASS 12,21 с Подробные фактические этапы и очередь модели сохранены в production-backends.json
LinTO FAIL внешнего пути 11,73 с linto_stream_error; UI показал причину, соединение закрыто, слот освобождён

После окончательного Gateway 13efe271 повтор Whisper Turbo при трёх живых потоках прошёл за 11,14 с: подготовка 0,94 с, предзагрузка/подключение 3,78 с, PCM 4,93 с, завершение ASR 1,30 с; закрытие соединения и освобождение слота подтверждены журналом.

Заключительный повтор новой фразы из ещё записываемого потока прошёл за 10,01 с: подготовка 0,85 с, предзагрузка/подключение 2,32 с, PCM 5,35 с, завершение ASR 1,31 с. Живое распознавание выдало «Ответь одним словом. Проверка.», повтор — «Отвечу одним словом. Проверка.». Эта разница распознавания сохранена в доказательствах; совпадение текста не заявляется. Очередь модели в журнале — 0,1 мс, отдельные вызовы Decoder — 148,4–157,5 мс. Три stream_id со статусом receiving подтверждены одним серверным снимком во время проверки.

Это единичные функциональные прогоны, а не статистика медианы/p95 модели. Ускорение загрузки Monitor не приписывается нейросетям. Отмена полного replay 182,101 с проверена: «Повтор отменён», слот освобождён.

Поставка

Исходная база: f89d8bdc0f26327dcd412c087ce350d26abdcf47.

Основной функционал первоначально поставлен как 61da43c6ca858d11155809311430434c13839253. Финальный main: 13efe271e90c3f26dc1ca1423930f4c140ab3a2f; он включает исправления завершения архива, раннего манифеста и привязок исходных строк. Все пять checks этого SHA прошли. Окончательная адресная поставка Gateway и Front завершена; Audio WS Ingress остаётся на 61da43c6.

Поставлены только API Gateway, Audio WS Ingress и Front. Задействован src_shared.monitor: его новый необязательный параметр потребляет Gateway. Core и Agent импортируют соседние общие типы, но не исполняют команду monitor и не используют изменённое поле. Проверка поставки подтвердила фактический Image ID, revision, digest, healthy / 1 replica / completed и неизменность соседних service specs/tasks. Приём аудио снова открыт.

Сервис Версия пакета / OCI build Revision SHA256 образа
API Gateway 6.10 / 1.0.0.1004 13efe271 b26fee7ee18a7921f34b1fbf35702e64b27e78ea5ad65ef372648bb15ffcaf66
Audio WS Ingress 3.6 / 1.0.0.1000 61da43c6 bb27c27c93ed16b740c062b112ba356f75187e0a5e635a5db823d67a34e967d8
Front 5.13 / 1.0.0.1004 13efe271 1e9409fcff5c7efa7017c371894cf63a71eb3b04aa005cf1a33ffe7d30f94b2a

Финальные Gateway rollout и Front rollout — PASS на SHA 13efe271, pipeline 5410. Preflight 23892, сборки Gateway 23882 / Front 23887 и пять обязательных checks прошли. Последовательная поставка проверила точный образ, рабочую task и неизменность соседних сервисов.

Первоначальные Backend rollout и Frontend rollout — PASS. Build/release pipeline: 5406. У него все пять обязательных checks и адресная поставка PASS; общий статус содержит отказ необязательной загрузки ZIP-артефакта из-за DNS runner. Это отдельно от успешной серверной поставки.

Расширение 1.8.1 установлено в прежний локальный источник; ID, permissions, host_permissions и CSP сохранены. Пользователь подтвердил reload. ZIP опубликован и скачан обратно для проверки SHA-256: [пакет 1.8.1](<https://git.giscloud.ru/voice-chat/webrtc-komaroff/-/packages/1>). Размер 841990 байт, SHA-256376c47b2bd63c0b0be5005f45c270ca9a02852cad5a3b3e9de54a34e305e6a92`. DNS runner не менялся.

Итог diff от согласованной базы: 36 файлов, +763 / −210 строк, включая тесты и документацию. Работа выполнена одним writer в изолированном checkout; основная копия не редактировалась.

Измерения

Контролируемый Chrome-стенд использовал реальные компоненты Monitor, три потока, 10 событий графика/с, обновления запросов примерно каждые 700 мс и задержку RPC 20 мс. В исходном коде автоматические обновления запросов отсутствовали: задержка «до» и процент её уменьшения не определены. После изменений медиана — 306 мс, p95 — 315,7 мс, отображено 2569 обновлений.

Метрика Было → стало Абсолютная разница Изменение
Готовность начального аудио, медиана стенда 3100,7 → 165,1 мс −2935,6 мс −94,68%
Готовность начального аудио, p95 стенда 3141,5 → 198,5 мс −2943,0 мс −93,68%
RPC начальной загрузки с метаданными, стенд 129 → 5 −124 −96,12%
Начальные запросы Monitor без живых потоков 4 → 4 0 0%
Начальный буфер PCM 3 072 000 → 384 000 байт −2 688 000 байт −87,5%
Получение PCM исторической записи, production 16 115,6 → 2541,7 мс −13 573,9 мс −84,23%
RPC PCM исторической записи, production 137 → 4 −133 −97,08%
Сбор 100 полей, медиана 4,2 → 3,4 мс −0,8 мс −19,05%
Сбор 100 полей, p95 6,8 → 4,7 мс −2,1 мс −30,88%
DOM-ссылки после закрытия коллектора 100 → 0 −100 −100%

Открытие Monitor без живых потоков требует тех же четырёх чтений: сессии, записи, потоки и запросы. Дополнительных выборок для удалённых дублирующих секций нет. Снимок с тремя живыми потоками содержал пятое чтение сессий от отдельного уведомления; он не используется для сравнения начальной загрузки.

Загрузка сравнивает прежний начальный участок 32 с с новым 4 с: это время до готовности плеера, а не ускорение передачи одинакового объёма. Production — единичный наблюдаемый запуск, не медиана/p95. В изолированном сборе полей выполнено 100 вызовов, ровно 100 сборов в каждой версии; повторная доставка инструмента проверена отдельно.

Прогон выполнялся на frontend 61da43c6; последующая правка Front меняет только два номера строк в ссылках на исходники и не затрагивает проверенные обработчики, графики или плеер.

За последние 15 минут нагрузки: 1 подписка, 2–3 таймера, 1 RAF, 1 Blob URL, 8995–9000 точек истории, 128 результатов, ровно 1193 DOM-узла. JS heap менялся от 10,07 до 17,31 МБ; после очистки — 10,63 МБ. Снимки heap сами по себе не доказывают отсутствие всех возможных утечек; измеренные коллекции ограничены и ресурсы освобождаются. Дополнительный production-замер 4 мин 37 с: heap 9,55 → 5,54 МБ, обработчики 85 → 79, DOM-узлы CDP 775 → 645.

Плеер после остановки: прежнее наблюдение пользователя — около 960 событий за 1,8 с; исправленный плеер — 0 событий и 0 присваиваний currentTime за тот же интервал во всех шести сценариях.

Исходные данные: metrics-final.json, soak-final.json, fields.json, production-audio-before.json, production-audio-after.json, player-chrome.json.

Ошибки, обнаруженные при заключительной приёмке

  1. Полная проверка архива выполнялась в двухсекундном RPC под общей блокировкой записи. На синтетическом архиве 86,4 МБ / 15 мин воспроизведены тайм-аут завершения и тайм-аут соседнего append. В production при завершении длинных записей соседний архив получил recording_unavailable, хотя живое аудио продолжалось. После исправления end marker сохраняется за 3,84 мс, проверка проходит отдельно; 30 соседних append успешны (медиана 4,70 мс, p95 5,51 мс). Проверка 172,8 МБ / 30 мин прошла за 14,87 с, finalize — 3,93 мс; 30 соседних append успешны, p95 4,88 мс. Для фоновой проверки действует отдельный лимит 60 с и курсор на 32 блока, foreground RPC сохраняет лимит 2 с. Ошибочные тестовые записи не были выданы за полные.
  2. При доставке манифеста раньше PCM он оставался в ожидающих событиях до finalize. Реальная фраза активного потока получила audio_archive_manifest_missing. Теперь один SQL-запрос атомарно переносит ожидающий манифест в вставляемый блок. Число запросов записи не увеличено; оба порядка доставки проверены с PostgreSQL. Новых фоновых задач и очередей нет.

В production финальный Gateway читает PCM продолжающейся записи 69353e7e…: статус «Идёт запись», 297,792 с сохранено, в памяти только 0–4 с, загрузка успешна до finalize. Исторические записи 88a3b999… (705,572 с) и b7c5d8d8… (713,957 с) подтверждены полными.

Регрессии сначала воспроизвели оба отказа, затем прошли на исправленном коде; полный адресный набор — 43 теста и 4 subtests PASS. Доказательства: archive-finalize-regression-before.log, archive-finalize-regression-after.log, archive-parallel-benchmark.json, archive-30-minute-after.json, manifest-before-pcm-before.log, manifest-before-pcm-after.log.

Заключительная проверка в Chrome

27.10.2026 в 00:32:40 новая физическая фраза создала запрос fd3b76d6-fef5-5f4c-9e20-7bfc9f98c537 в общей сессии d46de968-2756-4000-97b7-d0d11fbc7d70. В другой сессии появился отдельный голосовой запрос a10dbc30-3c51-50a5-beb9-bb6df709ec35. Monitor показал изменения без нажатия «Обновить»; точная задержка этого production-события не измерялась.

Для первой фразы до остановки микрофона были доступны PCM16 / 48000 Hz / mono, 2,344 с, и снимок настроек: NS и EC requested/actual включены; AGC requested — «По умолчанию браузера», actual — включён. Диапазон replay 1785,416–1790,760 с успешно проверен и обработан. В момент проверки одновременно работали 69353e7e…, a23be5d5… и d43e6424…. После replay число запросов общей сессии осталось 31, число её потоков — 12; диагностический прогон не появился как новое сообщение или исходная запись.

После последовательного выключения микрофонов все три записи прошли проверку и получили статус «Полная». Завершение первой записи не отключило соседний поток. Итоговые состояния сохранены в production-final-shared-archives.txt, production-final-other-archive.txt, production-final-acceptance.json. Снимок результата активной фразы: production-new-active-voice-replay.png.

Исходник

Скачать Markdown · К материалам исследования