Skip to content

Associação ao tempo real

media.source.realtime_aligner

Para um live stream, não basta conhecer a ordem dos quadros e a velocidade de reprodução. O streamer precisa saber a que horário do calendário cada quadro corresponde: assim, pode gravá-lo no DVR e, depois, encontrar o momento desejado pela data e hora.

As fontes fornecem bases diferentes para essa decisão. Algumas têm apenas uma linha do tempo relativa; outras têm seus próprios relógios, que nem sempre são confiáveis. A rede pode entregar em rajadas um fluxo uniforme em tempo de mídia. O Sapsan associa essas linhas do tempo ao tempo real, preservando os intervalos entre os quadros, e revê essa associação quando o comportamento da fonte muda.

Tempo de mídia, relógio da fonte e horário de chegada

Um quadro possui timestamps: o DTS define o momento de decodificação, e o PTS, o momento de exibição. Eles determinam a posição do quadro na linha do tempo de mídia, mas nem sempre contêm a data e a hora do dia.

Fonte de tempo O que o streamer sabe Objetivo
DTS/PTS relativos, por exemplo, em MPEG-TS A ordem dos quadros e os intervalos entre eles Escolher a posição dessa linha do tempo no calendário do streamer.
Timestamps de calendário, por exemplo, após a associação de RTP por RTCP Sender Report O horário absoluto segundo o relógio do remetente Verificar se esse relógio é confiável.
Horário de chegada real Quando o quadro ficou disponível para o pipeline do servidor Considerar os atrasos de rede e a entrega em lotes sem transformá-los em distorções da linha do tempo de mídia.

Em um mesmo stream, essas informações podem aparecer em momentos diferentes. Por exemplo, uma entrada RTSP primeiro recebe quadros com timestamps RTP relativos e depois obtém a associação ao horário absoluto por RTCP. Uma reconexão da câmera ou uma mudança de fonte pode alterar novamente a base da linha do tempo.

MPEG-TS sem horário de calendário

Os timestamps de MPEG-TS permitem reproduzir vídeo e áudio no ritmo correto, mas não informam que um quadro corresponde, por exemplo, às 14:00:00 de hoje. O contador pode começar com um valor arbitrário e ultrapassar o limite de seu intervalo.

O Sapsan escolhe um deslocamento entre a linha do tempo de mídia e o relógio do streamer. Depois, aplica esse deslocamento ao DTS e ao PTS, preservando as distâncias entre os timestamps:

calendar_time = source_time + offset

Por exemplo, um quadro com DTS relativo de 42,000 s é associado às 14:00:00. O quadro seguinte, com DTS de 42,040 s, recebe o horário 14:00:00,040. Seu horário não é substituído pelo momento da próxima leitura do socket.

Assim, o arquivo recebe uma linha do tempo de calendário baseada na chegada do stream ao Sapsan. Para uma fonte sem timestamps absolutos, essa associação é feita pelo servidor: não é possível usá-la para recuperar o horário original de captura desconhecido nem o atraso até o streamer. Quando o buffer de entrada está ativado, a associação ocorre depois que ele libera os quadros; portanto, seu atraso também afeta a posição da linha do tempo.

RTSP e WebRTC: o horário absoluto precisa ser verificado

Entradas baseadas em RTP, incluindo RTSP e WebRTC, podem obter o horário absoluto por RTCP Sender Report. Mas um timestamp de calendário não garante um relógio correto: a câmera pode ter perdido a configuração de horário, operar sem sincronização ou transmitir um horário muito distante no passado ou no futuro.

No caminho normal de alinhamento, o Sapsan distingue timestamps de calendário de timestamps relativos. É considerado de calendário um valor na escala de tempo Unix a partir do ano 2000. Se esse timestamp diferir do relógio do streamer em até 60 segundos, ele é preservado: o intervalo de entrega não se torna um motivo para atribuir novamente o horário da fonte.

