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
ElementItemchamadoSchedule: 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;DeleteRulesdesarma 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:optimuspara o adaptador Optimus,camerapara ONVIF padrão.Extension.Excludes— na descrição de um tipo emGetSupportedRules: 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— emGetRules: 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,$Parametero parâmetro,$Sento valor enviado e$Reado lido após a gravação. Uma lista vazia significa que a câmera salvou tudo.$Sourcede um parâmetro na descrição de um tipo:extension— o parâmetro não está no padrão, por exemploSensitivity,MinSizeouSchedule;by-analogy— o nome do parâmetro foi tomado por analogia com uma regra de tipo semelhante.-
$Unitde 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 exemplocus:RegionEntranceDetectoroucus: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; 400auth_error— o cabeçalhox-onvif-authnão tem a formauser: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; 422schedule_overlap— cenários incompatíveis nas mesmas horas.errors[].pathindica o campo. - 502
auth_error— a câmera recusou o usuário e a senha; 502onvif_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
GetRulesantes de repetir; caso contrário, repetirCreateRulescria 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.