Skip to content

Аналитика камеры через API

Вкладка Аналитика работает через запрос central POST /central/api-v4/streams/{stream}/onvif-call/analytics/{method}. Тот же запрос использует внешняя система. Central передаёт вызов стримеру, который принимает видео камеры, а стример — камере.

Перед началом

Запрос доступен ролям superadmin и admin. Стрим должен быть запущен, а камера подготовлена, как описано в разделе Подготовка стрима. Для примеров нужны Bash, curl и jq. Ответы в примерах получены от камеры Optimus; набор типов и параметров у другой камеры свой.

export CENTRAL_URL='https://central.example.com'
export API_LOGIN='admin'
export API_PASSWORD='your-password'
export STREAM='entrance'
analytics() {
  curl --fail-with-body --silent --show-error \
    --user "$API_LOGIN:$API_PASSWORD" \
    --header 'Content-Type: application/json' \
    --data "$2" \
    "$CENTRAL_URL/central/api-v4/streams/$STREAM/onvif-call/analytics/$1"
}

Имя стрима со слэшем передаётся в кодированном виде: cams%2Fentrance.

Методы

Имена и тела методов повторяют сервис ONVIF Analytics, записанный в JSON. Атрибуты XML передаются с префиксом $, токен конфигурации аналитики Optic подставляет сам.

  • GetSupportedRules — типы правил камеры, их число и несовместимые сценарии.
  • GetRuleOptions — пределы параметров правила.
  • GetRules — правила камеры.
  • CreateRules, ModifyRules, DeleteRules — создание, изменение и удаление правил.
  • GetServiceCapabilities — что поддерживает сервис аналитики камеры.
  • GetSupportedAnalyticsModules, GetAnalyticsModuleOptions, GetAnalyticsModules, ModifyAnalyticsModules — модули аналитики, например сетка и чувствительность детектора движения.

Другие методы записи отвергаются с кодом unsupported_method. Каждая попытка записи правил попадает в журнал аудита central с действием stream_onvif.rules_write.

Возможности камеры

Типы правил, их предельное число и несовместимые сценарии:

analytics GetSupportedRules '{}' | jq '.SupportedRules.RuleDescription[]
  | {type: ."$Name", max: ."$maxInstances", excludes: .Extension.Excludes}'
{"type":"tt:LineDetector","max":"4","excludes":["tt:LineCounting","tt:ObjectAbandoned","tt:ObjectRemoved","cus:CrowdDetector","cus:QueueDetector","tt:ObjectDetection","tt:LicensePlateRecognition"]}

Пределы параметров одного типа:

analytics GetRuleOptions '{"RuleType":"tt:LineDetector"}' | jq '.RuleOptions'
[{"$Name":"Direction","$RuleType":"tt:LineDetector","StringList":"Right Left Any"},
 {"$MaxItems":"3","$Name":"ClassFilter","$RuleType":"tt:LineDetector","StringList":"Human Vehicle NonMotorVehicle"},
 {"$Name":"Sensitivity","$RuleType":"tt:LineDetector","IntRange":{"Max":"100","Min":"1"}}]

Возможности камеры стример держит в памяти. Чтобы прочитать их с камеры заново, например после обновления прошивки, добавьте заголовок x-onvif-fresh: true.

Чтение правил

analytics GetRules '{}' | jq

В ответе Extension.Executor называет исполнителя: optimus для адаптера Optimus, camera для стандартного ONVIF. Extension.Clock.UtcOffsetMinutes — смещение часов камеры от UTC, в этих часах задаётся расписание.

Создание, изменение и удаление

Создайте линию. Имя правила <тип>_<номер> назначается при создании и возвращается в RuleName:

analytics CreateRules '{"Rule":[{"$Type":"tt:LineDetector","Parameters":{
  "SimpleItem":[{"$Name":"Armed","$Value":"false"},{"$Name":"Direction","$Value":"Any"}],
  "ElementItem":[{"$Name":"Segments","Polyline":{"Point":[{"$x":-0.5,"$y":0},{"$x":0.5,"$y":0}]}}]}}]}'
{"Extension":{"Executor":"optimus","NotApplied":[]},"RuleName":["LineDetector_2"]}

Поставьте линию на охрану с расписанием по будням с 9 до 14:

analytics ModifyRules '{"Rule":[{"$Name":"LineDetector_2","$Type":"tt:LineDetector","Parameters":{
  "SimpleItem":[{"$Name":"Armed","$Value":"true"}],
  "ElementItem":[{"$Name":"Schedule","HourSchedule":{
    "Mon":[[9,14]],"Tue":[[9,14]],"Wed":[[9,14]],"Thu":[[9,14]],"Fri":[[9,14]],"Sat":[],"Sun":[]}}]}}]}'

Если камера объявила несовместимые сценарии (Extension.Excludes) и окно пересекается с одним из них, запись отвергается: ответ — 422 schedule_overlap, см. Ошибки.

Удалите линию:

analytics DeleteRules '{"RuleName":["LineDetector_2"]}'

Чувствительность детектора движения задаётся в модуле аналитики:

analytics ModifyAnalyticsModules '{"AnalyticsModule":[{"$Name":"CellMotionEngine_1","$Type":"tt:CellMotionEngine",
  "Parameters":{"SimpleItem":[{"$Name":"Sensitivity","$Value":"6"}]}}]}'

Правила записи:

  • Координаты — от −1 до 1 по обеим осям, начало в центре кадра, ось y направлена вверх.
  • Расписание — ElementItem с именем Schedule: все семь дней (Mon…Sun), интервалы [начало, конец) в целых часах по часам камеры. Пустой день — сценарий в этот день выключен. У камер Optimus расписание общее для всех правил типа.
  • Постоянные правила (тип с $fixed="true") — CreateRules отвергается, DeleteRules снимает правило с охраны.
  • ModifyRules — меняет только переданные параметры.
  • Extension.NotApplied — параметры, которые камера приняла, но не сохранила, см. Расширения ответа.