Se a diferença ultrapassar a janela de confiança, o timestamp é tratado como uma linha do tempo que exige associação ao horário do servidor. A verificação é simétrica para o passado e o futuro. Isso evita gravar a transmissão atual segundo um calendário claramente incorreto da câmera.

A janela de confiança não garante uma sincronização precisa: um erro de relógio dentro dela pode ser preservado. A sincronização do horário na fonte e no servidor continua necessária para que a gravação no arquivo corresponda exatamente ao evento real.

A decisão também é tomada para cada faixa. Uma faixa com horário de calendário confiável não recebe novamente o deslocamento escolhido para a linha do tempo relativa: caso contrário, o servidor poderia adicionar a época Unix a um timestamp já absoluto.

Entrega em rajadas: HLS → HTTP MPEG-TS

Um servidor intermediário pode receber vários segundos de HLS, processar o segmento e enviar seu conteúdo por HTTP MPEG-TS quase de uma só vez. Depois, há uma pausa até o próximo segmento. O tempo de mídia avança uniformemente dentro de cada rajada, enquanto o horário de chegada dos quadros varia bastante.

Se cada quadro recebesse um horário segundo sua chegada, vários segundos de vídeo seriam comprimidos em uma curta rajada de rede, e a pausa entre os segmentos se tornaria uma lacuna na linha do tempo. Se o deslocamento fosse alterado a cada oscilação, surgiriam descontinuidades e novas associações repetidas.

O Sapsan processa essa entrada em sequência:

  1. O buffer de entrada acumula os quadros e os libera no ritmo do DTS. Os tempos internos do fluxo determinam os intervalos de liberação, enquanto as rajadas da rede são absorvidas pela fila.
  2. O alinhador associa a linha do tempo de mídia resultante ao calendário. Ele preserva o deslocamento escolhido enquanto a diferença permanece aceitável.
  3. Os componentes seguintes recebem os timestamps associados para transcodificação, empacotamento e gravação.

Na entrada tshttp, a profundidade padrão do buffer é 30 000 ms. A configuração é enviada pela API do central:

streams:
  - name: tv1
    inputs:
      - tshttp:
          url: http://origin.example/live/tv1.ts
        source_options:
          buffer_ms: 30000

buffer_ms é definido em source_options da entrada. É uma profundidade alvo em tempo de mídia, não um número de bytes. O valor explícito 0 desativa o buffer; um valor positivo também o ativa para outros tipos de entrada. Nos demais tipos, ele fica desativado por padrão. Aumentar a profundidade permite cobrir pausas mais longas, com maior atraso e consumo de memória.

O buffer não consegue compensar uma interrupção indefinida da fonte. Quando os quadros acumulados acabam, a entrega é interrompida. Quando o acúmulo é excessivo, o material antigo pode ser descartado para reduzir o atraso em relação ao conteúdo ao vivo; esses eventos ficam disponíveis nas estatísticas.

Quando a associação muda

Para uma linha do tempo que exige deslocamento do servidor, o alinhador verifica a diferença entre o relógio atual e o DTS já deslocado. Se o módulo da diferença ficar maior que 5 segundos, um novo deslocamento é escolhido. Isso permite reagir à reinicialização dos timestamps, ao desvio de ritmo acumulado e à mudança de linha do tempo após uma reconexão.

A decisão se baseia em uma única faixa principal de áudio ou vídeo. O vídeo tem prioridade sobre o áudio. As demais faixas com tempo relativo recebem o deslocamento comum: suas diferenças não devem fazer com que cada uma reajuste alternadamente a linha do tempo de todo o stream. Se a faixa principal não chegar por mais de 5 segundos, outra faixa de áudio ou vídeo que esteja chegando pode assumir esse papel.

O deslocamento é aplicado ao DTS e ao PTS. O alinhador preserva a relação entre eles; não corrige uma dessincronização de áudio e vídeo já existente na fonte.

