Skip to content

Análise da câmera pela API

A aba Analítica funciona com a solicitação do central POST /central/api-v4/streams/{stream}/onvif-call/analytics/{method}. Um sistema externo usa a mesma solicitação. O central encaminha a chamada ao streamer que captura o vídeo da câmera, e o streamer a repassa à câmera.

Antes de começar

A solicitação está disponível para os papéis superadmin e admin. O stream deve estar em execução e a câmera preparada como descrito em Preparação do stream. Os exemplos exigem Bash, curl e jq. As respostas dos exemplos vêm de uma câmera Optimus; outra câmera tem o seu próprio conjunto de tipos e parâmetros.

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"
}

Um nome de stream com barra é passado codificado: cams%2Fentrance.

Métodos

Os nomes e corpos dos métodos seguem o serviço ONVIF Analytics escrito em JSON. Os atributos XML levam o prefixo $; o Optic adiciona sozinho o token de configuração de análise.

  • GetSupportedRules — os tipos de regra da câmera, o seu número e os cenários incompatíveis.
  • GetRuleOptions — os limites dos parâmetros de uma regra.
  • GetRules — as regras da câmera.
  • CreateRules, ModifyRules, DeleteRules — criar, alterar e excluir regras.
  • GetServiceCapabilities — o que o serviço de análise da câmera suporta.
  • GetSupportedAnalyticsModules, GetAnalyticsModuleOptions, GetAnalyticsModules, ModifyAnalyticsModules — os módulos de análise, por exemplo a grade e a sensibilidade do detector de movimento.

Outros métodos de gravação são recusados com o código unsupported_method. Cada tentativa de gravar regras é registrada no log de auditoria do central com a ação stream_onvif.rules_write.

Capacidades da câmera

Tipos de regra, o seu número máximo e cenários incompatíveis:

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"]}

Limites dos parâmetros de um tipo:

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"}}]

O streamer guarda as capacidades da câmera em memória. Para lê-las novamente da câmera, por exemplo após atualizar o firmware, adicione o cabeçalho x-onvif-fresh: true.

Leitura de regras

analytics GetRules '{}' | jq

Na resposta, Extension.Executor indica o executor: optimus para o adaptador Optimus, camera para ONVIF padrão. Extension.Clock.UtcOffsetMinutes é o deslocamento do relógio da câmera em relação ao UTC; o horário é definido nessas horas.

Criar, alterar e excluir

Crie uma linha. O nome da regra <tipo>_<número> é atribuído na criação e devolvido em 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"]}

Arme a linha com horário de segunda a sexta, das 9 às 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":[]}}]}}]}'

Se a câmera declarou cenários incompatíveis (Extension.Excludes) e a janela se sobrepõe a um deles, a gravação é recusada: a resposta é 422 schedule_overlap, veja Erros.

Exclua a linha:

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

A sensibilidade do detector de movimento é definida no módulo de análise:

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

Regras de gravação:

  • Coordenadas — de −1 a 1 nos dois eixos, origem no centro do quadro, o eixo y aponta para cima.
  • Horário — um ElementItem chamado Schedule: os sete dias (Mon…Sun), intervalos [início, fim) em horas inteiras do relógio da câmera. Um dia vazio desliga o cenário nesse dia. Nas câmeras Optimus, o horário é comum a todas as regras do tipo.
  • Regras permanentes (tipo com $fixed="true") — CreateRules é recusado; DeleteRules desarma a regra.
  • ModifyRules — altera somente os parâmetros enviados.
  • Extension.NotApplied — parâmetros que a câmera aceitou, mas não salvou, veja Extensões da resposta.

Extensões da resposta

O que o padrão ONVIF não prevê, o Optic transmite como extensões:

  • Extension.Executor — em toda resposta: optimus para o adaptador Optimus, camera para ONVIF padrão.
  • Extension.Excludes — na descrição de um tipo em GetSupportedRules: tipos que a câmera não mantém ativos nas mesmas horas que este. Câmeras com ONVIF padrão não os declaram.
  • Extension.Clock.UtcOffsetMinutes — em GetRules: o deslocamento do relógio da câmera em relação ao UTC; o horário é definido nessas horas.
  • Extension.NotApplied — nas respostas de gravação: um item por parâmetro que a câmera aceitou, mas não salvou. $Rule é a regra, $Parameter o parâmetro, $Sent o valor enviado e $Read o lido após a gravação. Uma lista vazia significa que a câmera salvou tudo.
  • $Source de um parâmetro na descrição de um tipo: extension — o parâmetro não está no padrão, por exemplo Sensitivity, MinSize ou Schedule; by-analogy — o nome do parâmetro foi tomado por analogia com uma regra de tipo semelhante.
  • $Unit de um parâmetro:

    • pixel — pixels do quadro;
    • second — segundos;
    • frame-width — fração da largura do quadro.
    • $fixed="true" de um tipo — a regra é permanente: não pode ser criada nem excluída, apenas armada ou desarmada.
    • O prefixo cus: — um tipo ou parâmetro fora do padrão ONVIF, por exemplo cus:RegionEntranceDetector ou cus:HourSchedule.

Descrição de um tipo com extensões:

{"$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"}]}}

Resposta de gravação em que a câmera manteve o interruptor da regra à sua maneira:

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

Acionamentos

Os acionamentos das regras são guardados como episódios com episode_type=trigger. O código da regra vai em episode_subtype; vários códigos são separados por vírgulas.

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"}}

Códigos de regra:

  • lcd — cruzamento de linha;
  • cc — contagem de cruzamentos;
  • enter — entrada na zona;
  • exit — saída da zona;
  • pid — intrusão;
  • sod — objeto abandonado ou removido;
  • cd — aglomeração;
  • qd — fila;
  • tamper — sabotagem.

O quadro do acionamento é devolvido por GET /central/api-v4/episodes/{episode_id}/images/{sha256}, com sha256 tirado de frame_preview.

Cabeçalhos da solicitação

  • x-onvif-fresh: true — ler novamente as capacidades da câmera, sem a memória do streamer.
  • x-onvif-auth: user:password — credenciais da câmera no lugar das da URL RTSP.
  • x-onvif-port — a porta HTTP da câmera, se for diferente da padrão.

Erros

  • 400 unsupported_method — um método de gravação fora da lista de análise; 400 auth_error — o cabeçalho x-onvif-auth não tem a forma user:password.
  • 401 — credenciais do Optic inválidas.
  • 404 not_found — o stream não está em execução em nenhum streamer.
  • 409 no_camera_target — o stream não tem uma fonte RTSP com o endereço da câmera.
  • 422 param_error — um valor fora dos limites da câmera; 422 schedule_overlap — cenários incompatíveis nas mesmas horas. errors[].path indica o campo.
  • 502 auth_error — a câmera recusou o usuário e a senha; 502 onvif_error — a câmera respondeu com erro ou está inacessível.
  • 503 — a câmera está ocupada ou pede para aguardar; repita a solicitação mais tarde.
  • 504 — a câmera não respondeu a tempo. A gravação pode ter sido aplicada: leia as regras com GetRules antes de repetir; caso contrário, repetir CreateRules cria uma segunda regra.

Exemplos de resposta 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":"…"}]}}

O central não repete uma chamada em outro streamer após perder a conexão: a gravação na câmera pode já ter sido feita, e repeti-la a alteraria duas vezes.