Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

От RTSP-камеры до истории событий: настраиваем видеоаналитику через JavaScript Viewer

Дата публикации: 06-10-2026 09:01:57

Привет, Хабр! В первой статье я разбирал внутреннее устройство real-time-конвейера на C++20: почему медленный YOLO не должен останавливать RTSP и зачем между этапами нужны ограниченные слоты последнего значения. Теперь посмотрим на ту же систему с другой стороны — глазами пользователя, который подключает камеру и должен получить не просто видео с рамками, а управляемый и проверяемый результат.Я покажу практический порядок настройки своей платформы видеоаналитики через браузерный JavaScript Viewer: от стабильного потока и детектора движения до постоянных ID, двух контуров YOLO и истории событий в PostgreSQL. Главный вопрос статьи — не «где находится кнопка», а «какой участок конвейера меняет этот параметр и как проверить эффект». Читать далее

Основное содержимое страницы с новостью.

Уровень сложностиСредний

Время на прочтение9 мин

Охват и читатели4.3K

Кейс

Привет, Хабр! В первой статье я разбирал внутреннее устройство real-time-конвейера на C++20: почему медленный YOLO не должен останавливать RTSP и зачем между этапами нужны ограниченные слоты последнего значения. Теперь посмотрим на ту же систему с другой стороны — глазами пользователя, который подключает камеру и должен получить не просто видео с рамками, а управляемый и проверяемый результат.

Я покажу практический порядок настройки своей платформы видеоаналитики через браузерный JavaScript Viewer: от стабильного потока и детектора движения до постоянных ID, двух контуров YOLO и истории событий в PostgreSQL. Главный вопрос статьи — не «где находится кнопка», а «какой участок конвейера меняет этот параметр и как проверить эффект».

Общий вид JavaScript Viewer

Viewer с подключённым Clang Server: сверху — видеопоток, слева — подсистемы, снизу — телеметрия, справа — параметры выбранного этапа.

Что находится в браузере, а что — на сервере

Первое важное разделение: Viewer не выполняет видеоаналитику. Браузер показывает JPEG или HLS, редактирует конфигурацию, отправляет REST-команды и отображает историю. Захват RTSP, Motion, Tracking, ONNX Runtime, FFmpeg и PostgreSQL остаются на стороне VideoAnalyticsServer.

Браузерный Viewer
  интерфейс + Canvas + hls.js + REST-клиент
                  |
                  v
Node.js reverse proxy
  разрешённые REST- и HLS-маршруты
                  |
                  v
VideoAnalyticsServer
  RTSP -> Motion -> Tracking -> YOLO -> HLS/история

Такое разделение позволяет использовать один Viewer с несколькими реализациями сервера. Сейчас общий REST-контракт поддерживают версии на C++/Clang, Python и Rust. Пользовательский сценарий остаётся прежним, хотя внутренняя модель параллельности у серверов различается.

Сам Viewer написан без frontend-фреймворка и сборщика: ES Modules, fetch, async/await, AbortController, Canvas, Pointer Events и hls.js. Node.js раздаёт статику и работает как узкий reverse proxy. CPU-тяжёлой аналитики в браузере нет, поэтому Web Worker для текущей версии не требуется.

Шаг 1. Сначала добиваемся стабильного видео

Настраивать нейросеть при нестабильном источнике бесполезно. Сначала я выбираю камеру, запускаю поток и несколько минут наблюдаю за нижней строкой Viewer.

В ней отображаются:

  • Server FPS — скорость обработки на сервере;

  • Viewer FPS — сколько кадров фактически показано в браузере;

  • Потери — пропуски на клиентском контуре;

  • Очередь — накопившиеся кадры показа;

  • RTSP-перезапуски — число переподключений к камере;

  • разрешение и битрейт источника.

Если Viewer FPS меньше Server FPS, это ещё не доказывает проблему аналитики: причиной могут быть вкладка в фоне, декодирование HLS или сеть. А рост счётчика RTSP-перезапусков уже указывает на источник, соединение или декодер.

Viewer поддерживает два режима показа.

Режим

Когда удобен

Особенность

JPEG polling

Настройка, диагностика, отдельные кадры

Просто отменять устаревшие запросы через AbortController

HLS

Продолжительный просмотр

Плавнее воспроизведение, но появляется буфер и небольшая задержка