Quando ocorre uma nova associação, um evento de mudança da linha do tempo é enviado ao pipeline de mídia. O empacotamento posterior pode encerrar os fragmentos atuais e iniciar outros. A nova associação pode deslocar o horário tanto para a frente quanto para trás: o mecanismo restabelece a relação com o tempo real, mas não promete ocultar qualquer salto da fonte sem uma descontinuidade.

Para fontes com uma linha do tempo de calendário já preparada, há um modo separado de preservação do horário. Entradas diretas de HLS e DASH passam sem essa correção; seu atraso normal de vários segmentos não provoca novas associações constantes. Portanto, a captura direta de HLS e a captura de HTTP MPEG-TS obtido por um servidor intermediário a partir de HLS exigem comportamentos diferentes. A preservação do horário também se aplica aos caminhos internos que transportam quadros já associados, para não alterar novamente a linha do tempo em cada etapa.

O alinhamento faz parte do pipeline ao vivo. Os limites de 5 e 60 segundos descrevem a implementação atual; não há parâmetros YAML separados para eles na configuração do stream.

O que observar

Consulte as estatísticas no streamer que recebe a fonte:

curl -fsS -u "$ADMIN_USER:$ADMIN_PASSWORD" \
  http://streamer:8080/streamer/api-v4/streams/stats/tv1 \
  | jq '{name, dts_source, source_timing_offset_ms,
         source_timing_offset_min_ms, source_timing_offset_max_ms,
         source_timing_jitter_ms, source_timing_input,
         source_timing_window_started_at, input}'

O campo dts_source mostra a base da linha do tempo:

  • realtime — o horário é mantido por um deslocamento em relação ao relógio do streamer.
  • input — os timestamps da fonte são preservados: passaram pela verificação de horário de calendário ou a entrada opera no modo de preservação da linha do tempo.

Antes da chegada de quadros e após um silêncio prolongado, o campo pode estar ausente. Na exportação de métricas, stream_dts_source usa os valores 1 para realtime e 2 para input.

source_timing_offset_ms mostra o deslocamento atual medido pelo monitor de tempo. Os limites source_timing_offset_min_ms / source_timing_offset_max_ms e source_timing_jitter_ms se referem à janela de um minuto concluída; source_timing_input e source_timing_window_started_at identificam a fonte e o início da janela. Para uma linha do tempo relativa, o monitor escolhe seu próprio ponto de referência; portanto, esses valores não devem ser considerados uma medição do atraso desconhecido entre a câmera e o streamer.

O monitor fica antes do alinhador, mas depois do buffer de entrada. Quando o buffer está ativado, seus indicadores já refletem a entrega suavizada. Para avaliar a irregularidade original, compare-os com o estado do buffer e os episódios em que ele se esvazia, em vez de observar apenas um gráfico de jitter.

A seção input oferece os indicadores do buffer:

Campo Significado
buffer_target_ms Profundidade alvo em milissegundos de tempo de mídia.
buffer_depth_ms Profundidade atual.
buffer_underruns Número acumulado de episódios de esgotamento do buffer.
buffer_skips Número acumulado de reduções da fila por excesso de profundidade.
buffer_skipped_ms Tempo total de mídia descartado, em milissegundos.

Campos zerados podem estar ausentes na resposta. Compare o aumento dos contadores ao longo de um intervalo; a ausência de toda a seção de estatísticas não significa que a verificação tenha sido realizada sem erros.

Para a operação, é útil verificar três cenários:

  • Fluxo relativo uniforme — a linha do tempo do arquivo acompanha o relógio do streamer, e os intervalos entre os quadros são preservados.
  • Fonte com relógio incorreto — um calendário claramente não confiável é substituído pela associação ao servidor; após a correção do relógio, a fonte pode voltar a fornecer seu próprio horário.
  • Fluxo que chega em rajadas — o buffer suaviza a entrega; pausas prolongadas e excesso de profundidade ficam visíveis nas estatísticas e não são mascarados pela reatribuição constante do horário de cada quadro.