Episodes¶
vision.index.episodes
Um episódio descreve um evento do stream e o associa a um momento do vídeo. O central armazena o estado mais recente do episódio e as suas imagens; o histórico está disponível pela API e pela consola do Optic.
Episódios do stream no Optic¶
Abra a página do stream e a aba Episódios. São mostrados os episódios guardados deste stream, os mais recentes primeiro. Cada mosaico contém uma pré-visualização e a hora do evento, e a matrícula quando disponível. Esta aba só está ativada no Optic.
Se a câmera enviou um evento sem imagem, o mosaico e o cartão carregam um quadro do arquivo de vídeo no momento de início do episódio. Isso também funciona para eventos já guardados. O quadro fica disponível enquanto a pré-visualização correspondente permanecer no arquivo; se não for possível lê-lo, a interface mostra um erro ao carregar a imagem.
Defina os filtros de pesquisa e clique em Aplicar:
- Tipo — o tipo de episódio.
- Regra — o código da regra para as ativações, por exemplo
lcd. - Placa — a matrícula exata reconhecida.
Carregar mais obtém a página seguinte com os mesmos filtros. Atualizar volta a ler o histórico desde o início; a lista não é atualizada automaticamente.
Clique num mosaico para abrir o cartão. O cartão mostra a descrição e o fotograma completo, se estiver guardado. Quando há um arquivo de vídeo configurado, abre o reprodutor com cinco segundos antes e depois do episódio. Um episódio pode permanecer no histórico depois de eliminar o seu vídeo: a retenção dos metadados é configurada separadamente.
Episódios criados pela API num stream em gravação:

Cartão do episódio com reprodução do arquivo de vídeo:

