Skip to content

RTSP DVR

media.play.rtsp_dvr

O Sapsan fornece o arquivo gravado por RTSP. O cliente obtém os períodos de gravação disponíveis, seleciona um horário UTC e controla a reprodução na mesma sessão. A leitura de um arquivo existente não exige uma fonte de entrada ativa.

Transporte

RTSP 1.0 e RTP/RTCP interleaved compartilham uma conexão TCP. UDP não é suportado: SETUP com UDP retorna 461.

Codecs compatíveis

  • H.264
  • HEVC / H.265
  • AV1
  • AAC
  • Opus
  • PCMA
  • PCMU

A lista corresponde à packetização RTSP; o cliente deve suportar os codecs selecionados.

AAC usa MPEG4-GENERIC com cabeçalhos AU; AV1 usa fragmentação RTP e um sequence header. Há declarações SDP para MP4A-LATM e MPEG Audio (MPA, MP2/MP3), mas a saída atual não oferece a respectiva packetização RTP completa; eles não fazem parte da lista acima. Se necessário, converta o áudio para AAC ou Opus. O nome de um codec no SDP, por si só, não garante compatibilidade.

Protocolo e URL

O controle utiliza RTSP 1.0: RFC 2326. A descrição das trilhas utiliza SDP: RFC 4566. A mídia utiliza RTP/RTCP: RFC 3550. Para H.264, aplica-se o formato de payload RTP do RFC 6184.

A lista de períodos do arquivo em um único atributo SDP e o parâmetro position são extensões da interface de arquivo do Sapsan. Seus formatos estão descritos abaixo. As capacidades suportadas e as diferenças conhecidas são indicadas explicitamente; o suporte a RTSP 1.0 não implica suporte a todos os modos desses RFCs.

O acesso exige um arquivo DVR gravado, um listener RTSP configurado e uma licença que permita media.play.rtsp_dvr.

rtsp://sapsan.example.com:554/camera?dvr=true

A URL é estática: o horário é informado no cabeçalho Range, não na URL. O valor dvr=true é obrigatório; outros valores são rejeitados. Uma URL comum sem esse parâmetro fornece reprodução ao vivo e não aceita um Range: clock=... de arquivo. Se houver autorização por token, acrescente &token=<token>.

Licença

O recurso media.play.rtsp_dvr usa o limite de licença separado media_play_rtsp_dvr. RTSP ao vivo usa media_play_rtsp; a permissão para reproduzir ao vivo não concede acesso ao arquivo.

A admissão é verificada antes da leitura do arquivo, inclusive em um PLAY direto sem DESCRIBE anterior. Um limite zero proíbe o acesso, e um limite numérico esgotado impede novas sessões: o servidor responde 453 Not Enough Bandwidth.

A sessão de arquivo mantém sua admissão por licença após o fim do intervalo selecionado. O próximo PLAY na mesma conexão usa essa sessão. Libere-a com TEARDOWN ou fechando a conexão; EOF por si só não libera a vaga ocupada. Consulte licenciamento.

Períodos de gravação disponíveis

O cliente começa com DESCRIBE:

DESCRIBE rtsp://sapsan.example.com:554/camera?dvr=true RTSP/1.0
CSeq: 1
Accept: application/sdp

A resposta 200 OK tem um corpo application/sdp. Antes das descrições de trilhas m=, inclui este atributo de sessão:

a=range:clock=20261019T080000Z-20261019T093000Z;clock=20261019T100000Z-

O exemplo mostra dois períodos de gravação separados por uma lacuna. O formato de horário é YYYYMMDDThhmmssZ, em segundos inteiros UTC. A ausência de horário após o hífen no último período indica gravação em andamento.

  • Ordem. Os períodos são apresentados em ordem cronológica crescente.
  • União. Períodos adjacentes são unidos; lacunas de até 10 segundos inclusive também são unidas ao construir a lista. Esse período não garante quadros em cada segundo abrangido.
  • Quantidade. São anunciados no máximo os 100 períodos mais recentes. Gravações anteriores ainda existentes podem ser solicitadas por um PLAY explícito, mesmo quando não aparecem na lista.
  • Arquivo vazio. O atributo a=range é omitido. O servidor pode usar uma fonte ao vivo disponível para descrever as trilhas.

Quando existem gravações, a descrição das trilhas vem do arquivo. Assim, DESCRIBE e a reprodução permanecem disponíveis após a desconexão da fonte de entrada.

Preparação do transporte

