.. _video_tag: Видеопоток (тег типа 6) ^^^^^^^^^^^^^^^^^^^^^^^ Как завести камеру в конфигураторе, описано в :ref:`video_cameras`. Ниже — контракт чтения, архива и управления. Тег с ``prsValueTypeCode = 6`` — окно в камеру, а не ряд чисел. Кадры не пишутся в RabbitMQ, VictoriaMetrics и PostgreSQL. Камера заводится как коннектор с адресом потока. Каталог архива, срок хранения, ширина и частота кадров задаются у хранилища данных типа ``3`` (``archivePath``, ``retentionHours``, ``archiveWidth``, ``archiveFps``). Тег привязывают и к коннектору, и к этому хранилищу. Новых атрибутов LDAP для этого нет. Пример конфигурации коннектора: .. code-block:: json { "source": { "rtspUrl": "rtsp://192.168.1.72:554/live/ch00_0", "rtspTransport": "tcp", "onvifPort": 8899, "onvifUser": "", "onvifPassword": "" }, "log": { "level": "INFO", "fileName": "logs/prs_connector_{id}.log", "maxBytes": 10485760, "backupCount": 10, "sendToPlatform": false } } Зона распознавания человека задаётся на этом же экране, поверх картинки. Переход на тег другого типа сразу убирает блок видео, не дожидаясь ответа сервера. Сейчас на экране одна зона. Кнопка **Зона** включает правку и остаётся подсвеченной, пока правка включена. Остальные кнопки блока на мгновение загораются жёлтым, чтобы было видно нажатие. Углы ставятся кликами по картинке. Клик по жёлтой линии добавляет вершину на эту линию. **Шаг назад** снимает последнюю точку. **Удалить зону** убирает многоугольник. Контур не выходит за границы картинки. Справа снизу у блока видео есть ручка: потяните её, чтобы изменить размер. **Записать** сохраняет зону в ``prsJsonConfigString`` тега ключом ``zones``. Каждая координата — доля кадра от 0 до 1, ноль слева и сверху. ``zones`` — массив многоугольников, каждый многоугольник сам массив точек ``[x, y]``: .. code-block:: json {"zones": [[[0.1, 0.2], [0.4, 0.2], [0.4, 0.8]]]} Сейчас в массиве одна зона. Пустой ``zones`` означает весь кадр. **Весь кадр** как раз записывает пустой список. Если раньше было записано несколько многоугольников, на экране показывается первый, и следующая запись оставляет только его. Старый конверт ``{"zone": {"zones": [...]}}`` при чтении ещё понимается, а запись уже кладёт массив в корень. Человек ищется в прямоугольнике вокруг зоны: он равномерно увеличивается до входа сети 640×640, пропорции фигуры сохраняются. Края прямоугольника чуть шире многоугольника, чтобы человека на границе не разрезало. Человек считается в зоне, если его рамка пересекает этот многоугольник. Пустая зона по-прежнему означает весь кадр. Метод «Человек в зоне» попадает в каталог «Методы» командой «Загрузка описания» из ``methodDescription.yaml`` проекта видеометодов. На теге хранится ссылка на него. Многоугольники метод не хранит: параметр ``zone`` — запрос к платформе ``prsTag.api_crud.read.*`` за атрибутом ``prsJsonConfigString`` этого тега, а JSONata ``$eval(data[0].attributes.prsJsonConfigString[0]).zones`` отдаёт в метод массив ``zones``. ``source.rtspUrl`` обязателен и должен быть адресом ``rtsp://`` или ``rtsps://``. Наличие этого ключа и делает коннектор камерой. Тот же ключ в корне JSON тоже принимается. Ключ ``log`` совпадает с журналом коннектора: ``level``, ``fileName``, ``maxBytes``, ``backupCount`` и флажок ``sendToPlatform``. Архив пишется в ``/``. Каталог вне тома ``/var/lib/peresvet/video`` пропадёт вместе с контейнером. ``retentionHours`` у хранилища — срок хранения в часах; если ключ опущен, берётся 24. ``archiveWidth`` и ``archiveFps`` тоже у хранилища: ширина архива в пикселях (чётное число, высота подстраивается) и частота кадров. ``null`` или пустое значение означает ширину и частоту камеры, поток копируется. Пустые ``onvifUser`` и ``onvifPassword`` означают, что камера логин не требует. Транспорт по умолчанию TCP. Его можно задать ключом ``rtspTransport`` со значением ``tcp`` или ``udp``. Управление камерой идёт по OnVif, отдельным запросом, без второго подключения RTSP. Хост берётся из ``rtspUrl``, порт по умолчанию 8899 (ключ ``onvifPort``). Если камера требует логин, его задают ключами ``onvifUser`` и ``onvifPassword``. В блоке «Данные тега» кнопки стоят слева от картинки. Стрелки двигают камеру, пока их держат. «Ближе» и «Дальше» делают один шаг зума. «Стоп» останавливает поворот и наклон сразу. «Домой» возвращает камеру по уже сделанным с этой страницы движениям и снимает накопленный зум: сама камера положение не запоминает. Под стрелками камера показывает параметры изображения, которые сама отдаёт по OnVif: яркость, контраст, насыщенность, резкость, засветка, динамический диапазон, ИК-фильтр (день, ночь, авто) и баланс белого. Ползунок или список отправляет на камеру только изменённый параметр. Камера может ответить успехом и при этом не изменить кадр: прошивка принимает зум и параметры изображения, сохраняет числа и не применяет их к объективу. Поворот и наклон при этом могут работать. Снаружи конфигуратора то же управление — ``POST /v1/ptz/``, тело JSON. Обязателен ``tagId`` тега видеопотока. Поле ``action``: * ``status`` — профиль, ``pan``, ``tilt``, ``zoom`` и список пресетов. То же делает ``GET /v1/ptz/?tagId=``. * ``move`` — непрерывный поворот, пока не придёт ``stop`` или не истекут 8 секунд таймаута команды. ``pan``, ``tilt`` и ``zoom`` от −1 до 1. Если камера объявляет свою шкалу скорости выше 1, перед первым поворотом платформа поднимает её скорость до этого максимума: иначе команда доходит сразу, а объектив ползёт. Повтор той же команды, пока поворот уже идёт, на камеру не отправляется. * ``step`` — один относительный сдвиг с теми же тремя полями. * ``pulse`` — шаг зума. Знак ``zoom`` задаёт направление, на камеру уходит ±1. * ``stop`` — остановить текущий поворот и наклон. * ``home`` — пройти назад движения, посланные с момента старта сервиса подхвата, затем вызвать домашнее положение камеры. * ``preset`` — перейти к пресету, поле ``token`` или ``preset``. * ``image`` — текущие параметры изображения и допустимые значения. * ``image_set`` — записать параметры: ``brightness``, ``contrast``, ``saturation``, ``sharpness`` (числа), ``backlight`` и ``wideDynamicRange`` (``ON`` или ``OFF``), ``irCut`` (``ON``, ``OFF``, ``AUTO``), ``whiteBalance`` (``AUTO`` или ``MANUAL``). Ошибка управления приходит тем же JSON ``error.code`` и ``error.message``. Чужой тег — 422, выключенный тег — 409, тег без камеры — 424, камера отклонила команду — 502. Тег типа «Видеопоток» привязывается к этому коннектору на вкладке коннектора и не кладётся в хранилище истории. Чтение ______ ``GET /v1/data/?tagId=`` для такого тега отдаёт не JSON-точки, а медиа: * без ``start`` и ``finish`` — живой поток WebRTC (один H.264 на всех зрителей); * только ``finish`` — снимок ``image/jpeg`` на этот момент; если фрагмента на это время нет, ответ ``404`` без картинки; * ``start`` и ``finish`` — фрагмент ``video/mp4`` за период. Ключи ``timeStep`` и ``count`` для видеопотока пока не поддерживаются. На одну камеру держится один сеанс RTSP в контейнере подхвата ``prs-video-capture``. Этот сеанс копирует поток камеры в архив, если хранилище не задало ширину или частоту, и один раз кодирует H.264 для живого просмотра. Смотрящих может быть несколько, картинка при этом не кодируется заново: платформа проверяет право чтения тега, по RPC находит сервис отдачи и проксирует запрос по HTTP. Отдача так же находит подхват и забирает у него байты. Клиент к камере не подключается. В RabbitMQ уходит только идентификатор и базовый URL процесса, не кадры. Распознавание берёт последний кадр этого сеанса (``/internal/video//frame``), а не открывает запись отдельным ffmpeg. Снимок на прошлый момент и фрагмент за период собираются из архива и могут занять время. В конфигураторе живой поток открывается в ``