dobrovolskiy.com
EN
← Заметки2026-08-30 · Дмитрий Добровольский

Сверхлёгкий просмотрщик и регистратор IP-камер на C: десятки RTSP-потоков на слабом ПК

Кейс Ultralight IP CAM Viewer: приложение на C11 (17 тыс. строк) поверх FFmpeg + SDL2 — сетка RTSP-камер, запись в почасовые MPEG-TS, таймлайн архива, управление ONVIF PTZ и работа на очень слабом железе.

Ultralight IP CAM Viewer — приложение для Windows на чистом C11 поверх FFmpeg и SDL2: матрица RTSP-камер, непрерывная запись в почасовые сегменты MPEG-TS, прокручиваемый таймлайн архива, ONVIF PTZ мышью и плагинный ABI на C. Один рабочий поток на камеру и статически слинкованный минимальный FFmpeg делают его настолько лёгким, что одна машина тянет заметно больше камер, чем обычный NVR-софт. Сделано для реального склада с 15 камерами.

Зачем ещё один просмотрщик камер

У заказчика склад и цех с пятнадцатью IP-камерами и один старый офисный компьютер, чтобы за ними смотреть. Каждый NVR-пакет, который он пробовал, либо съедал машину целиком, либо останавливался на нескольких потоках. Запрос был простой: показать все камеры сразу, вести архив, дать отмотать назад, не падать и не требовать нового компьютера.

Ответ — написать на C с двумя зависимостями, которые я контролирую: FFmpeg для демуксинга и декодирования, SDL2 для рендеринга, звука и потоков. Всё остальное — вывод текста, ONVIF-клиент, интерфейс — написано руками. В итоге около 17 000 строк на C и портативная поставка: exe плюс две DLL.

Весь фокус — в дисциплине потоков

У каждой камеры свой рабочий поток: открывает RTSP-сессию, декодирует и отдаёт кадры рендереру. Блокировки только на уровне камеры, между камерами ничего общего. Потоки декодирования никогда не трогают диск; регистратор каждой камеры полностью асинхронный и не блокирует декодирование. Поток интерфейса только заглядывает в последний кадр. Семафор, ограничивающий одновременные RTSP-подключения, убирает всплески рукопожатий, из-за которых регистраторы отказывают в соединении при одновременном старте всех камер.

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

Запись и «машина времени»

Запись идёт почасовыми сегментами MPEG-TS в recordings/<камера>/<дд.ММ.гггг>/<начало__конец>.ts; при закрытии файл переименовывается по точному интервалу. Обрезчик архива держит лимит MaxArchiveGB.

Режим DVR (F9) сканирует записи в индекс покрытия и рисует внизу полосу таймлайна, по которой можно двигаться, масштабировать и перематывать; воспроизведение идёт в темпе 1× поверх живой плитки, чтобы не терять контекст, на какую камеру смотришь.

ONVIF без gSOAP

Поворотные камеры управляются мышью. ONVIF-клиент — обнаружение устройства, медиапрофилей, ContinuousMove/Stop — это самописный SOAP 1.2 с аутентификацией WS-Security UsernameToken digest. Он живёт в отдельном потоке с почтовым ящиком на одну команду (побеждает самая свежая) и сторожевым таймером, который останавливает голову, если команды перестали приходить.

Плагинный ABI и счётчик лиц без зависимостей

Аналитика не вкомпилирована. Плагины — библиотеки на C с версионированным ABI (магическое число, версия ABI, структуры с проверкой размера); они получают кадры YUV420P и звук S16 и возвращают прямоугольники наложения. Поставляемый плагин «Счётчик лиц» находит лица каскадом pico, повторно идентифицирует их по LBP-гистограммам и считает уникальных посетителей за день — без OpenCV и внешних библиотек, ставится своим MSI.

Надёжность и упаковка

Журнал падений через SEH, поток-сторож зависаний интерфейса, трассировочный лог старта и автоматическое переподключение закрывают все режимы отказа, которые встретились на объекте. Настройки в settings.ini пишет фоновый писатель; менеджер камер, настройки и менеджер плагинов — оверлеи внутри приложения (F1/F2/F10) на русском и английском. Сборка CMake + Ninja под MSYS2 UCRT64 со скриптом минимальной статической сборки FFmpeg; установщики — WiX MSI и MSIX.

Что сделал бы иначе

Заложил бы плагинный ABI раньше. Он появился после запроса на счётчик лиц, и встраивание задним числом означало правку пути кадра в каждом рабочем потоке. Всё остальное — правило «один поток на камеру», никакого диска в потоках декодирования — оставил бы ровно как есть: именно поэтому старый офисный ПК справляется.

Вопросы

Сколько камер вытянет?

Рабочая конфигурация — 15 камер на слабом офисном ПК. Предел — производительность декодирования, она растёт с числом ядер; поскольку нет накладных расходов фреймворка, а запись никогда не блокирует декодирование, одна машина держит заметно больше потоков, чем обычный NVR-софт.

Работает с камерами Hikvision / Dahua / TP-Link?

Работает со всем, что говорит по RTSP (видео H.264 плюс звук). На объекте заказчика смешаны адреса в стиле Dahua/Hikvision `/user=…_channel=1` и TP-Link `/stream1`. Для PTZ нужен ONVIF.

Можете адаптировать под мой объект или добавить аналитику?

Да. Особенности конкретных камер, своё наложение или новый плагин анализа — типичная задача на одну-две сессии; плагинный ABI сделан именно для этого.

Нужно что-то похожее?

Делаю это вживую на звонке в Zoom / Яндекс Телемост, вы смотрите на экран, таймер останавливается по вашему слову. Первые 15 минут бесплатно.

Ещё проекты

Сверхлегкий просмотрщик IP-камерСверхлёгкий многокамерный просмотрщик и регистратор RTSP: десятки камер на одном слабом ПК или сервере написанный на чистом C.