Envie SETUP para cada trilha necessária usando seu identificador no SDP. RTP/RTCP é transportado na mesma conexão TCP do RTSP — interleaved TCP. No exemplo, <track-url> representa a URL da trilha selecionada:

SETUP <track-url> RTSP/1.0
CSeq: 2
Transport: RTP/AVP/TCP;unicast;interleaved=0-1

Cabeçalhos relevantes da resposta:

RTSP/1.0 200 OK
CSeq: 2
Session: example-session;timeout=60
Transport: RTP/AVP/TCP;unicast;interleaved=0-1

Use o Session recebido nas próximas solicitações. Escolha outro par de canais interleaved para a próxima trilha. O transporte UDP é rejeitado com 461.

Os exemplos mostram os campos relevantes da troca. Na rede, as linhas terminam em CRLF, uma linha vazia separa os cabeçalhos do corpo e Content-Length informa o tamanho do corpo em bytes.

Seleção de horário e busca

Para reproduzir um intervalo, envie PLAY para a URL de toda a sessão:

PLAY rtsp://sapsan.example.com:554/camera?dvr=true RTSP/1.0
CSeq: 3
Session: example-session
Range: clock=20261019T081000Z-20261019T081500Z
Scale: 1

Campos essenciais da resposta:

RTSP/1.0 200 OK
CSeq: 3
Session: example-session;timeout=60
Range: clock=20261019T081000Z-20261019T081500Z
Scale: 1

A resposta RTP-Info contém seq e rtptime para as trilhas preparadas que estão sendo entregues, inclusive no início do arquivo e após uma busca. Na retomada após uma pausa, rtptime corresponde ao próximo quadro real, inclusive em um salto sobre uma lacuna de gravação.

Solicitação PLAY Comportamento do Sapsan
Range: clock=<from>-<to> Começar em um fragmento independente e entregar quadros com DTS inferior a <to>
Range: clock=<from>- Selecionar fragmentos existentes a partir do horário indicado, sem limite superior
Novo Range: clock=... na mesma sessão Mudar imediatamente de posição; não é necessário outro SETUP
Range: npt=now- Mudar para a reprodução ao vivo
Sem Range, com uma fonte já selecionada Continuar a reprodução, inclusive após PAUSE
Sem Range, no primeiro início Selecionar a fonte ao vivo
NPT numérico aberto, como npt=10- 451 Parameter Not Understood; a reprodução atual continua

O Range da resposta informa os limites selecionados. Se <from> estiver dentro de um fragmento independente, a reprodução começa no início desse fragmento, que pode ser anterior ao solicitado. A busca para trás é limitada a 60 segundos; se não houver um início adequado, o próximo fragmento independente é selecionado. O fim é limitado por <to> e pela gravação disponível. Quadros com DTS igual ou superior a <to> não são entregues.

O hífen é mantido mesmo com o fim aberto. As solicitações aceitam segundos UTC inteiros, mas um limite real na resposta pode incluir milissegundos, por exemplo clock=20261019T081000.250Z-20261019T081500Z.

A reprodução ocorre para a frente na velocidade normal. Omita Scale ou indique 1; uma solicitação com Scale: 1 recebe Scale: 1. Outras velocidades e a forma inversa clock=-<to> retornam 451 Parameter Not Understood, mantendo a reprodução atual.

Se houver uma lacuna de gravação entre os fragmentos selecionados, o servidor passa ao próximo fragmento disponível sem esperar toda a duração da lacuna. As marcas de tempo saltam o período ausente.

Um intervalo aberto lê a seleção de fragmentos disponível ao receber PLAY e termina quando ela se esgota. Não incorpora novos fragmentos nem muda automaticamente para a transmissão ao vivo. A reprodução ao vivo exige um PLAY explícito com npt=now-.

Posição atual

Para obter a posição de entrega, envie GET_PARAMETER com position no corpo:

GET_PARAMETER rtsp://sapsan.example.com:554/camera?dvr=true RTSP/1.0
CSeq: 4
Session: example-session
Content-Type: text/parameters
Content-Length: 10

position

O corpo é position seguido de CRLF, totalizando 10 bytes. Resposta:

RTSP/1.0 200 OK
CSeq: 4
Session: example-session;timeout=60
Range: clock=20261019T081012Z
Supported: position

O horário é retornado em um cabeçalho, não no corpo da resposta. É uma única marca de tempo sem hífen, diferente do intervalo da resposta PLAY. O valor corresponde ao DTS do último quadro entregue, truncado para segundos inteiros, e não ao momento em que o cliente o exibe.

