01Назначение и границы системы
1.1Что разрабатывается
Периметр (рабочее название) — программный комплекс видеонаблюдения класса VMS для объектов среднего размера: торговые центры, производства, склады, сети магазинов, жилые комплексы. Функциональный ориентир — «Линия» (ДССЛ) и TRASSIR.
Комплекс состоит из трёх поставляемых продуктов:
- Сервер — служба на Linux: приём потоков с камер, запись в архив, управление хранилищами, детекция, раздача видео клиентам, REST/gRPC API.
- Клиент для Windows — нативное приложение оператора: живой просмотр в сетках, работа с архивом, экспорт, PTZ.
- Веб-интерфейс — администрирование сервера и облегчённый просмотр без установки ПО.
1.2Границы версии 1.0
В релиз 1.0 входит: приём RTSP/ONVIF, непрерывная запись и запись по детекции, многодисковый архив с ретеншном, живой просмотр до 64 каналов в сетке, просмотр и экспорт архива, детектор движения, PTZ, расписания, права доступа, лицензирование по каналам.
В релиз 1.0 не входит и переносится на последующие версии:
| Функция | Версия | Причина отсечения |
|---|---|---|
| Распознавание лиц, ЛПР (номера) | 2.0 | Требует отдельного GPU-конвейера и юридической обвязки |
| Интеграция с POS / кассами | 2.0 | Индивидуально под каждую кассовую систему |
| Федерация серверов, единое дерево объектов | 1.5 | Архитектурно заложено, реализуется после стабилизации узла |
| Мобильные клиенты iOS / Android | 1.5 | Зависит от готовности WebRTC-раздачи |
| Отказоустойчивый кластер (failover-узел) | 2.0 | Резервирование на 1.0 — только дублирование записи |
| Интеграция со СКУД и ОПС | 1.5 | Нужен выбор конкретных партнёрских систем |
Сервер никогда не декодирует и не перекодирует основной поток. Видео с камеры проходит от сокета до файла архива и до клиента как последовательность байтов кодированных кадров. Декодирование допускается только для субпотока в детекторе движения и для генерации превью. Это единственный способ уложить 100 каналов в 16 ядер — и именно так устроены промышленные VMS.
1.3Целевые сценарии эксплуатации
- Оператор круглосуточно держит открытой сетку 16–36 камер, реагирует на тревоги, изредка разворачивает канал на весь экран.
- Служба безопасности разбирает инцидент: находит момент по времени и движению, просматривает 4–9 камер синхронно, экспортирует фрагмент для передачи.
- Инженер добавляет камеры, настраивает расписания и зоны детекции, следит за заполнением дисков и доступностью каналов.
- Руководитель раз в неделю заходит из браузера посмотреть несколько камер и выгрузить отчёт по доступности.
02Термины и сокращения
| Термин | Значение |
|---|---|
| Канал | Один видеопоток одной камеры. Единица лицензирования. Камера с main+sub — это один канал. |
| Основной поток (main) | Поток максимального разрешения, используется для записи и полноэкранного просмотра. |
| Субпоток (sub) | Поток низкого разрешения (обычно 640×360…704×576), используется в сетках и детекторе движения. |
| Сегмент | Файл архива фиксированной длительности или размера, содержащий непрерывный участок записи одного потока. |
| GOP | Группа кадров между опорными (IDR). Определяет гранулярность позиционирования в архиве. |
| Пул хранения | Точка монтирования (диск, массив, сетевой ресурс) с квотами и политикой ретеншна. |
| Ретеншн | Автоматическое удаление старых записей при достижении лимита по объёму или глубине. |
| Раскладка | Именованный набор камер с расстановкой по ячейкам экрана. |
| VSP | Video Stream Protocol — внутренний бинарный протокол раздачи видео нативному клиенту. |
| ONVIF | Отраслевой стандарт управления IP-камерами. Профили: S (видео), T (H.265), G (архив), M (аналитика). |
03Целевая нагрузка и расчёт ресурсов
3.1Расчётный профиль объекта
Проектная точка — 100 каналов на один сервер. Типовая камера: 4 Мп, H.265, 15–25 к/с, битрейт 4 Мбит/с (main) и 0,5 Мбит/с (sub), GOP 2 с. Записывается основной поток; субпоток передаётся клиентам и детектору, но в архив не пишется.
Базовая формула объёма (единицы производителей дисков, 1 ТБ = 1012 байт):
ТБ_в_сутки = суммарный_битрейт_Мбит/с × 0,0108
// 100 каналов × 4 Мбит/с = 400 Мбит/с → 400 × 0,0108 = 4,32 ТБ/сутки
3.2Сценарии объёма архива
| Сценарий | Каналов | Мбит/с на канал | Поток Мбит/с | ТБ/сут | 30 сут |
|---|---|---|---|---|---|
| 50 камер 2 Мп, непрерывно | 50 | 3,0 | 150 | 1,62 | 49 ТБ |
| 100 камер 4 Мп, непрерывно | 100 | 4,0 | 400 | 4,32 | 130 ТБ |
| 100 камер 4 Мп, по детекции (25 %) | 100 | 4,0 | 100 | 1,08 | 33 ТБ |
| 100 камер 4К, непрерывно | 100 | 8,0 | 800 | 8,64 | 259 ТБ |
Глубина архива и режим записи — настройки уровня камеры, а не проектное допущение (см. раздел 5). Таблица служит калькулятором планирования: непрерывная запись 100 каналов 4 Мп на 30 суток требует 130 ТБ полезного объёма — 8×20 ТБ в JBOD, — а переход той же конфигурации на запись по детекции снижает потребность до 33 ТБ. Соответствующий калькулятор встраивается в интерфейс и пересчитывает прогноз при каждом изменении настроек (6.9, 5.6).
3.3Требования к серверу
| Каналов | CPU | RAM | Сеть | Диски |
|---|---|---|---|---|
| до 25 | 4 ядра x86-64 | 16 ГБ | 1 GbE | 2 × HDD + SSD под ОС и БД |
| до 50 | 8 ядер | 32 ГБ | 2 × 1 GbE (LACP) | 4 × HDD JBOD + NVMe под БД |
| до 100 | 16 ядер | 64 ГБ | 10 GbE | 8 × HDD JBOD + NVMe (БД, индекс, превью) |
Обоснование по подсистемам при 100 каналах:
- CPU. Транзитная запись без декодирования — 0,02–0,04 ядра на поток, итого 2–4 ядра. Детектор движения на субпотоках (640×360, 5 к/с) — ещё 2–3 ядра программно или почти ноль при VAAPI/QSV на встроенном видеоядре. Остальное — запас на пики и клиентские сессии.
- RAM. Кольцевой буфер преролла 30 с × 100 каналов × 0,5 МБ/с ≈ 1,5 ГБ; буферы записи 8 МБ × 100 ≈ 0,8 ГБ; PostgreSQL, кэш ФС и рантайм — остальное.
- Диск. 50 МБ/с суммарной записи — мало по объёму, но 100 параллельных потоков дают случайный доступ. Решается буферизацией по 4–8 МБ на поток и записью большими последовательными блоками; тогда обычный HDD-массив держит нагрузку с многократным запасом.
- Сеть. 400 Мбит/с входящего трафика плюс исходящий клиентам. Четыре оператора с сеткой 16 субпотоков — около 32 Мбит/с, но развёрнутые основные потоки и выгрузка архива дают пики в сотни Мбит/с. 1 GbE работает без запаса, 10 GbE обязателен для комфорта.
04Архитектура
4.1Состав серверных модулей
| Модуль | Ответственность | Ключевые зависимости |
|---|---|---|
| Ingest | Подключение к камере, переподключение, разбор RTP, сборка кадров, парсинг SPS/PPS/VPS, определение параметров потока | gortsplib, mediacommon |
| Ring buffer | Кольцевой буфер последних N секунд каждого потока в RAM: преролл, «мгновенный повтор», старт с опорного кадра | — |
| Recorder | Нарезка на сегменты, запись fMP4 и индекса, ротация файлов, транзакционная фиксация в БД | — |
| Retention | Учёт занятого места, кольцевое удаление, квоты по камере и пулу, защищённые интервалы | — |
| Detector | Декодирование субпотока, детекция движения по зонам, приём событий ONVIF с камеры, генерация событий | FFmpeg (LGPL, динамически) |
| Streamer | Раздача live и архива: VSP для нативного клиента, WebRTC и LL-HLS для браузера | pion/webrtc |
| Core API | REST + gRPC, аутентификация, RBAC, конфигурация, аудит, здоровье системы | PostgreSQL |
| Discovery | WS-Discovery, опрос ONVIF-профилей, автозаполнение параметров камеры, PTZ | — |
4.2Управление жизненным циклом потока
Каждый канал обслуживается независимой горутиной-супервизором с конечным автоматом состояний: idle → connecting → probing → streaming → degraded → reconnecting. Требования:
- Отказ одной камеры не влияет ни на одну другую. Паника в обработчике потока перехватывается и переводит канал в
reconnecting. - Переподключение с экспоненциальной задержкой 1 → 2 → 4 → … → 30 с и джиттером, чтобы 100 камер не переподключались синхронно после сетевого сбоя.
- Обрыв фиксируется как событие и отображается на шкале архива как разрыв записи, а не как «пустое время».
- Потребители потока (запись, детектор, клиенты) подписываются на общую шину кадров; ни один потребитель не может заблокировать чтение из сокета — медленный подписчик получает дроп с ближайшего опорного кадра.
05Принципы конфигурирования
Требование заказчика: система тиражируемая, ни одно эксплуатационное решение не может быть зашито в код. Глубина архива, режим записи, пороги детекции, длительность сегмента, поведение при отказе — всё это на разных объектах отличается и должно меняться из интерфейса. Раздел задаёт правила, которым подчиняются все остальные разделы документа.
5.1Запрет зашитых значений
Любое поведение, которое на двух разных объектах может потребоваться разным, выносится в конфигурацию. В коде остаются только значения по умолчанию, собранные в одном модуле и снабжённые описанием, типом и допустимым диапазоном. Числовой литерал в логике записи, ретеншна, детекции, сети или переподключения — дефект, выявляемый на код-ревью.
Числа, приведённые в разделах 4 и 7 настоящего ТЗ (30 суток, 5 минут на сегмент, 256 МБ, 10 секунд преролла), — это значения по умолчанию, а не проектные допущения. Расчёты раздела 4 служат калькулятором планирования объекта, а не описанием жёстко заданного режима.
5.2Иерархия настроек
Четыре уровня, каждый переопределяет предыдущий только явно заданными полями, остальное наследуется:
| Уровень | Область | Пример |
|---|---|---|
| 1 | Значения по умолчанию продукта | Преролл 5 с, транспорт TCP, сегмент 5 мин |
| 2 | Профиль — именованный набор настроек | «Периметр объекта»: непрерывно, 60 суток, высокий приоритет |
| 3 | Группа камер | «Склад»: запись по детекции, 14 суток |
| 4 | Отдельная камера | Касса №3: непрерывно, 90 суток, защита от удаления |
В интерфейсе для каждого параметра видно действующее значение, уровень, с которого оно пришло, и что произойдёт, если переопределение снять. Без этого настройка парка из 100 камер превращается в угадывание.
5.3Профили
Профиль — самостоятельная сущность, на которую ссылаются камеры. Виды: профиль записи, профиль хранения, профиль детекции, профиль подключения. Изменение профиля немедленно применяется ко всем камерам, которые на него ссылаются. Поддерживается массовое применение профиля к выделенным камерам и копирование настроек с одной камеры на группу.
5.4Применение без перезапуска
- Изменение глубины хранения, квот, расписаний, зон детекции, реакций на события, прав доступа применяется немедленно и без разрыва записи.
- Изменение параметров подключения — адреса, учётных данных, URI, транспорта — требует переподключения, но только затронутого канала, с явным предупреждением о секундах разрыва.
- Перечень параметров, требующих перезапуска службы, должен стремиться к пустому. Если параметр всё же требует перезапуска, он помечается в интерфейсе, и система предлагает окно применения.
5.5История изменений, экспорт и откат
- Каждое изменение конфигурации версионируется: кто, когда, что было, что стало. Доступен просмотр различий между версиями и откат.
- Экспорт и импорт конфигурации объекта целиком — для тиражирования однотипных объектов и восстановления на новом сервере. Пароли камер выгружаются только в зашифрованном виде.
- Шаблон объекта: сохранённая конфигурация без привязки к конкретным адресам, применяемая при развёртывании нового объекта той же серии.
5.6Предупреждение о последствиях
Изменения, влияющие на объём архива, показывают пересчитанный прогноз до сохранения: текущая и новая расчётная глубина, дата, с которой начнётся вытеснение, свободное место в пуле. Изменение, которое приведёт к немедленному удалению существующих записей, требует отдельного подтверждения и фиксируется в аудите.
5.7Реестр параметров
Полный реестр ведётся как машиночитаемый файл, из которого генерируются интерфейс, схема API и документация. Ниже — ключевые параметры; реестр версии 1.0 содержит порядка 150 позиций.
| Параметр | Уровень | По умолч. | Диапазон |
|---|---|---|---|
| Режим записи | камера | непрерывно | выкл · непрерывно · расписание · детекция · событие · комбинированный |
| Глубина хранения, сут | камера | 30 | 1 … 3650 |
| Политика ретеншна | камера | по глубине и объёму | по глубине · по объёму · комбинированно |
| Преролл, с | камера | 5 | 0 … 60 |
| Постролл, с | камера | 15 | 0 … 300 |
| Кольцевой буфер, с | камера | 10 | 0 … 60 |
| Приоритет камеры | камера | 50 | 0 … 100 |
| Длительность сегмента, с | пул | 300 | 60 … 900 |
| Размер сегмента, МБ | пул | 256 | 32 … 1024 |
| Минимум свободного места, % | пул | 5 | 1 … 30 |
| Квота защищённых записей, % | пул | 20 | 0 … 90 |
| Шифрование архива | пул | выкл | вкл · выкл |
| Транспорт RTSP | камера | TCP | TCP · UDP · авто |
| Максимальная пауза переподключения, с | система | 30 | 5 … 300 |
| Чувствительность детектора | зона | 50 | 0 … 100 |
| Минимальный размер объекта, % кадра | зона | 1 | 0,1 … 50 |
| Минимальная длительность движения, мс | зона | 500 | 100 … 10000 |
| Порог перехода на субпоток, ячеек | пользователь | 9 | 1 … 64 |
| Срок хранения журнала аудита, сут | система | 365 | 30 … 3650 |
Реестр — не документация, а источник, из которого генерируются экран настроек, схема API и справка. При разработке в одиночку это единственный способ выполнить требование полной конфигурируемости: 150 рукописных экранов настройки не пишутся одним человеком, 150 строк реестра — пишутся за день.
Настроек «только в конфигурационном файле» и «только в интерфейсе» не существует. Каждый параметр реестра доступен через API на чтение и запись с проверкой прав, иначе автоматизация развёртывания на сетевых объектах станет невозможной, а интеграторы будут править файлы на сервере руками.
06Медиа-подсистема и подключение камер
6.1Приём потоков
| Протокол | Режим | Приоритет |
|---|---|---|
| RTSP / RTP over TCP (interleaved) | Основной режим по умолчанию — надёжен, проходит NAT и не теряет пакеты | v1.0 |
| RTSP / RTP over UDP | Опция для нагруженных сетей; требует обработки потерь и восстановления по RTCP | v1.0 |
| ONVIF Profile S / T | Обнаружение камер, получение URI потоков, параметры, PTZ, события | v1.0 |
| MJPEG over HTTP | Старые камеры и специфические устройства | v1.0 |
| RTMP / SRT push | Источники за NAT, которые сами подключаются к серверу | v1.2 |
| ONVIF Profile G | Выгрузка архива из встроенной SD-карты камеры после разрыва связи | v1.5 |
6.2Кодеки
Видео: H.264 (Baseline/Main/High), H.265 (Main/Main10), MJPEG. Аудио: AAC-LC, G.711 µ/A, G.726, Opus. AV1 — резерв на 2.0.
Отдельно поддерживаются «умные» кодеки камер (Hikvision H.264+, Dahua Smart Codec, Axis Zipstream): они формируют потоки с очень длинным GOP и B-кадрами. Требование: сервер обязан корректно записывать и отдавать такие потоки транзитом, а позиционирование в архиве выполняется по фактическим опорным кадрам, а не по номинальному GOP.
6.3Кольцевой буфер и преролл
Для каждого канала в RAM хранится скользящее окно последних 0–60 секунд (по умолчанию 10 с), выровненное по границам GOP. Назначение:
- Преролл при записи по событию: в архив попадает не только момент срабатывания, но и заданное число секунд до него.
- Мгновенный старт живого просмотра: клиент получает данные с последнего опорного кадра, не дожидаясь следующего IDR — картинка появляется за десятки миллисекунд вместо секунд.
- Функция «повтор последних 30 секунд» у оператора без обращения к диску.
6.4Раздача видео
| Потребитель | Транспорт | Задержка | Обоснование |
|---|---|---|---|
| Клиент Windows 1.0 | VSP — бинарные кадры поверх WSS | < 300 мс | Полный контроль над буферизацией, точный seek, один сокет на все каналы сетки |
| Браузер, live 1.0 | fMP4 через MSE поверх одного сокета | < 1 с | Реализовано без WebRTC: браузер декодирует H.264 сам, сервер не перекодирует. WebRTC остаётся резервом, если задержка станет критичной |
| Браузер, архив 1.0 | fMP4 через MSE | — | Сегменты архива отдаются как есть, без ремукса |
| Интеграции | RTSP-выход сервера | < 1 с | Совместимость со сторонними системами и видеостенами |
Формат кадра VSP (заголовок 24 байта, little-endian):
u8 type // 1=video 2=audio 3=meta 4=keepalive 5=gap
u8 flags // bit0 keyframe, bit1 discontinuity
u16 stream_id // номер подписки в рамках соединения
u32 length // длина payload
i64 pts_us // абсолютное время UTC, микросекунды
i64 dts_us
// payload: NAL-юниты в формате AVCC (length-prefixed)
Управляющий канал того же соединения (JSON-сообщения): subscribe, unsubscribe, seek, set_speed, set_quality, keyframes_only. Режим keyframes_only обязателен: он используется при перемотке архива на высоких скоростях и при отрисовке превью на шкале времени.
6.5Автообнаружение камер в сети
Требование: инженер указывает диапазон адресов или просто нажимает «Найти камеры», и система сама находит устройства, определяет производителя и модель, подбирает URI потоков и параметры. Ручной ввод RTSP-ссылки остаётся, но как запасной путь, а не как основной сценарий.
Поиск выполняется несколькими независимыми механизмами параллельно, результаты объединяются по MAC-адресу:
| Механизм | Транспорт | Что даёт |
|---|---|---|
| ONVIF WS-Discovery | UDP multicast 239.255.255.250:3702, SOAP Probe | Основной путь. Адрес, XAddr сервиса устройства, типы и scopes |
| UPnP SSDP | UDP multicast 239.255.255.250:1900 | Модель и производитель для камер без ONVIF-ответа |
| mDNS / Bonjour | UDP 5353, службы _rtsp._tcp, _onvif._tcp, _axis-video._tcp | Axis, часть Hanwha и потребительских камер |
| SADP (Hikvision) | UDP 37020, широковещательный запрос | Серийный номер, модель, статус активации, версия прошивки |
| Dahua Discovery | UDP 37810, широковещательный JSON-запрос | Модель, MAC, версия; распознаёт также OEM-бренды на платформе Dahua |
| Сканирование подсети | ARP + TCP-проба портов 554, 80, 443, 8000, 8899, 2020, 34567, 37777 | Запасной путь для камер с выключенным ONVIF и в маршрутизируемых сетях |
| Импорт списка | CSV, диапазон IP, файл выгрузки из другой VMS | Массовое добавление на объектах с готовой адресацией |
| LLDP / SNMP на коммутаторе | SNMP-опрос таблиц портов v1.5 | Привязка камеры к порту коммутатора для диагностики и питания PoE |
WS-Discovery, SSDP и mDNS не проходят через маршрутизаторы. На объектах с несколькими VLAN обнаружение работает только в подсети сервера, поэтому сканирование диапазонов и импорт списка обязательны в версии 1.0, а не откладываются. Для удалённых сегментов предусматривается лёгкий агент-ретранслятор обнаружения. v1.5
6.6Определение производителя и модели
Идентификация выполняется по цепочке признаков, каждый следующий уточняет предыдущий:
- MAC OUI — встроенный справочник префиксов IEEE даёт производителя ещё до любого запроса к устройству. Учитывать, что OEM-камеры (RVi, Novicam, Trassir, часть Beward) используют OUI платформы-донора — это признак, а не приговор.
- ONVIF
GetDeviceInformation— Manufacturer, Model, FirmwareVersion, SerialNumber. Самый достоверный источник. - HTTP-отпечаток — заголовок
Server,WWW-Authenticaterealm, заголовок страницы входа, хеш favicon, характерные пути (/doc/page/login.aspу Hikvision,/RPC2_Loginу Dahua,/axis-cgi/у Axis). - RTSP
OPTIONS— заголовокServerи набор поддерживаемых методов.
Результат — vendor, model, firmware и идентификатор профиля из встроенной базы. Если совпадений нет, устройство помечается как generic-onvif или generic-rtsp и обрабатывается по общим правилам.
6.7Автоопределение потоков и параметров
Порядок действий после идентификации устройства:
- Через ONVIF Media.
GetProfiles→GetStreamUriдля каждого профиля. Приоритетный путь: даёт готовые URI, кодек, разрешение, частоту кадров, битрейт и признак наличия аудио без единого подключения к потоку. - Через базу шаблонов. Если ONVIF недоступен, перебираются RTSP-пути профиля вендора, начиная с наиболее вероятного. Перебор ограничен по времени и числу попыток.
- Проба потока. Для каждого найденного URI выполняется
DESCRIBE, разбирается SDP, затем принимаются первые 5–10 секунд данных. ИзSPS/VPSизвлекаются реальные разрешение, профиль и уровень кодека; по временным меткам измеряется фактическая частота кадров и битрейт. - Назначение ролей. Профиль с максимальным разрешением становится основным потоком, профиль с разрешением ниже 800×600 — субпотоком. Если субпотока нет, система предупреждает: сетка более 16 каналов будет работать на основных потоках с соответствующей нагрузкой.
- Определение возможностей. Наличие PTZ и набор команд, тревожные входы и выходы, аудиовыход для двусторонней связи, встроенная аналитика (ONVIF Profile M), карта памяти (Profile G), поддержка событий по подписке.
Автоподбор пароля по списку заводских значений допустим только по явной команде оператора и с жёстким лимитом: не более 3 попыток на устройство с паузой 5 с. Большинство камер блокируют учётную запись после 5–10 неудачных входов, и массовый перебор на объекте из 100 камер приведёт к недоступности половины из них. Найденные заводские пароли отмечаются в интерфейсе как уязвимость с требованием смены.
6.8База профилей вендоров
Встроенный обновляемый справочник (JSON, поставляется с сервером и обновляется отдельно от версии ПО). Для каждого вендора описываются шаблоны RTSP-путей, порт ONVIF, особенности реализации и известные дефекты прошивок.
| Вендор | Шаблон основного потока | Субпоток |
|---|---|---|
| Hikvision | /Streaming/Channels/101 | /Streaming/Channels/102 |
| Dahua, RVi, Novicam | /cam/realmonitor?channel=1&subtype=0 | subtype=1 |
| Axis | /axis-media/media.amp | ?resolution=640x360 |
| Hanwha, Samsung | /profile1/media.smp | /profile2/media.smp |
| Uniview | /media/video1 | /media/video2 |
| Bosch | /rtsp_tunnel?h26x=4&line=1&inst=1 | inst=2 |
| Vivotek | /live.sdp | /live2.sdp |
| Reolink | /h264Preview_01_main | /h264Preview_01_sub |
| Beward | /av0_0 | /av0_1 |
| Generic ONVIF | URI берутся из GetStreamUri, шаблоны не применяются | |
Помимо путей, профиль хранит поправки на известные дефекты прошивок — без них подключение части камер «работает через раз»:
| Поправка | Проявление без неё |
|---|---|
sps_in_sdp_only | Камера не повторяет SPS/PPS в потоке. Первый кадр после подключения не декодируется — параметры нужно подставлять перед каждым IDR |
force_tcp | По UDP камера теряет пакеты или не отвечает вовсе |
keepalive_get_parameter | Сессия рвётся каждые 60 с, потому что камера не принимает OPTIONS как keepalive |
broken_pts | Временные метки скачут или обнуляются. Требуется реконструкция часов по частоте кадров, иначе архив «рассыпается» на шкале |
declared_codec_mismatch | В SDP объявлен H.265, фактически передаётся H.264 (и наоборот). Кодек определяется по стартовым кодам, а не по описанию |
phantom_audio | Аудиотрек объявлен, но данные не идут. Без поправки запись ждёт аудио и накапливает задержку |
onvif_port | ONVIF висит не на 80, а на 8000, 2020 или 8899 — устройство считается «не поддерживающим ONVIF» |
6.9Повторная проверка параметров
Раз в сутки и при каждом переподключении система сверяет фактические параметры потока с сохранёнными. Если разрешение, кодек, частота кадров или битрейт изменились — например, настройки камеры поменяли через её веб-интерфейс — формируется событие, конфигурация канала обновляется, а прогноз глубины архива пересчитывается. Молча писать поток с неожиданно выросшим втрое битрейтом недопустимо: это самый частый способ незаметно потерять глубину архива на объекте.
07Хранение архива
7.1Формат хранения
Архив хранится сегментными файлами в фрагментированном MP4 (fMP4 / CMAF) с отдельным файлом индекса. Решение принято против двух альтернатив: сырой раздел с собственным контейнером (быстрее, но резко усложняет диагностику и восстановление у заказчика) и обычный MP4 (не переживает отключение питания — таблица moov дописывается в конце).
Свойства выбранного формата:
- Файл, оборванный на середине, остаётся полностью читаемым до последнего целого фрагмента — критично при пропадании питания.
- Экспорт в MP4 — ремукс без перекодирования, то есть секунды на часовой фрагмент.
- Сегменты отдаются в браузер через MSE напрямую, без промежуточного слоя.
Раскладка на диске:
/mnt/pool-1/perimetr/<camera-uuid>/2026/09/02/14/
init.mp4 // параметры трека (SPS/PPS/VPS)
20260902T140000.000_140459.872.m4s // медиа-сегмент, ~5 мин
20260902T140000.000.vidx // индекс опорных кадров
20260902T140459.872_140959.640.m4s
...
Сегмент закрывается по достижении 5 минут или 256 МБ — что наступит раньше. Граница сегмента всегда совпадает с опорным кадром. Индекс .vidx хранит только записи по IDR (16 байт: смещение, размер фрагмента, PTS), при GOP 2 с это ~150 записей и 2,4 КБ на сегмент. Позиционирование внутри GOP выполняется разбором фрагмента на лету.
Покадровый индекс для 100 каналов на 30 суток занял бы около 155 ГБ и создал бы вторую по нагрузке подсистему хранения. Индекс по IDR — 3 ГБ, помещается на NVMe целиком и читается за микросекунды. Точность позиционирования при этом остаётся равной длине GOP, что и является физическим пределом для любого VMS.
7.2Пулы хранения
- Администратор объявляет произвольное число пулов — точек монтирования: локальные диски, RAID-массивы, iSCSI, NFS/SMB.
- Для каждого пула задаются: максимальный объём (или процент), минимальный свободный резерв, приоритет, список привязанных камер.
- Камера может писать в один пул с автоматическим переключением на резервный при недоступности основного. Переключение фиксируется как событие и отражается на шкале.
- Поддерживается двухуровневое хранение: «горячий» пул на SSD для последних N часов и «холодный» на HDD для остального. v1.2
- Рекомендуемая конфигурация — JBOD, а не RAID-5/6: при отказе диска теряется архив только тех камер, что писали на него, а не деградирует запись всего сервера. Камеры равномерно распределяются по дискам.
7.3Ретеншн и защита записей
| Политика | Поведение |
|---|---|
| По глубине | Удалять записи старше N суток независимо от свободного места |
| По объёму | При достижении квоты удалять самые старые сегменты камеры (кольцевая запись) |
| Приоритет камер | Каналы с высоким приоритетом получают гарантированную глубину, остальные уплотняются первыми |
| Защищённые интервалы | Помеченные оператором или тревогой фрагменты не удаляются автоматически. Учитываются отдельной квотой; при её переполнении — предупреждение администратору, а не тихое удаление |
| Юридическое удержание | Блокировка удаления по всему объекту на период разбирательства, с записью в аудит |
7.4Целостность и восстановление
- При старте выполняется быстрая сверка БД и файловой системы: сегменты в БД без файлов помечаются утраченными, файлы без записей в БД — переиндексируются фоновым сканером.
- Незакрытый сегмент после аварийного выключения восстанавливается линейным сканом фрагментов, индекс перестраивается.
- Периодический контроль SMART дисков и заполнения; предупреждение оператору при прогнозе исчерпания места, деградации массива и при росте ошибок чтения.
7.5Шифрование архива v1.2
Опциональное шифрование сегментов AES-256-GCM с ключом на пул. Ключ хранится вне пула, в защищённом хранилище сервера; при выносе диска архив нечитаем. Учитывать, что шифрование даёт 3–8 % накладных расходов CPU и исключает прямую отдачу сегментов в браузер без расшифровки на сервере.
08Подсистема записи
8.1Режимы записи
Режим задаётся на уровне камеры, группы или профиля по правилам раздела 5 и может отличаться для разных интервалов расписания одной и той же камеры.
| Режим | Описание |
|---|---|
| Непрерывно | Круглосуточная запись основного потока. Максимальный объём, максимальная полнота |
| По расписанию | Недельная сетка с шагом 15 минут; отдельно задаются праздничные дни и исключения |
| По детекции движения | Запись при срабатывании детектора с прероллом и построллом |
| По событию | Тревожный вход камеры, ONVIF-событие, событие внешней системы, ручная тревога оператора |
| Комбинированный | Непрерывно с пониженным качеством или частотой опорных кадров, полное качество — по событию v1.2 |
| Вручную | Оператор включает запись кнопкой; интервал автоматически помечается защищённым |
8.2Требования к записи по событию
- Преролл берётся из кольцевого буфера, настраивается 0–60 с, по умолчанию 5 с.
- Постролл настраивается 0–300 с, по умолчанию 15 с. Новое срабатывание внутри постролла продлевает запись, а не создаёт второй фрагмент.
- Запись всегда начинается с опорного кадра — иначе первые секунды фрагмента невозможно декодировать.
- Между двумя фрагментами архива фиксируется явный разрыв со временем начала и конца, чтобы шкала не показывала ложную непрерывность.
8.3Дублирование записи v1.2
Возможность вести параллельную запись выбранных камер во второй пул или на второй сервер. Для 1.0 достаточно резервного пула при отказе основного; полноценное зеркалирование — 1.2.
09Детекция и аналитика
9.1Три уровня детекции
| Уровень | Где выполняется | Нагрузка на сервер | Версия |
|---|---|---|---|
| События камеры | На камере, приходят по ONVIF-подписке или проприетарному API | Нулевая | 1.0 |
| Серверный детектор движения | Декодирование субпотока, анализ по зонам | 2–3 ядра на 100 каналов | 1.0 |
| Примитивы на нейросети | Детектор объектов на Intel iGPU через OpenVINO | Ограничена бюджетом инференса, см. 9.3 | после 1.0 |
Приоритет всегда за событиями камеры: современные камеры детектируют движение и объекты лучше и бесплатнее для сервера. Серверный детектор — универсальный запасной вариант для устройств без собственной аналитики и способ получить единообразное поведение на разнородном парке.
9.2Серверный детектор движения
- Работает по субпотоку, приведённому к 320×240 и 5 кадрам в секунду. Декодирование — программное или через VAAPI/QSV на встроенном видеоядре.
- Сетка зон, накладываемая на кадр; для каждой зоны — независимая чувствительность, минимальный размер объекта и минимальная длительность движения.
- Маски игнорирования: деревья, дороги, экраны мониторов, зона отображения времени.
- Подавление ложных срабатываний: адаптивная модель фона, отсечение резких изменений освещённости, игнорирование смены день/ночь и переключения ИК-подсветки.
- Гистерезис: движение считается начавшимся после N последовательных кадров и завершившимся после M секунд покоя.
- Результат сохраняется покадрово в компактной форме — битовая маска активных ячеек сетки с временной меткой. Это основа умного поиска по архиву.
9.3Примитивы аналитики и бюджет инференса
Выбранный ускоритель — встроенное графическое ядро Intel (Quick Sync + OpenVINO). Это дёшево, не требует отдельной карты и не создаёт логистических проблем при поставке. Но у решения жёсткий потолок, который нужно зафиксировать в ТЗ, а не обнаружить на объекте.
| Задача | Ресурс iGPU | Реальная ёмкость |
|---|---|---|
| Декодирование субпотоков | Фиксированный блок Quick Sync, отдельный от исполнительных устройств | Все 100 каналов с большим запасом |
| Детекция движения | CPU, после аппаратного декодирования | Все 100 каналов, 2–3 ядра |
| Примитивы: линия, зона, оставленный предмет | Исполнительные устройства iGPU, модель класса YOLO-nano, INT8 | 10–15 каналов на UHD 770, 25–30 на Arc / Core Ultra, при 3 к/с на канал |
Примитивы реализуются после версии 1.0. Отсюда два обязательных требования:
- Аналитика назначается на выбранные камеры, а не на все. На объекте из 100 камер примитивы нужны на периметре, входах и складе — это 10–20 каналов, что укладывается в бюджет.
- Планировщик бюджета инференса. Система измеряет фактическую пропускную способность ускорителя при старте, показывает администратору остаток бюджета в кадрах в секунду и не позволяет включить аналитику сверх него, предлагая снизить частоту анализа. Молчаливая деградация до одного кадра в десять секунд недопустима: оператор будет считать, что аналитика работает.
Ёмкость в таблице — ориентир по поколению iGPU, а не гарантия. Фактический бюджет измеряется на конкретной модели процессора и фиксируется в паспорте конфигурации. Если по итогам замера примитивы понадобятся более чем на 30 каналах, единственный путь — дискретная карта или NPU, и это решение стоит принимать, когда появятся реальные объекты.
9.4Умный поиск по архиву
Оператор выделяет прямоугольник на кадре и задаёт интервал времени; система возвращает список моментов, когда в этой области было движение. Поиск идёт по сохранённым маскам движения, без повторного декодирования видео, поэтому сутки архива одной камеры обрабатываются за доли секунды. Это одна из самых востребованных функций в разборе инцидентов и обязательна для версии 1.0.
9.5События и реакции
Единая шина событий: движение, потеря связи с камерой, расфокусировка и засветка, перекрытие объектива, тревожный вход, вход или выход пользователя, ошибка диска, исчерпание места, срабатывание внешней системы. Для каждого типа настраиваются реакции:
- Начать запись указанных камер (не обязательно той, что сработала).
- Показать камеру на экране оператора и вывести звуковой сигнал.
- Перевести PTZ-камеру на пресет.
- Замкнуть релейный выход камеры или модуля ввода-вывода.
- Отправить уведомление: электронная почта, Telegram, вебхук в стороннюю систему.
- Пометить фрагмент архива защищённым от удаления.
10Клиент для Windows
10.1Решение по клиенту и его цена
Нативный клиент на Qt/C++ входит в версию 1.0. Вопрос был поставлен и закрыт заказчиком: браузерный клиент как временная замена не рассматривается. Раздел фиксирует последствия этого решения и меры, которые делают его выполнимым в одиночку.
Клиент добавляет третий технологический стек со своей сборкой, отладкой и упаковкой. При прежней оценке для человека-разработчика это отодвигало выручку почти на год; при фактическом темпе цена решения — дни, а не месяцы. Прототип сетки уже работает.
Компенсирующее сокращение — из версии 1.0 убирается просмотр видео в браузере. Строить два независимых просмотрщика в одиночку невозможно, и это удачный размен: веб-интерфейс сводится к администрированию (формы, таблицы, мастер добавления камер), где он дёшев, а весь просмотр идёт через нативный клиент. Побочная выгода — в версии 1.0 не нужны ни WebRTC-стек, ни LL-HLS: единственным видеотранспортом остаётся VSP, и подсистема раздачи упрощается вдвое.
10.2Меры снижения риска
Клиент — самый рискованный компонент проекта. Меры ниже входят в ТЗ, а не остаются на усмотрение разработчика.
| Мера | Обоснование |
|---|---|
| Прототип отрисовки прежде всей остальной работы над клиентом выполнено | 16 окон, аппаратный декод, реальное железо. Главная гипотеза проекта проверена до вложений в клиент: 25 ячеек дают 625 к/с при 51 % процессора без потерь |
| Qt Widgets, а не QML | Для плотного операторского интерфейса Widgets быстрее в разработке и предсказуемее по производительности. QML даёт выигрыш на анимированных интерфейсах, которых здесь нет |
| Один путь отрисовки: D3D11 | Никаких OpenGL и Vulkan «на всякий случай». Откат предусмотрен только для декодирования — на программное, не для рендера |
| Сетка и шкала времени — свои виджеты на QPainter | Композиция из стандартных виджетов на 64 ячейках и на шкале с сотнями интервалов ведёт себя плохо и отлаживается долго. Собственная отрисовка проще, чем борьба с чужой |
| Версия 1.0 — сетки до 16 каналов, один монитор | 25, 36 и 64 ячейки и мультимониторный режим добавляются после базовой сетки. Это порядок работ, а не отказ от требований 10.4 |
| FFmpeg напрямую, без обёрток | Промежуточные абстракции над декодером в одиночном проекте не окупаются: их пишут дольше, чем используют |
10.3Технологическая база нативного клиента
| Слой | Решение | Примечание |
|---|---|---|
| Каркас и интерфейс | Qt 6.6+, C++20 | LGPLv3 — только динамическая линковка, см. раздел 21 |
| Декодирование | D3D11VA через FFmpeg, откат на программный декодер | Аппаратное декодирование обязательно, иначе сетка 25+ каналов невозможна |
| Отрисовка | Direct3D 11, вывод NV12-текстур без копирования в системную память | Преобразование цветового пространства — на GPU |
| Транспорт | VSP поверх WSS, одно соединение на сервер | Мультиплексирование всех каналов сетки в один сокет |
| Поддерживаемые ОС | Windows 10 21H2+, Windows 11, Windows Server 2019+ | Только x64 |
10.4Раскладки и живой просмотр
- Готовые сетки: 1, 4, 6, 8, 9, 10, 13, 16, 20, 25, 36, 64 ячейки, включая несимметричные с одной увеличенной ячейкой.
- Произвольные раскладки: перетаскивание камер в ячейки, объединение соседних ячеек, свободное соотношение сторон.
- Именованные раскладки сохраняются на сервере и привязываются к пользователю или роли, а не к рабочей станции.
- Автолистание (карусель) с настраиваемым интервалом и списком раскладок.
- Мультимониторная работа: до 4 мониторов, независимые раскладки, полноэкранный режим на каждом, восстановление конфигурации при запуске.
- Автоматический выбор потока. Ключевое требование производительности: при более чем 9 видимых ячейках клиент запрашивает субпотоки, при разворачивании ячейки — основной поток. Порог настраивается. Невидимые ячейки (свёрнутое окно, другая вкладка) отписываются от потока полностью.
- Цифровое увеличение колесом мыши с перемещением области внутри кадра.
- Индикация состояния в каждой ячейке: имя камеры, признак записи, признак тревоги, частота кадров, битрейт, потеря связи.
Число одновременных сессий аппаратного декодирования ограничено драйвером: у потребительских GeForce исторически ограничивалось несколько десятков сессий NVDEC, у Intel Quick Sync жёсткого лимита нет, но производительность падает нелинейно. Клиент обязан отслеживать отказ создания сессии, автоматически откатываться на программное декодирование для части ячеек и явно показывать оператору, что сетка превысила возможности видеокарты, — вместо чёрных ячеек без объяснения.
10.5Работа с архивом
- Единая шкала времени с отдельной дорожкой на каждую камеру раскладки. Цветовое кодирование: непрерывная запись, запись по движению, тревога, отсутствие записи, потеря связи.
- Масштаб шкалы от суток до секунд, навигация колесом и перетаскиванием; календарь с подсветкой дней, где есть записи.
- Синхронный просмотр всех камер раскладки по одной временной позиции — обязательное требование для разбора инцидентов.
- Скорости воспроизведения ×1/16, ×1/8, ×1/4, ×1/2, ×1, ×2, ×4, ×8, ×16, ×32, ×64 вперёд и назад. На скоростях выше ×4 сервер отдаёт только опорные кадры.
- Покадровое перемещение вперёд и назад, точный переход по введённому времени.
- Умный поиск по движению в выделенной области (см. 9.4).
- Стоп-кадр: сохранение, печать, копирование в буфер обмена, увеличение фрагмента.
10.6Экспорт
| Формат | Назначение |
|---|---|
| MP4 (ремукс без перекодирования) | Основной формат передачи. Быстрый, открывается любым плеером |
| Защищённый контейнер + подпись | Передача в правоохранительные органы. Хеш SHA-256 и подпись Ed25519 на каждый фрагмент, проверка подлинности в штатном просмотрщике |
| AVI / MKV | Совместимость по требованию |
| Кадры JPEG, серия | Иллюстрации к отчёту |
| Портативный просмотрщик | Самораспаковывающийся архив: видео нескольких камер, плеер, шкала времени, проверка подписи. Не требует установки |
При экспорте накладывается настраиваемый штамп: имя камеры, дата и время, имя объекта, водяной знак. Многоканальный экспорт сохраняет синхронизацию каналов. Все операции экспорта фиксируются в аудите с указанием пользователя, камер и интервала.
10.7PTZ
Управление через ONVIF PTZ: панорама, наклон, зум, фокус, диафрагма. Управление мышью в кадре (перетаскивание, выделение области для наезда), джойстик по USB-HID, пресеты, туры по пресетам, автопатрулирование, парковка по таймауту, приоритеты доступа между операторами.
10.8Прочие требования к клиенту
- Подключение к нескольким серверам одновременно с единым деревом камер. v1.5
- Дерево камер с группировкой по объектам, зданиям и этажам, поиск по названию, избранное.
- Планы помещений с расстановкой камер, переход к камере по клику на плане.
- Панель тревог: список активных событий, переход к моменту в архиве одним действием, квитирование оператором с комментарием.
- Настраиваемые горячие клавиши, работа без мыши для основных операций.
- Двусторонняя аудиосвязь через камеры с аудиовыходом.
- Автообновление клиента с сервера, тихая установка через MSI и групповые политики, потребление не более 500 МБ RAM при сетке 16 каналов.
11Веб-интерфейс
В версии 1.0 веб-интерфейс — инструмент администрирования, а не просмотра. Весь просмотр видео идёт через нативный клиент (10.1). Это сознательное сокращение: два независимых просмотрщика в одиночку не строятся, а формы и таблицы в вебе обходятся дёшево.
11.1Состав версии 1.0
- Мастер добавления камер на базе автообнаружения (6.5–6.7): сканирование сети, список найденных устройств с моделью и состоянием, массовое применение учётных данных, стоп-кадр для проверки, добавление пакетом.
- Настройка камер, профилей, расписаний, зон детекции, реакций на события — экраны генерируются из реестра параметров (5.7).
- Управление пулами хранения, квотами и ретеншном; прогноз глубины архива по фактическому битрейту.
- Пользователи, роли, права; журнал аудита с фильтрами.
- Мониторинг: состояние каналов, загрузка процессора и дисков, сетевой трафик, SMART, история недоступности камер.
- Стоп-кадр с камеры для диагностики — единственная работа с изображением в версии 1.0.
11.2Отложено
Живой просмотр и воспроизведение архива в браузере реализованы — через fMP4 и MSE, без WebRTC. Отложены: экспорт фрагментов из браузера, планы помещений, панель тревог. WebRTC и LL-HLS не реализуются вовсе, пока задержка около секунды устраивает: они дороже в поддержке и ничего не добавляют для настройки.
Стек: TypeScript, React, сборка в статику, отдаётся тем же сервером. Отдельного Node-процесса в поставке нет.
12Модель данных
PostgreSQL 16. Конфигурация и метаданные — в БД; медиаданные — в файловой системе. БД должна пережить потерю архива и наоборот.
| Сущность | Ключевые поля | Оценка объёма |
|---|---|---|
cameras | uuid, название, группа, адрес, учётные данные (шифрованные), vendor, model, профиль поправок, состояние | 100 |
streams | camera_id, роль (main/sub), URI, кодек, разрешение, fps, измеренный битрейт | 200 |
storage_pools | путь, квота, резерв, приоритет, состояние | < 20 |
segments | camera_id, pool_id, начало, конец, путь, размер, число кадров, флаг защиты | ~865 тыс. / 30 сут |
events | тип, camera_id, время начала и конца, метаданные (JSONB), квитирование | млн, партиции по неделям |
motion_masks | camera_id, время, битовая маска ячеек | хранится файлами рядом с сегментом |
schedules, rules | недельная сетка, условия, реакции | сотни |
users, roles, permissions | учётные записи, роли, права на камеры и действия | сотни |
layouts | владелец, сетка, расстановка камер | сотни |
audit_log | пользователь, действие, объект, IP, время, результат | млн, партиции по месяцам |
licenses | подпись, число каналов, срок, привязка к оборудованию | единицы |
Таблица segments — самая нагруженная на запись: около 20 тысяч вставок в сутки при 100 каналах. Индексы: (camera_id, ts_start) BRIN для диапазонных запросов и B-tree для точечных. Партиционирование по месяцам, старые партиции отцепляются вместе с удалением файлов.
13Программный интерфейс
Один публичный API, которым пользуются и веб-интерфейс, и нативный клиент, и интеграторы. Внутренних привилегированных путей в обход API нет.
| Раздел | Содержание |
|---|---|
/api/v1/auth | Вход, обновление токена, выход, двухфакторная аутентификация |
/api/v1/discovery | Запуск сканирования, статус, найденные устройства, проба потока, добавление пакетом |
/api/v1/cameras | CRUD камер и потоков, состояние, снимок текущего кадра, перепроверка параметров |
/api/v1/ptz | Команды перемещения, пресеты, туры |
/api/v1/archive | Наличие записей по интервалу (для шкалы), список сегментов, выдача сегмента, задание на экспорт |
/api/v1/events | Поиск событий, подписка через SSE, квитирование, умный поиск по движению |
/api/v1/storage | Пулы, заполнение, прогноз глубины, состояние дисков |
/api/v1/system | Здоровье, метрики, лицензия, версия, резервное копирование конфигурации |
/stream/vsp | WebSocket: живое видео и архив для нативного клиента |
/stream/webrtc | WHEP-совместимая точка входа для браузера |
/metrics | Метрики в формате Prometheus |
Версионирование в пути URL, обратная совместимость в пределах мажорной версии. gRPC-вариант того же API — для высокочастотных вызовов и внутреннего взаимодействия узлов в версии 1.5. Ограничение частоты запросов и постраничная выдача обязательны для всех списочных методов.
14Пользователи, права, аудит
- Ролевая модель. Предустановленные роли: администратор, инженер, старший оператор, оператор, наблюдатель. Роли редактируемы, число не ограничено.
- Гранулярность прав — по камере или группе камер и по действию: живой просмотр, просмотр архива, экспорт, PTZ, удаление записей, изменение конфигурации, управление пользователями.
- Отдельное право на экспорт и отдельное на просмотр архива глубже N суток — типовое требование службы безопасности.
- Аутентификация: локальные учётные записи с Argon2id, LDAP и Active Directory, двухфакторная аутентификация TOTP для административных ролей.
- Политики: сложность пароля, срок действия, блокировка после неудачных попыток, ограничение одновременных сессий, автоотключение по бездействию.
- Аудит фиксирует: вход и выход, просмотр архива (какая камера, какой интервал), экспорт, изменение конфигурации, удаление записей, изменение прав. Журнал недоступен для изменения из интерфейса и выгружается для внешнего анализа.
- Пароли камер хранятся зашифрованными AES-256-GCM на ключе сервера и никогда не возвращаются через API в открытом виде.
15Лицензирование продукта
Единица лицензирования — канал (одна камера независимо от числа её потоков). Базовый сервер поставляется с некоторым числом каналов, расширения докупаются.
| Механизм | Реализация |
|---|---|
| Формат лицензии | Подписанный Ed25519 файл: число каналов, набор функций, срок поддержки, привязка |
| Привязка | Отпечаток оборудования: серийные номера дисков и материнской платы, MAC. Устойчив к замене одного компонента |
| Активация | Офлайн (обмен файлами) и онлайн через сервер активации. Офлайн обязателен — объекты часто без интернета |
| Аппаратный ключ | Опциональный USB-ключ для перенос лицензии между серверами v1.2 |
| Поведение при превышении | Каналы сверх лимита не подключаются, но уже работающие продолжают писать. Аварийная остановка записи из-за лицензии недопустима |
| Демо-режим | Полный функционал, 8 каналов, 30 суток |
| Обновления | Функциональные обновления в пределах срока поддержки; по истечении ПО продолжает работать на последней доступной версии |
Модель монетизации — бессрочная лицензия на канал, подписка или лицензия на сервер — определяет и техническую реализацию, и требования к серверу активации. До ответа раздел описывает наиболее распространённую на рынке модель: бессрочная лицензия на канал плюс платный период обновлений.
16Нефункциональные требования
| Показатель | Целевое значение |
|---|---|
| Задержка живого просмотра в локальной сети (VSP) | ≤ 300 мс |
| Задержка живого просмотра в браузере (WebRTC) | ≤ 500 мс |
| Время до появления первого кадра при открытии камеры | ≤ 500 мс |
| Время отклика при перемотке архива | ≤ 1 с |
| Потеря записи при штатной работе | 0 кадров |
| Потеря записи при перезапуске службы | ≤ 2 с на канал |
| Восстановление связи с камерой после сбоя сети | ≤ 5 с |
| Выход сервера на полную запись 100 каналов после старта | ≤ 60 с |
| Доступность службы записи | 99,9 % в месяц |
| Время отклика API, 95-й перцентиль | ≤ 200 мс |
| Клиент: сетка 16 каналов, потребление RAM 1.0 | ≤ 500 МБ |
| Клиент: сетка 16 каналов, загрузка CPU | ≤ 25 % на 4-ядерном ПК |
| Непрерывная работа сервера без перезапуска | ≥ 90 суток |
Показатели набираются поэтапно: 30 каналов, затем 50, затем 100. Требования к задержкам и потерям записи действуют с первого дня в полном объёме — их нельзя «донастроить позже», это свойства архитектуры, а не оптимизация.
Приёмочное испытание — 72 часа непрерывной записи 100 реальных каналов с четырьмя подключёнными операторами, имитацией обрывов сети, отключением диска и перезагрузкой камер. Все показатели таблицы проверяются на этом стенде, а не по отдельности. Испытание выполняется на нагрузочном эмуляторе (19.5), потому что реального объекта на 100 камер к этому моменту может не быть.
17Развёртывание и эксплуатация
- Целевые ОС: Ubuntu 22.04 и 24.04 LTS, Debian 12 — базовые; Астра Linux Special Edition и РЕД ОС — обязательные для реестра и госсектора (Q28). Четыре сборочные цели в CI и четыре стенда проверки. Астра и РЕД ОС отстают по версиям системных библиотек, поэтому сервер собирается со статической линковкой всего, кроме FFmpeg, который остаётся динамическим по требованиям LGPL.
- Поставка: пакеты deb и rpm, служба systemd, отдельный системный пользователь без прав root. Конфигурация в
/etc/perimetr, состояние в/var/lib/perimetr, архив — только в объявленных пулах. - Установка в один шаг: пакет ставит зависимости, создаёт базу, поднимает службу, открывает мастер первичной настройки в браузере.
- Обновление без длительного простоя записи: новая версия стартует, принимает соединения с камерами и только затем гасит старую. Допустимый разрыв записи — 30 с.
- Резервное копирование конфигурации и БД по расписанию, восстановление на чистый сервер с подключением существующих пулов архива.
- Логи структурированные, в journald и в файл с ротацией. Уровень детализации переключается без перезапуска.
- Метрики в формате Prometheus, готовый дашборд Grafana: состояние каналов, битрейты, глубина архива, свободное место, ошибки.
- Диагностический архив одной кнопкой: логи, конфигурация без паролей, состояние камер и дисков, последние события. Обязательная функция — от неё напрямую зависит стоимость поддержки объектов.
- Docker-образ поставляется для тестовых стендов. Для продуктива не рекомендуется: пробрасывание дисков, multicast-обнаружение и производительность сети в контейнере создают проблемы, несоразмерные выгоде.
18Правовые требования
Раздел фиксирует требования, влияющие на архитектуру. Он не заменяет юридическую экспертизу — перед выпуском на рынок нужна проверка юристом по выбранным юрисдикциям (см. Q1).
- Видеозапись людей — персональные данные. Система обязана поддерживать заданный срок хранения и его гарантированное истечение, а не бесконечное накопление.
- Журнал доступа к архиву — кто, когда, какую камеру и какой интервал смотрел и выгружал. Требование практически всех регуляторов и главный аргумент при проверках.
- Распознавание лиц переводит обработку в категорию биометрических данных с существенно более строгими требованиями к согласию и хранению. Это дополнительный довод вынести распознавание за пределы версии 1.0 и сделать его отдельно лицензируемым модулем.
- При продаже в ЕС — GDPR: оценка воздействия на защиту данных, обоснованный срок хранения, процедура удаления по обращению, документированное шифрование.
- При продаже в РФ подтверждено требование включения в реестр отечественного ПО (Q34). Это накладывает обязательства уже на этапе разработки: российский правообладатель, отсутствие в составе продукта компонентов из недружественных юрисдикций в качестве неотделимой части, документация по ГОСТ 19 и ГОСТ 34, размещение исходного кода и сборки на территории РФ. Сертификация ФСТЭК на текущем этапе не требуется, но архитектура подсистемы безопасности раздела 14 закладывается так, чтобы она стала возможной без переписывания.
- Продажи одновременно в РФ и за рубежом означают два комплекта требований, а не выбор между ними: 152-ФЗ и GDPR, два языка интерфейса и документации с первого релиза, две редакции политики хранения. Проще всего это решается настройкой профиля соответствия на уровне объекта, а не двумя ветками продукта.
19Ход работ и то, что не сжимается
В редакциях 0.3 и 1.0 сроки считались для человека-разработчика в одиночку — 24 месяца. Разработку ведёт ИИ-агент под контролем заказчика, и календарь сжимается на порядок: объём, отведённый под фазы Ф0 и Ф1, закрыт за одну рабочую сессию. Оценки в месяцах из документа убраны как вводящие в заблуждение.
Сжимается скорость написания и отладки кода. Не сжимается всё, что упирается в физическое время и чужие процессы — этому посвящён подраздел 19.3, и именно он теперь определяет срок выпуска.
19.1Что уже работает
| Подсистема | Состояние | Чем подтверждено |
|---|---|---|
| Реестр параметров, наследование настроек | работает | 22 параметра, экраны настроек генерируются из реестра, значения вне диапазона отвергаются |
| База: схема, секции, миграции | работает | 25 таблиц, помесячные секции назад и вперёд |
| Приём RTSP, восстановление шкалы времени | работает | 25,00 к/с на канал; скачки меток на 7 с восстановлены без сдвига частоты |
| Эмулятор камер с дефектами прошивок | работает | 5 дефектов, заглушка ONVIF, ответчик WS-Discovery |
| Архив: fMP4-сегменты и индекс по опорным кадрам | работает | читается сторонним декодером, экспорт ремуксом 67 с за 40 мс |
| Раздача видео: VSP и fMP4 для браузера | работает | один сокет на всю сетку |
| Клиент Qt: сетка живого видео | прототип | 25 ячеек, 625 к/с, 51 % процессора, потерь нет |
| Веб-интерфейс: просмотр, архив, камеры, настройки | работает | живое видео и воспроизведение архива в браузере |
| Автообнаружение камер | работает | WS-Discovery, скан подсети, ONVIF, справочник на 13 вендоров |
| Ретеншн | работает | удаление по глубине и вытеснение по месту, защищённые записи сохраняются |
19.2Что осталось до полного прототипа
| Работа | Зависимость |
|---|---|
| Детектор движения по субпотоку, зоны, умный поиск | Декодирование через FFmpeg на сервере |
| Расписания записи, события и реакции | Нет внешних зависимостей |
| Пользователи, роли, права, журнал аудита | Нет внешних зависимостей |
| PTZ через ONVIF | Нужна камера с поворотным механизмом для проверки |
| Экспорт фрагментов с подписью | Нет внешних зависимостей |
| Лицензирование, инсталляторы, документация | Нет внешних зависимостей |
| Клиент Qt: шкала архива, экспорт, раскладки, мультимонитор | Проверка пути D3D11VA требует машины с Windows |
19.3Что не сжимается независимо от темпа разработки
Ниже — работы, срок которых определяется не скоростью написания кода. Именно они, а не объём программирования, задают дату выпуска.
| Работа | Что ограничивает | Порядок срока |
|---|---|---|
| База поправок под дефекты прошивок | Нужны физические камеры разных платформ. Эмулятор воспроизводит только уже известные дефекты; новые обнаруживаются на реальном устройстве | непрерывно, по мере появления камер |
| Проверка пути D3D11VA | Требуется машина с Windows и дискретным либо встроенным видеоядром. На macOS проверен только архитектурно эквивалентный путь VideoToolbox | дни после появления машины |
| 72-часовое приёмочное испытание | Физическое время: трое суток непрерывной записи ста каналов | 3 суток на прогон, плюс повторы после правок |
| Пилотный объект в эксплуатации | Реальные обрывы сети, заполнение дисков и жалобы оператора накапливаются только со временем | недели |
| Реестр отечественного ПО | Внешняя процедура: подача, рассмотрение, замечания. Скорость разработки на неё не влияет | месяцы |
| Патентная экспертиза по H.264/H.265 | Работа патентного юриста | недели |
Программная часть версии 1.0 достижима за срок, измеряемый днями и неделями. Дата, с которой продукт можно продавать, определяется закупкой стенда камер, машиной с Windows и трёхсуточным испытанием. Всё это стоит запускать параллельно с разработкой, а не после неё.
19.4Правила разработки
Ограничения ниже — часть технического задания. Они не про скорость, а про то, что отличает работающий продукт от демонстрации.
- Не писать своё там, где есть проверенное. RTSP-стек, база данных, декодер, каркас интерфейса берутся готовыми. Исключение делается осознанно: разбор ответов ONVIF написан свой, потому что строгое сопоставление со схемой ломается на реальных камерах.
- Контракт VSP и REST фиксируется и дальше только расширяется. Сервер, нативный клиент и веб-интерфейс разрабатываются в разное время; менять протокол задним числом значит переделывать все стороны.
- Экраны настроек генерируются из реестра параметров (5.7). Иначе требование полной конфигурируемости превращается в полторы сотни рукописных экранов.
- Каждый закрытый дефект прошивки становится тестом навсегда. Эмулятор обязан уметь воспроизвести его по команде.
- Ничто не считается работающим без проверки. Замер, снимок экрана или прогон стороннего декодера — но не рассуждение о том, что код выглядит правильным.
- Свой объект в эксплуатации как можно раньше. Он даёт то, чего не даст стенд.
19.5Стенд оборудования и эмуляция камер
На старте доступны 1–2 камеры. Этого достаточно для базового приёма RTSP, но принципиально недостаточно для базы профилей вендоров и поправок под дефекты прошивок (6.8) — а именно она определяет, будет ли продукт «подключать любую камеру» или «подключать те камеры, что были у разработчика». План закрытия этого разрыва:
- Закупка стенда. 8–10 устройств разных платформ: Hikvision, Dahua, один OEM на платформе Dahua, Axis, Hanwha, Uniview, Reolink, Beward, плюс один регистратор и одна PTZ-камера с аудио. Порядок затрат сопоставим с месяцем работы одного разработчика и окупается на первом же объекте с незнакомым парком.
- Библиотека отпечатков. С каждой встреченной камеры — на стенде, у партнёра, на объекте заказчика — сохраняется полный отпечаток: ответы ONVIF
GetDeviceInformationиGetProfiles, SDP изDESCRIBE, HTTP-заголовки, первые 30 секунд потока. Отпечатки складываются в репозиторий тестов. Это главный способ наращивать базу поправок, не владея камерами физически, и он должен работать с первого дня, а не появиться после жалоб с объектов. - Эмулятор камер. Собственный RTSP-сервер на gortsplib, проигрывающий записанные потоки, и ONVIF-заглушка, отвечающая по сохранённым отпечаткам. Обязательно воспроизводит дефекты прошивок: SPS только в SDP, скачки временных меток, разрыв сессии по таймауту, несовпадение объявленного и фактического кодека, фантомный аудиотрек, ONVIF на нестандартном порту.
- Нагрузочный эмулятор. Вариант эмулятора, поднимающий 100 потоков с одной машины. Без него приёмочное испытание раздела 16 нельзя провести до появления реального объекта, а значит нельзя и подтвердить целевые показатели перед продажей.
- Сбор с объектов. Кнопка «сообщить о несовместимой камере» в интерфейсе: собирает отпечаток, вырезает учётные данные и передаёт разработчику с согласия администратора. Каждая такая заявка пополняет базу профилей и закрывается обновлением справочника, а не новой версией сервера.
Пока стенда нет, работа идёт на эмуляторах и двух имеющихся камерах. Реальная совместимость при этом не проверяется, и риск переносится прямо в момент первых продаж, где его цена максимальна. Закупка стенда — самая дешёвая из возможных страховок срока и единственное, что нельзя ускорить темпом разработки.
Самые частые причины срыва сроков — не архитектура, а разнородность камер: работа растягивается на каждой новой партии устройств. Второй по величине риск для одиночной разработки — расползание объёма: каждая «маленькая полезная функция» стоит недели, которой нет. Раздел 19.1 существует именно для того, чтобы отказы были приняты заранее и письменно, а не под давлением первого же заказчика.
20Вопросы к заказчику
Ответы на эти вопросы уточняют разделы выше. Отмеченные блок нужны до начала разработки — без них решения принимаются вслепую и переделываются. Отмеченные отвечено учтены в редакции 0.3. Все вопросы закрыты, включая решение по клиенту (10.1). Документ переведён в редакцию 1.0.
A. Продукт и рынок
B. Объект и нагрузка
C. Камеры и сеть
D. Функциональность
E. Инфраструктура и эксплуатация
21Стек и лицензионная чистота
| Компонент | Роль | Лицензия | Условие использования |
|---|---|---|---|
| Go 1.23+ | Ядро сервера | BSD-3 | Без ограничений |
| gortsplib | RTSP-клиент и сервер | MIT | Без ограничений |
| pion/webrtc | WebRTC-раздача | MIT | Без ограничений |
| pgx | Драйвер PostgreSQL | MIT | Без ограничений |
| PostgreSQL 16 | Хранение конфигурации и метаданных | PostgreSQL License | Без ограничений |
| FFmpeg (libavcodec) | Декодирование субпотока, ремукс при экспорте | LGPL 2.1 | Сборка без --enable-gpl и --enable-nonfree, только динамическая линковка |
| Qt 6 | Каркас клиента Windows | LGPLv3 | Только динамическая линковка, публикация сведений о версии и возможность замены библиотеки пользователем |
| React, TypeScript | Веб-интерфейс | MIT / Apache 2.0 | Без ограничений |
1. Сборка FFmpeg. Кодировщики x264 и x265 распространяются под GPL. Их включение делает GPL всю сборку и несовместимо с проприетарным продуктом. Так как сервер по проекту не перекодирует видео, они не нужны — но сборочный конвейер должен явно это гарантировать, а не полагаться на дисциплину разработчиков.
2. Патенты на кодеки. H.264 и H.265 покрыты патентными пулами (Via LA, Access Advance). Распространение коммерческого ПО с декодером может требовать отчислений — для H.265 они выше и пулов несколько. Свободная лицензия FFmpeg не освобождает от патентных обязательств. Вопрос требует консультации патентного юриста до начала продаж, а не после.
Альтернатива для Qt — коммерческая лицензия The Qt Company: снимает требования LGPL, но стоит заметных денег на разработчика в год. Поскольку клиент входит в версию 1.0, вопрос лицензии Qt решается до выпуска клиента — и решается в пользу LGPL, см. ниже.
21.1Требования реестра отечественного ПО к составу
- Свободные компоненты из таблицы выше не мешают включению в реестр: использование open-source допускается, ограничения касаются проприетарных зависимостей и исключительных прав.
- Исключительное право на продукт должно принадлежать российскому лицу, а выплаты правообладателям за рубеж не должны превышать установленной доли выручки. Отсюда практический вывод: коммерческая лицензия Qt создаёт риск для заявки, а LGPL-вариант — нет.
- Требуется комплект документации по ГОСТ 19 и ГОСТ 34: описание применения, руководства пользователя и администратора, описание процессов разработки и поддержки. Готовится параллельно с разработкой и составляет заметную долю общей трудоёмкости.
- Сборка и репозиторий исходного кода размещаются на инфраструктуре в РФ. Это решение принимается как можно раньше: переезд репозитория с историей позже — отдельная работа.