Для HLS можно выбрать исходную высоту, 1280p, 720p или 480p и частоту 15/30 FPS. Это параметры выходного видео, а не разрешение входа YOLO. Смешивать их при диагностике не следует.

Запись MP4 также не является записью HLS. Server берёт исходные кадры уже открытого RTSP-сеанса до наложения аналитики и передаёт их отдельному FFmpeg. Второе подключение к камере не создаётся.

Шаг 2. Motion превращает изменение пикселей в кандидатов

Motion — самый дешёвый аналитический этап. Его задача не назвать объект, а найти области изображения, где произошло достаточно заметное изменение.

Настройка Motion

Параметры детектора движения. Они влияют на число и форму кандидатов, которые затем получает Tracking.

Основные параметры имеют физический смысл:

Параметр

Если уменьшить

Если увеличить

Минимальная область

Видны мелкие объекты, но растёт шум

Мелкие события отбрасываются

Изменение яркости

Выше чувствительность

Меньше реакции на шум и освещение

Ядро склейки по горизонтали

Фрагменты чаще остаются раздельными

Близкие части соединяются

Ядро склейки по вертикали

Сохраняется больше мелких контуров

Вертикальные фрагменты объединяются

Я начинаю с достаточно строгого порога яркости и небольшой морфологической склейки. Затем смотрю не на один красивый кадр, а на поведение в разное время: солнце, тень, фары, дождь и движение листвы. Если один автомобиль распадается на несколько жёлтых прямоугольников, сначала корректирую ядро склейки, а не повышаю чувствительность всей сцены.

Motion не должен подтверждать семантику. Его ложный кандидат относительно дешёв, пока он не превращается в лишний трек и не запускает дополнительные проходы YOLO.

Шаг 3. Tracking стабилизирует цель во времени

Один прямоугольник Motion живёт один кадр. Tracking связывает обнаружения между кадрами, присваивает постоянный ID и некоторое время прогнозирует положение объекта, если Motion временно его потерял.

Настройка Tracking

racking отвечает не за распознавание класса, а за устойчивость цели во времени.

Здесь параметры уже связаны между собой:

  • Максимальное расстояние ограничивает допустимое перемещение центра между обновлениями. Слишком маленькое значение рвёт быстрые треки, слишком большое может склеить соседние цели.

  • Допустимые пропуски задают, сколько обновлений трек живёт без нового обнаружения. Большое значение помогает при кратком перекрытии, но дольше сохраняет исчезнувшие объекты.

  • Подтверждений определяют, сколько совпадений нужно до публикации нового ID. Это хороший фильтр кратковременного шума.

  • Сглаживание уменьшает дрожание рамки ценой запаздывания.

  • Зазор склейки объединяет близкие фрагменты Motion до передачи трекеру.

Практический порядок такой: сначала добиться, чтобы реальная цель получала один ID, затем уменьшить ложные треки с помощью подтверждений и только после этого настраивать сглаживание. Иначе красивая плавная рамка может скрыть неправильное сопоставление объектов.

Шаг 4. Области анализа экономят вычисления

Панорамная камера содержит много участков, которые не представляют интереса: небо, стены, крыши. Анализировать их с тем же разрешением, что вход или парковку, дорого и бессмысленно.

Редактор областей Tracking

Жёлтые области ограничивают Motion и Tracking. Координаты хранятся нормированно и не привязаны к одному разрешению кадра.

В Viewer область рисуется на стоп-кадре. Пользователь протягивает прямоугольник, уточняет четыре вершины и задаёт имя. На экране координаты показываются в пикселях, но на Server уходят в диапазоне от 0 до 1.

Это небольшое решение оказалось важным. Камера может переключиться с 2304×1296 на 1280×720, HLS — на 720p, а область «Парковка» должна сохранить геометрический смысл. Нормализованные координаты позволяют пересчитать её под текущий кадр.

У Motion/Tracking и YOLO разные наборы областей:

Жёлтые области -> где искать движение и сопровождать цели
Синие области  -> где выполнять полнокадровый YOLO

Они не обязаны совпадать. Например, Tracking может охватывать всю дорогу, а тяжёлый YOLO — только въезд и парковку.

Шаг 5. Два контура YOLO решают разные задачи

В системе работают две независимые ONNX Runtime Session.

Первый контур получает полный кадр или выбранные синие области. Он дорогой, особенно при входе 2304 px, зато способен найти объект без предварительного движения.