Antes do primeiro quadro entregue da fonte selecionada, inclusive após uma busca, position retorna 503 Service Unavailable sem Range, com Supported: position. Durante uma pausa e após EOF do arquivo, retorna 200 OK e a última posição confirmada. O código 200 por si só não indica se os quadros continuam sendo entregues. Um parâmetro desconhecido em um corpo não vazio retorna 200 OK e Supported: position, sem Range.

Pausa e encerramento da sessão

PAUSE na URL da sessão suspende a entrega preservando a posição dentro do fragmento. O próximo PLAY sem Range retoma os quadros restantes. Um novo Range: clock=... muda imediatamente a posição, inclusive ao enviar várias solicitações PLAY em pipeline; não é criada uma fila de intervalos.

Durante a pausa, mantenha a sessão ativa com um GET_PARAMETER vazio. O servidor anuncia timeout=60; envie solicitações keepalive com frequência maior que esse intervalo. Solicitações RTSP e pacotes RTCP recebidos contam como atividade.

Quando um intervalo que já entregou mídia RTP chega ao fim natural, o servidor envia RTCP BYE para as trilhas preparadas e encerra a entrega atual. A conexão e a sessão permanecem abertas: outro intervalo pode ser solicitado sem repetir SETUP.

Para liberar a sessão, envie TEARDOWN com seu Session. Após 200 OK, a conexão é fechada e a vaga de licença é liberada.

Mídia e limites de compatibilidade

Para H.264, os parâmetros do decodificador são transmitidos no SDP, e SPS/PPS ausentes são inseridos antes dos quadros-chave. Os parâmetros são atualizados quando a configuração dos fragmentos do arquivo muda. As marcas RTP são calculadas a partir do DTS do arquivo; RTCP Sender Report as relaciona ao horário NTP.

RTCP Sender Report contém as contagens acumuladas de pacotes RTP e octetos da carga útil. Cabeçalhos RTP e o encapsulamento interleaved não entram nos octetos. Uma busca com o mesmo SSRC não reinicia os contadores.

O perfil suportado tem os seguintes limites:

  • Transporte. Somente interleaved TCP; UDP retorna 461.
  • Velocidade. Somente reprodução normal para a frente; outros valores de Scale retornam 451.
  • Escala de tempo. Para buscar no arquivo, use clock com segundos UTC inteiros. NPT numérico e SMPTE não são suportados. Frações de segundo só são permitidas nas respostas.
  • Sequência de intervalos. Cada novo PLAY de arquivo muda a posição imediatamente; não há fila de intervalos.
  • Gravação em andamento. Um intervalo aberto não lê fragmentos criados após o início da reprodução.

Códigos de resposta

Código Causa
400 Bad Request dvr ou URL inválidos; falta Transport em SETUP
403 Forbidden Autorização negada ou stream criptografado indisponível para entrega RTSP
404 Not Found Stream, arquivo ou trilha não encontrados
451 Parameter Not Understood Range ou Scale não suportados; arquivo solicitado por uma URL comum de transmissão ao vivo
453 Not Enough Bandwidth Função proibida pela licença ou limite de sessões atingido
454 Session Not Found Falta o contexto de sessão necessário
457 Invalid Range Janela vazia ou invertida; nenhum fragmento de arquivo adequado
461 Unsupported Transport Foi solicitado um transporte diferente de interleaved TCP
503 Service Unavailable Fonte indisponível; position solicitado antes do primeiro quadro da fonte selecionada. EOF do arquivo por si só não causa 503 para position

Verificação do cliente

Verifique a integração com uma gravação de limites temporais conhecidos e uma lacuna:

  1. Obtenha o SDP e compare a=range com os períodos de gravação, considerando a união de lacunas curtas.
  2. Envie SETUP para as trilhas necessárias. Confira os pares de canais interleaved e o identificador da sessão.
  3. Solicite position antes do primeiro quadro: espera-se 503 sem Range.
  4. Inicie PLAY dentro de um fragmento com Scale: 1. Confira o Range escolhido, o Scale retornado e se rtptime/seq correspondem ao primeiro pacote RTP. Nenhum quadro deve ter DTS >= <to>.
  5. Pause dentro de um fragmento e retome com PLAY sem Range. Confira se os quadros restantes e a posição são preservados.
  6. Verifique 451 para velocidade não suportada e NPT numérico: a reprodução atual deve continuar.
  7. Aguarde EOF e RTCP BYE e solicite outro intervalo na mesma conexão. Confira a posição após EOF e os contadores acumulados de Sender Report.
  8. Verifique a recusa por licença 453 com limite zero ou esgotado e finalize com TEARDOWN.