Retenção de episódios no central¶
O central coleta o último estado dos episódios e suas imagens dos streamers e os armazena no PostgreSQL. Os episódios retidos continuam disponíveis quando o streamer de origem está indisponível. Esse armazenamento é independente da gravação de vídeo.
Em DVR do stream ou de seu modelo, Retenção adicional de episódios (horas) define dvr.episodes_additional_depth; a API e o YAML usam segundos. O total é dvr.max_depth + dvr.episodes_additional_depth. A profundidade adicional não definida equivale a zero. Se a seção DVR existe mas max_depth não está definido, usam-se dez anos; zero explícito continua sendo zero. Sem seção DVR, ou com total zero, o central não retém episódios.
O prazo começa em closed_at para episódios fechados e em updated_at para os abertos. Alterações na configuração DVR efetiva, incluindo o modelo, recalculam a retenção de todos os episódios restantes. A seção DVR do próprio stream substitui a seção do modelo por inteiro. Excluir um stream exclui seus episódios e imagens. Aumentar a retenção não recupera episódios já removidos fisicamente pela limpeza em segundo plano.
API de episódios¶
GET /central/api-v4/episodes lê o histórico do PostgreSQL; GET /central/api-v4/episodes/{episode_id} lê um episódio. A origem GET /streamer/api-v4/episodes contém a janela atual em memória do streamer; interrupções prolongadas podem causar lacunas.
Estas rotas pertencem à API de gestão; o papel viewer pode lê-las. Os espectadores podem usar as APIs streaming e playback com o token do stream. O cartão obtém o vídeo pela API de reprodução habitual.
O limite padrão é 100, o máximo 1000 e a página serializada, incluindo o envelope, é limitada a 32 MiB. Continue com next_cursor; offset é proibido. Episódios grandes demais são ignorados com um contador para não bloquear o avanço. sort aceita -opened_at (padrão), opened_at, -updated_at, updated_at; o ID desempata na mesma direção. Essa paginação não é um feed incremental global.
Filtros: listas separadas por vírgulas em media, episode_type, episode_subtype; episode_id; license_plate_text exato e license_plate_text_like com SQL LIKE. from e to são Unix ms e selecionam a interseção com [from,to). Um episódio aberto continua após sua última atualização. opened_at, started_at, updated_at e closed_at aceitam _gt, _gte, _lt, _lte. Filtros diferentes combinam-se com AND e listas com OR. O vencimento não oculta o registro antes da exclusão física.
details.type identifica o tipo. Em vehicle, purpose, emergency_subtype, facing_side, color, model não usam vehicle_. A prévia inline está em preview.data (base64), com preview.timestamp. Imagens completas incluem sha256 e MIME sem URL; o cliente constrói GET /central/api-v4/episodes/{episode_id}/images/{sha256}. O hash deve pertencer ao estado atual do episódio. Bytes e MIME originais são preservados; sem MIME usa-se application/octet-stream.
episodes_stale_timeout_secs fecha episódios sem uma versão nova após 86400 segundos por padrão, usando o updated_at anterior como fechamento. Uma versão mais recente pode reabri-los; repetir uma versão não reinicia o prazo. A unicidade global do ID e o feed global continuam sendo requisitos separados para ativar a função. O prazo é contado a partir do updated_at do episódio; o horário de recebimento não o prolonga. O central não altera updated_at ao fechar um episódio abandonado.
Configure na página Configurações do central no console. O valor fica no documento compartilhado /central/api-v4/config e aplica-se sem reiniciar. Limpar o campo restaura o padrão.
Leitura com um token do stream¶
Os episódios e as suas imagens aceitam os mesmos tokens que o vídeo do stream. Estes pedidos não exigem acesso de gestão. Use Authorization: Bearer ou o parâmetro de consulta token; quando ambos estão presentes, o parâmetro de consulta tem prioridade.
Rotas relativas a /playback no central e a /streaming num nó:
GET /v/{stream_name}/episodes
GET /v/{stream_name}/episodes/{episode_id}
GET /v/{stream_name}/episodes/{episode_id}/preview
GET /v/{stream_name}/episodes/{episode_id}/images/{sha256}
Playback lê o histórico do PostgreSQL, incluindo episódios externos, mesmo quando o nó está indisponível. Os filtros e a ordenação são os mesmos do histórico de gestão; media é proibido porque o stream já está indicado na rota. Streaming do nó lê a sua janela atual de análise em memória e aceita cursor e limit; peça o histórico persistente ao central. Um token de stream não permite abrir episódios nem imagens de outro stream.
Ler uma lista, um episódio, uma pré-visualização ou uma imagem completa não cria nem prolonga uma sessão, não inicia a captura ou gravação a pedido nem conta como visualização de vídeo. O acesso é verificado em cada pedido; as respostas usam Cache-Control: no-store. O vídeo aberto separadamente pelo playback é contabilizado da forma habitual.
curl -H "Authorization: Bearer $PLAY_TOKEN" \
"$CENTRAL/playback/v/episode-demo/episodes?limit=100"
Criar um episódio externo¶
Os sistemas externos enviam episódios para POST /central/api-v4/episodes. Basta conhecer o nome do stream: o central grava o episódio e as imagens diretamente no PostgreSQL. O nó pode estar indisponível e não é necessário haver vídeo. É necessária permissão de escrita na API de gestão; o papel viewer não pode criar episódios.
Crie episode.json. Os tempos são milissegundos Unix na linha do tempo do vídeo; substitua o nome do stream e os tempos do evento pelos seus valores.
{
"media": "episode-demo",
"opened_at": 1700000000000,
"closed_at": 1700000004000,
"details": { "type": "motion", "is_motion": true }
}
Envie o documento com o endereço do central e as suas credenciais:
curl --user "$API_LOGIN:$API_PASSWORD" \
--header 'Content-Type: application/json' \
--data-binary @episode.json \
"$CENTRAL_URL/central/api-v4/episodes"
A primeira solicitação devolve 201 e um episode_id como string decimal. O episódio já está disponível por GET e Atualizar na aba Episódios. Uma repetição com os mesmos media, opened_at e details.type devolve 200 e o ID original sem alterar os dados nem o prazo de retenção. Os outros atributos, incluindo a regra de trigger, não fazem parte da chave. Os episódios custom usam a etiqueta literal custom. A exclusão física do episódio libera a chave.
details tem o mesmo formato das respostas de leitura. Pode incluir preview e frame_preview com data em base64 e mime_type; o tempo da prévia fica em preview.timestamp. Envie os bytes completos das imagens: uma referência sha256 não basta. O central atribui o ID e updated_at. A solicitação completa é limitada a 32 MiB.
O stream deve existir e a sua configuração DVR efetiva deve permitir a retenção de episódios. Respostas de erro:
- 404 — stream desconhecido.
- 409 — retenção desativada.
- 422 — documento inválido, com caminhos dos campos.
- 413 — tamanho da solicitação excedido.
Após um timeout, repita a mesma chave. POST cria um episódio; a repetição não fecha nem atualiza um episódio aberto existente. Os episódios produzidos pela análise do nó continuam a chegar pelo harvester.
Dados adicionais do episódio¶
Veja um exemplo completo de escrita, alteração e busca de meta em Dados personalizados de episódios.