Расширения ответа

То, чего нет в стандарте ONVIF, Optic передаёт расширениями:

  • Extension.Executor — в каждом ответе: optimus для адаптера Optimus, camera для стандартного ONVIF.
  • Extension.Excludes — в описании типа в GetSupportedRules: типы, которые камера не держит включёнными в одни часы с этим. Камеры на стандартном ONVIF их не объявляют.
  • Extension.Clock.UtcOffsetMinutes — в GetRules: смещение часов камеры от UTC, в этих часах задаётся расписание.
  • Extension.NotApplied — в ответах записи: по элементу на параметр, который камера приняла, но не сохранила. $Rule — правило, $Parameter — параметр, $Sent — отправленное значение, $Read — прочитанное после записи. Пустой список — камера сохранила всё.
  • $Source у параметра в описании типа: extension — параметра нет в стандарте, например Sensitivity, MinSize или Schedule; by-analogy — имя параметра взято по аналогии с однотипным правилом.
  • $Unit у параметра:

    • pixel — пиксели кадра;
    • second — секунды;
    • frame-width — доля ширины кадра.
    • $fixed="true" у типа — правило постоянное: его нельзя создать или удалить, только поставить на охрану или снять с неё.
    • Префикс cus: — тип или параметр вне стандарта ONVIF, например cus:RegionEntranceDetector или cus:HourSchedule.

Описание типа с расширениями:

{"$Name":"cus:RegionEntranceDetector","$maxInstances":"4","Extension":{"Excludes":["tt:LineCounting","tt:ObjectAbandoned","tt:ObjectRemoved","cus:CrowdDetector","cus:QueueDetector","tt:ObjectDetection","tt:LicensePlateRecognition"]},
 "Parameters":{"SimpleItemDescription":[{"$Name":"MinSize","$Type":"xs:int","$Source":"extension","$Unit":"pixel"}],
  "ElementItemDescription":[{"$Name":"Schedule","$Type":"cus:HourSchedule","$Source":"extension"}]}}

Ответ записи, в котором камера оставила выключатель правила по-своему:

{"Extension":{"Executor":"optimus","NotApplied":[{"$Parameter":"Armed","$Read":true,"$Rule":"LineDetector_1","$Sent":false}]}}

Срабатывания

Срабатывания правил хранятся как эпизоды с episode_type=trigger. Код правила передаётся в episode_subtype, несколько кодов — через запятую.

curl --fail-with-body --silent --show-error \
  --user "$API_LOGIN:$API_PASSWORD" \
  "$CENTRAL_URL/central/api-v4/episodes?media=$STREAM&episode_type=trigger&episode_subtype=lcd,enter" | jq
{"episode_id":"7701038866144167249","media":"entrance","opened_at":1793037836008,"closed_at":1793037836008,
 "frame_preview":{"sha256":"5c43636115c17e9cdd6810added59741109f637ce529f4d38e06fd2f341e954a","mime_type":"image/jpeg"},
 "detections":[],"details":{"type":"trigger","rule":"lcd"}}

Коды правил:

  • lcd — пересечение линии;
  • cc — подсчёт пересечений;
  • enter — вход в зону;
  • exit — выход из зоны;
  • pid — вторжение;
  • sod — оставленный или унесённый предмет;
  • cd — скопление;
  • qd — очередь;
  • tamper — саботаж.

Кадр срабатывания отдаёт GET /central/api-v4/episodes/{episode_id}/images/{sha256}, где sha256 берётся из frame_preview.

Заголовки запроса

  • x-onvif-fresh: true — прочитать возможности камеры заново, без памяти стримера.
  • x-onvif-auth: user:password — учётные данные камеры вместо взятых из RTSP-адреса.
  • x-onvif-port — HTTP-порт камеры, если он отличается от стандартного.

Ошибки

  • 400 unsupported_method — метод записи вне списка аналитики; 400 auth_error — заголовок x-onvif-auth не вида user:password.
  • 401 — неверные учётные данные Optic.
  • 404 not_found — стрим не запущен ни на одном стримере.
  • 409 no_camera_target — у стрима нет RTSP-источника с адресом камеры.
  • 422 param_error — значение вне пределов камеры; 422 schedule_overlap — несовместимые сценарии в одни часы. В errors[].path указан путь к полю.
  • 502 auth_error — камера отвергла логин и пароль; 502 onvif_error — камера ответила ошибкой или недоступна.
  • 503 — камера занята или просит подождать; повторите запрос позже.
  • 504 — камера не ответила вовремя. Запись при этом могла примениться: перед повтором прочитайте правила GetRules, иначе повтор CreateRules создаст второе правило.

Примеры ответа 422:

{"error":{"code":"param_error","message":"tt:LineDetector: MinSize is 8 px, the camera takes 64..1080 px",
  "errors":[{"path":["Rule",0,"Parameters","SimpleItem",4,"$Value"],"message":"tt:LineDetector: MinSize is 8 px, the camera takes 64..1080 px"}]}}
{"error":{"code":"schedule_overlap","message":"tt:LineDetector and tt:LicensePlateRecognition are both active on day 0 from 14:00 to 18:00 by the camera clock; the camera keeps only one of them at a time",
  "errors":[{"path":["Rule",0,"Parameters","ElementItem",0,"HourSchedule"],"message":"…"}]}}

Central не повторяет вызов на другом стримере после обрыва связи: запись в камеру может уже выполниться, и повтор изменил бы её дважды.