
Всем привет, я Иван, продакт-менеджер. В этой статье разберу практический опыт построения системы видеоаналитики на базе open source-инструментов: от выбора библиотек и архитектуры до проблем с производительностью и масштабированием под десятки видеопотоков.
Материал будет полезен инженерам, тимлидам и продакт-менеджерам и всем тем, кто рассматривает open source как основу для production-ready CV-систем.
Почему мы решили не писать всё с нуля
Начнём с базового вопроса: почему вообще open source?
На практике в компьютерном зрении уже закрыты почти все фундаментальные задачи:
детекция объектов,
трекинг,
базовая обработка изображений,
инференс моделей.
Писать собственную реализацию этих вещей с нуля — дорого, долго и бессмысленно. Мы решили использовать open source как фундамент, а свою экспертизу вложить туда, где он заканчивается:
в архитектуру,
в масштабирование,
в устойчивую обработку видеопотоков,
в интеграцию с бизнес-системами.
Мы также рассматривали альтернативные подходы — закрытые коммерческие платформы и managed-сервисы. На практике они быстро упирались в ограничения: сложность кастомизации под конкретные сценарии, vendor lock-in и непрозрачную модель масштабирования по стоимости.
Базовый стек
На старте мы выбрали максимально «приземлённый» и проверенный набор инструментов:
YOLO (Ultralytics) — детекция объектов в кадре и видеопотоке
OpenCV — декодирование видео, пред- и постобработка изображений
PyTorch — обучение и инференс моделей
NumPy — работа с массивами на всех этапах пайплайна
Важно: open source закрывает именно алгоритмическую часть. Всё, что связано с жизненным циклом данных, отказоустойчивостью и масштабированием, пришлось проектировать отдельно.
Например, в качестве базовой модели детекции мы остановились на YOLO из-за хорошего баланса между точностью и задержками. Для наших сценариев latency была важнее максимального mAP: система должна реагировать почти в реальном времени, а не «догонять» события.
PyTorch выбрали из-за удобства дообучения и отладки. В процессе разработки модели часто менялись, и возможность быстро экспериментировать с архитектурой и параметрами оказалась важнее потенциального выигрыша в производительности, который могли бы дать более жёсткие фреймворки.
OpenCV использовали не только для декодирования, но и для ряда оптимизаций на этапе предобработки — это позволило снизить нагрузку на GPU в пиковые моменты.
Архитектура: почему всё разнесено по сервисам
С самого начала мы отказались от монолитного подхода. Причина простая: видеопотоки — это неравномерная нагрузка. Камеры могут «сыпаться», пропадать, возвращаться, давать пики.
В итоге архитектура выглядит так:
Frontend — веб-интерфейс для подключения камер, настройки зон и просмотра событий
Backend — API и хранилище событий
Detection-сервисы — обработка видеопотоков и детекция объектов
Recognize-сервисы — специализированное распознавание (номера, лица и т.д.)
Отдельное внимание пришлось уделить отказоустойчивости. В реальности камеры могут пропадать, отдавать битый поток или резко менять битрейт. Поэтому каждый Detection-сервис работает независимо и не блокирует остальные при сбоях.
Очередь сообщений используется не только для масштабирования, но и как буфер: если сервис распознавания временно недоступен, события не теряются, а обрабатываются позже. Для таких случаев мы используем retry-механику и отдельные очереди для проблемных сообщений.
Связь между компонентами идёт через API и очередь сообщений (RabbitMQ).
Kafka рассматривали, но в нашем масштабе она давала больше операционной работы, чем пользы: отдельная эксплуатация, настройки, наблюдаемость, плюс необходимость аккуратно держать latency, отказались.

Как работает пайплайн:
Камера отдает поток H.264 по RTSP.
Detection находит объекты и формирует кропы.
Backend сохраняет их и ставит задачу на распознавание.
Recognize возвращает результат.
Пользователь видит событие в интерфейсе или получает уведомление.
На практике самые затратные по времени этапы — это декодирование видеопотока и инференс модели. Именно они определяют верхнюю границу по количеству камер на сервер.
Мы сознательно разделили эти этапы и минимизировали синхронные операции, так мы сгладили пики нагрузки и избежали накопления задержек при росте числа потоков.
Зачем нужна модульность
Можно быстро подключить новый сценарий (например, контроль СИЗ), дообучив модель.
Detection и Recognize масштабируются параллельно — под разные камеры и задачи.
Разделение ответственности: интерфейс, хранилище и модули развиваются независимо.
Производительность
На одном сервере (Threadripper PRO + 2× RTX 4090) система держит около 30 RTSP-потоков. Средняя задержка от появления объекта в кадре до события в интерфейсе — меньше секунды. Это ключевой показатель, ради которого мы оптимизировали пайплайн.