Второй контур получает вырезки активных целей Tracking и приводит их к 256×256. Он уточняет класс уже найденного движущегося объекта и выполняется заметно быстрее.

Полный кадр / области -> Full YOLO 320...2304
Motion -> Tracking ID -> ROI + запас -> Tracking YOLO 256

Это не два режима одного последовательного вызова. Они могут работать параллельно, имеют отдельные задания и конкурируют за CPU. Поэтому увеличение разрешения Full YOLO способно повлиять на задержки Tracking YOLO, даже если его собственный вход остаётся 256×256.

Настройка YOLO

Общие параметры двух контуров YOLO и разрешённые классы объектов.

Порог уверенности

Обычный порог применяется к разрешённым классам, а для person предусмотрен отдельный. В наблюдении человек часто занимает меньше пикселей, чем автомобиль, поэтому единый порог для всех классов неудобен.

Снижение порога повышает полноту, но увеличивает количество ложных событий. Менять его лучше после того, как стабилизированы области, Motion и Tracking. Иначе невозможно понять, что именно породило лишнюю запись.

NMS

Non-Maximum Suppression убирает перекрывающиеся рамки одного класса. Здесь направление настройки иногда понимают наоборот:

  • низкий порог NMS агрессивнее подавляет пересекающиеся рамки;

  • высокий оставляет больше перекрывающихся результатов.

Если одна машина получает несколько близких рамок, сначала проверяю NMS и порог уверенности, а не усложняю Tracking.

Запас ROI Tracking

Трекер может дать рамку немного меньше реального объекта. Запас расширяет вырезку перед масштабированием в 256×256. Слишком маленький запас обрезает объект, слишком большой добавляет фон и соседние цели.

Задержка завершения события

YOLO не обязан видеть объект на каждом проходе. Задержка определяет, сколько секунд отсутствия допускается до завершения события. Она не ускоряет inference, а управляет жизненным циклом записи в истории.

Шаг 6. Проверяем не настройку, а фактический вход модели

Пользователь может включить маскирование пространства вне областей. В таком случае Server заменяет исключённые пиксели нейтральным серым RGB (114, 114, 114) до формирования тензора.

Чтобы не гадать, Viewer умеет запросить разовый снимок фактического входа Full YOLO.

Фактический вход YOLO

Предпросмотр показывает изображение после применения областей и маски, то есть именно то, что получает подготовительный этап нейросети.

Этот экран полезнее обычного видеокадра при поиске ошибок конфигурации. Он сразу отвечает на вопросы:

  • действительно ли включена маска;

  • не закрыли ли областью нужный объект;

  • какое разрешение используется;

  • не перепутаны ли области Tracking и YOLO.

Снимок создаётся только по запросу и не запускает дополнительный непрерывный поток.

Шаг 7. История — это проверяемый результат

Цветные рамки на видео удобны для демонстрации, но систему приходится оценивать по событиям: где, когда и как долго находился объект, какой класс получил и какое изображение сохранилось.

История YOLO

История событий с серверной фильтрацией и сортировкой. Синяя рамка отмечает распознанный объект.

Viewer не подключается к PostgreSQL напрямую. Он формирует REST-запрос с областью, датой, часовым интервалом, полем сортировки и смещением часового пояса. Server валидирует параметры, выполняет параметризованный SQL и возвращает уже отсортированные строки.

Viewer
  region + date + time + timezoneOffset + sort + order
                         |
                         v
VideoAnalyticsServer
  проверка параметров -> PostgreSQL -> JSON
                         |
                         v
Viewer
  таблица + длительность + миниатюра

Для Tracking сохраняется первое фото подтверждённого трека. В истории YOLO хранится класс и снимок распознанного объекта. Фильтры двух экранов одинаковы, поэтому удобно сравнивать: было ли движение, появился ли устойчивый ID и дошёл ли кандидат до распознавания.

Если событий нет, я проверяю цепочку слева направо:

  1. активен ли RTSP;

  2. видит ли Motion область изменения;

  3. подтверждается ли Tracking ID;

  4. разрешён ли класс YOLO;

  5. попадает ли объект в нужную область;

  6. совпадают ли дата, час и часовой пояс фильтра истории.

Такой порядок быстрее случайного изменения всех порогов одновременно.

Роли и границы доверия

Viewer различает роли администратора и наблюдателя. Наблюдатель видит поток, конфигурацию, области и историю, но не может менять серверное состояние. Недоступность кнопки — только удобство интерфейса; окончательное решение всегда принимает Server и возвращает HTTP 403 при недостаточных правах.

