Quando áudio e vídeo se descolam na TV ao vivo

18 de junho de 2026

Os lábios param de bater com a voz

Ninguém percebe nos primeiros dez minutos. Duas horas dentro de uma transmissão ao vivo, a boca do apresentador está bem de leve à frente da voz — ou atrás dela — e o telespectador não sabe dizer por que o canal parece estranho, mas sente. Erro de lip-sync é o vale da estranheza da reprodução de vídeo: abaixo de um limiar é invisível, acima dele a imagem inteira parece barata, e num stream ao vivo de longa duração você escorrega por cima dessa linha tão devagar que nunca pega num teste curto.

Video-on-demand raramente tem esse problema — um filme de duas horas decodifica de uma única timeline limpa e para. Ao vivo é diferente. Roda por horas, insere anúncios, sai de encoders e packagers que nunca estiveram perfeitamente em sincronia, e toca em SoCs de TV cujos relógios estão a alguns parts-per-million de todo mundo. Drift é o padrão; manter o sync é o que você tem que engenheirar.

Por que áudio e vídeo se descolam

Dentro do player, áudio e vídeo são dois pipelines com dois decoders, e eles não avançam no mesmo relógio a menos que algo os force.

Todo frame e toda amostra de áudio carrega timestamps — PTS para apresentação, DTS para decodificação — que dizem quando aquilo deve ser mostrado ou ouvido em relação a uma timeline compartilhada. Em teoria, os dois pipelines obedecem a esses stamps e ficam travados juntos. Na prática, o relógio do áudio e o relógio do vídeo são osciladores fisicamente diferentes, e em hardware barato o DAC de áudio e a saída de vídeo pulsam em taxas de leve diferentes. Alguns parts-per-million parecem nada; ao longo de três horas, alguns ppm viram dezenas de milissegundos, e acumulam numa direção só. Esse é o escorregamento lento.

Depois tem a fonte. Segmentos ao vivo nem sempre têm durações certinhas e idênticas. Intervalos de anúncio chegam em discontinuity boundaries — marcadores SCTE-35 que cortam do programa pro anúncio e de volta — e cada splice desses é um lugar onde as timelines de áudio e vídeo podem ser costuradas com um pequeno offset. Timestamp gaps, um segmento um fio mais curto ou mais longo, um PTS que dá wrap ou pula: cada um é uma chance de ganhar ou perder alguns milissegundos.

Buffer underruns são a versão violenta. Quando a rede trava e o buffer seca, algo tem que ceder. Se o pipeline de vídeo dropa ou pula frames pra alcançar enquanto o áudio segue tocando — ou o contrário — você não escorrega por alguns milissegundos, você sai de sync tudo de uma vez.

Detectar antes de o telespectador detectar

Você não conserta um drift que não está medindo, e a medição é comparar onde o áudio acha que está com onde o vídeo acha que está. No navegador você tem menos acesso direto que um player nativo, mas dá pra comparar as posições de áudio e vídeo que o pipeline expõe e acompanhar o delta crescer com o tempo. Numa stack nativa dá pra ler os render timestamps reais dos dois pipelines. De qualquer jeito, o sinal é o mesmo: uma diferença que se alarga entre o relógio do áudio e o do vídeo.

O número que importa é o limiar de percepção, e ele não é simétrico. Os humanos toleram o áudio atrasado em relação ao vídeo muito melhor do que o áudio adiantado — a gente está acostumada a som que chega depois da coisa que o produziu, nunca antes. A regra de bolso da radiodifusão, vinda do trabalho da ITU e da EBU sobre lip-sync, é mais ou menos áudio no máximo +45ms à frente do vídeo e no máximo −125ms atrás antes de ficar detectável. Então seus limiares de correção também deveriam ser assimétricos: reaja mais cedo quando o áudio se adianta à imagem do que quando ele fica pra trás, porque o olho é bem menos tolerante com som que chega cedo demais.

Consertar: um empurrãozinho ou um pulo

Uma vez que você decidiu que o drift passou do limiar, você tem duas ferramentas, e o ofício inteiro é escolher entre elas.

A ferramenta gentil é um empurrão no playback rate. Acelere ou desacelere o pipeline adiantado por uma fração de por cento — playbackRate = 1.02 por um momento — e deixe ele fechar o vão ao longo de um ou dois segundos. Mantido pequeno o bastante, dezenas de milissegundos de pitch-shift e ritmo de frames ficam abaixo do que qualquer um nota. É a ferramenta certa pro escorregamento lento de ppm, onde o erro é pequeno e você tem tempo de drená-lo de forma invisível.

A ferramenta bruta é um hard reseek: pular o player pra uma posição corrigida e realinhar os dois pipelines ao mesmo ponto da timeline. Conserta qualquer tamanho de erro na hora, mas o usuário vê e ouve — um stutter, um momento repetido ou dropado. Você reserva isso pros desyncs grandes, os saltos que um empurrãozinho demoraria demais pra absorver.

O movimento estrutural é ressincronizar nas boundaries que o próprio stream já te dá. Uma discontinuity — um splice de anúncio, um marcador SCTE-35 — é um lugar onde uma pequena correção se esconde dentro de um corte que o telespectador já espera que seja meio sem-costura. Reancorar os dois pipelines à media timeline numa discontinuity é quase de graça em termos de percepção, enquanto fazer o mesmo pulo no meio de uma frase é gritante. Corrija onde a costura já está.

O tradeoff que você está de fato fazendo

Toda correção é uma escolha entre dois males não-tão-de-graça: um momento de conserto audível ou visível agora, ou deixar o drift correr torcendo pra ele ficar abaixo do limiar. Nenhum é invisível.

O julgamento é proporcional. Um drift pequeno e lento abaixo do limiar de percepção — deixe; a cura é mais perceptível que a doença. Um drift caminhando pra passar dos +45ms de áudio adiantado — empurre agora, antes que o olho do telespectador pegue. Um salto repentino saindo de um underrun — pegue o hard reseek e aceite o único stutter, porque a alternativa é horas de tudo estar sutilmente errado. Num stream que roda o dia inteiro, o objetivo não é sync perfeito a cada instante. É nunca deixar o erro crescer o bastante, ou durar o bastante, pra um humano dar nome ao que está incomodando.