При дальнейшем увеличении числа камер система начинает упираться в CPU-часть, связанную с декодированием видео и подготовкой данных. На практике узким местом оказывается не инференс, а подготовка видеопотока и работа с I/O.
Мы рассматривали варианты горизонтального масштабирования, но для текущих сценариев сделали ставку на вертикальное — с более мощными CPU и несколькими GPU на сервер.
Модель данных
Ядро системы — это события (Event) и кропы (EventPhoto). Каждое событие связано с камерой (Camera), функцией (CameraFunction) и временем. Кроп хранит изображение и результат обработки.
Отдельно ведутся пользователи (User), сотрудники (Employee), регионы (Region), а также настройки функций камеры и пакеты подписок. Такая модель позволяет хранить как «сырые» данные (кропы), так и бизнес-контекст (какой сотрудник, на какой территории, какое событие).
Мы сознательно не делаем видео основной сущностью системы. Хранение и обработка видеозаписей сильно усложняет аналитику и увеличивает требования к инфраструктуре.
Событийная модель позволяет работать с уже интерпретированными данными: временем, типом события, объектом и контекстом. Видео при этом остаётся источником, но не центром системы.
Модули и кейсы применения
Мы строили систему по принципу конструктора: модули можно подключать под разные задачи, они работают на общей архитектуре и обмениваются данными через единый пайплайн.
Автомобили. Система отмечает въезды и выезды: сохраняет время, фото и номер машины. Это дает статистику по парковкам и контроль тран��порта на промплощадках.

Люди и рабочее время. Камера фиксирует вход/выход или считает, сколько сотрудник провел в зоне — например, у станка. Так можно сверять табель с фактическим временем и понимать загрузку персонала.
Средства защиты. Отдельный модуль проверяет, есть ли каска или жилет. Нарушение фиксируется как событие.
Кейсы применения:
Завод: контроль транспорта на въезде и проверка касок.
Офис: вход сотрудников и интеграция со СКУД.
Склад: учет рабочего времени и СИЗ.
Парковка: автоматический учет заездов по номерам.
Мы строим модули на YOLO, OpenCV и PyTorch и дообучаем модели под конкретные сценарии. Для этого используем собственные датасеты — более 200 тысяч изображений автомобилей и номерных знаков, а также специализированные выборки для детекции касок и оружия.
Нишевые сценарии
В отдельных сценариях мы сознательно отказались от нейросетевых подходов. Например, при поиске дефектов на металлических поверхностях нейросети требовали большого объёма размеченных данных, которые было сложно и дорого собрать.
В таких случаях мы использовали классические методы компьютерного зрения, в частности признаки Харалика. Они позволяют анализировать текстуру поверхности и хорошо работают там, где дефект проявляется как изменение структуры материала, а не формы объекта.
Этот подход оказался устойчивым и предсказуемым, особенно в условиях ограниченного датасета. При этом он требует более точной настройки и понимания предметной области, чем нейросетевые модели. Прикерпляю пикчу:

Если тема классических методов CV интересна, могу разобрать этот подход подробнее в отдельной статье.
Инфраструктура и требования
Для стабильной работы используются:
Камеры: IP + RTSP (H.264, ≤1 Мбит/с).
Сервер: многопоточный CPU (Threadripper PRO), ≥128 ГБ RAM, 2× GPU уровня RTX 4090, быстрый SSD.
Мы тестировали и более легкие конфигурации: сервер с одной GPU держит не больше 8–10 потоков.
Отдельный пласт работы — эксплуатация. Мы мониторим не только технические метрики (загрузка CPU/GPU, задержки очередей), но и качество распознавания: рост ложных срабатываний часто сигнализирует о проблемах с камерой или освещением.
«Ошибка Кабачок»
При первых тестах на слабом сервере мы столкнулись с артефактами и потерей кадров из-за проблем с декодированием видеопотока. Внутри команды эту багу мы в шутку назвали «ошибка Кабачок». Опыт показал: без мощного CPU и двух GPU система нестабильна, поэтому для продакшена мы сразу выбрали Threadripper и RTX 4090.

Минимальная настройка
В config.ini настраиваются:
confidence_ratio— баланс между пропусками и ложными срабатываниями;
class_list— список объектов для поиска (авто, человек, каска);
BoundingBox— расширение рамки, чтобы не обрезать номер.
Интеграции:
Telegram — уведомления о событиях.
FaceReg — идентификация лиц.
Swagger — автодокументация API.
Выводы и уроки
Опыт с zool (так назвали продукт) показал, что ставка на open source оправдана, но не решает всё автоматически.
Где помогло:
Быстро собрали прототипы на YOLO, OpenCV и PyTorch.
Сократили расходы на лицензии.
Получили гибкость — можно дообучать модели под конкретные задачи.
Где пришлось дорабатывать:
Обучение на собственных датасетах (например, российские номера машин).
Оптимизация под высокую нагрузку и десятки потоков.
Настройка пайплайна и параметров, чтобы снизить ложные срабатывания.
Почему гибридный подход лучше. Открытые библиотеки закрывают базовые задачи, а свои сервисы дают управляемость и удобство для бизнеса. Такой баланс позволяет развивать продукт, не завязываясь на одном вендоре и сохраняя контроль над качеством.
Что дальше. Мы планируем расширять модули (например, анализ поведения людей), добавлять новые интеграции и повышать производительность системы при росте числа камер.