Пароль и Bearer-токен хранятся в sessionStorage текущей вкладки и удаляются после её закрытия. Node-прокси не принимает произвольный адрес назначения от браузера: REST направляется только на настроенный Server, HLS ограничен плейлистом и сегментами.

Viewer также не знает строку подключения PostgreSQL, пароли камер и пути файлов сервера. Граница выглядит так:

Браузеру доверяем ввод и отображение.
Proxy доверяем только разрешённые маршруты.
Server доверяем проверку роли и данных.
PostgreSQL доверяем хранение и выборку истории.
Диагностика по симптомам

Несколько симптомов позволяют быстро найти нужный слой:

Симптом

С чего начать

502 Bad Gateway

Доступность Server и маршрут reverse proxy

HTTP 403

Роль текущей Bearer-сессии

HTTP 409 при включении YOLO

Наличие совместимой ONNX-модели

Видео остановилось

RTSP-статус, перезапуски, журнал Viewer

HLS не появился сразу

Подождать формирования нового плейлиста после изменения профиля

История пуста

Детекторы, области, дата, час и кнопка применения фильтра

Много ложного Motion

Порог яркости, минимальная площадь и ядро склейки

Дубли YOLO

Уверенность, NMS и список разрешённых классов

Журнал Viewer относится только к текущей вкладке: подключения, загрузка конфигурации, ошибки авторизации и тайм-ауты. Для падения процесса, FFmpeg или PostgreSQL нужен отдельный серверный журнал.

Порядок настройки, который оказался воспроизводимым

В итоге я использую такую последовательность:

Стабильный RTSP и понятная телеметрия
Области Motion/Tracking
Motion без лишнего шума
Устойчивые Tracking ID
Области и разрешение Full YOLO
Tracking YOLO 256 и запас ROI
Уверенность, NMS и задержка события
Проверка фактического входа YOLO
Сопоставление Tracking History и YOLO History
Только после этого — длительный тест

Главное правило — менять один слой за раз. Если одновременно снизить порог Motion, увеличить допустимые пропуски Tracking и ослабить confidence YOLO, итоговая таблица станет богаче, но причина каждого события останется непонятной.

Итог

Пользовательский интерфейс системы видеоаналитики — это не просто панель с параметрами. Он должен помогать проследить путь решения:

кадр -> изменение -> устойчивый ID -> класс объекта -> событие в истории

Именно поэтому в Viewer рядом существуют телеметрия потока, редакторы областей, предпросмотр входа YOLO и две истории. Каждый экран проверяет определённую границу конвейера.

В следующей статье перейдём от настройки к безопасной публикации системы. Покажу, как вывести Viewer в интернет через VPS и обратный SSH-туннель, не открывая домашние порты — и почему одной ошибки в proxy достаточно, чтобы публичный сайт превратился в дверь в домашнюю сеть. Разберём реальный риск SSRF, фиксированный upstream, авторизацию HLS, loopback на обоих концах туннеля, ограниченный SSH-ключ и аварийное отключение внешнего доступа.

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Как не утопить RTSP в YOLO: real‑time‑конвейер на C++20, Clang и ONNX Runtime08.5806-10-2026
2YOLO‑JSON: знание [на этапе компиляции] — сила012.3813-09-2026
3YOLO‑JSON: Рефлексия + #embed + JSON schema = сверхоптимизированный парсер06.920-09-2026
4EventBus и CommandBus во frontend: когда прямых вызовов становится слишком много011.7230-09-2026
5Терпение. Или как один зависший кадр заставил меня построить ещё полсистемы;‑)010.4123-09-2026
6[Перевод] Как я запустил Bad Apple с частотой 20 fps на E‑Ink дисплее за $71011.9227-09-2026
7Как я писал сервер и нечаянно пробил 1М RPS01031-08-2026
8Разработка CAN адаптера (часть 1)010.404-10-2026
9Продвинутый статический анализ в TypeScript-проектах: выходим за рамки tsc и ESLint014.7501-10-2026
10Мы измерили платный антидетект‑браузер: canvas совпадал с чистой машиной байт в байт. Потом сделали свой, открытый07.414-09-2026

Классификация: Мнения. Схожих патентов: 0. Схожих новостей: 10. Тональность: 0. Информативность: 8.16. Источник: habr.com.