Skip to content

Legendas ocultas

As legendas ocultas (closed captions, CC) viajam dentro do próprio vídeo, e não como uma faixa separada: nos dados auxiliares de cada quadro (SEI para H.264 e HEVC, user data para MPEG-2, metadados OBU para AV1). Elas são entendidas por TVs e decodificadores, mas um reprodutor de navegador não consegue mostrar esse texto: HLS e DASH esperam as legendas como uma faixa separada.

O Sapsan faz as duas coisas: passa as legendas ocultas dentro do vídeo como estão e as decodifica numa faixa de legendas WebVTT.

Modos de processamento

O modo é definido pelo campo mode da seção closed_captions do stream. Ele controla apenas a entrega — a decodificação e a gravação no arquivo acontecem sempre:

  • passthrough (padrão) — as legendas ocultas ficam dentro do vídeo e são anunciadas nos manifestos como closed captions. Não há faixa de legendas nos manifestos.
  • extract — uma faixa de legendas no lugar das legendas ocultas embutidas: o texto é decodificado numa faixa WebVTT, enquanto as legendas ocultas são cortadas do vídeo de saída e não são anunciadas como closed captions.
  • both — as duas ao mesmo tempo: as legendas ocultas viajam dentro do vídeo e são anunciadas, e junto delas vai uma faixa de legendas.

Configuração

streams:
  - name: news
    inputs:
      - url: udp://239.0.0.1:1234
    closed_captions:
      mode: extract
      services:
        CC1:
          language: eng
          name: English
        SERVICE3:
          language: spa
          name: Espanol

A seção services é opcional e resolve duas tarefas:

  • define o nome e o idioma do item de menu no reprodutor. Sem ela, o nome é deduzido do stream: o idioma anunciado pelo serviço e, caso contrário, o endereço do serviço (CC1, SERVICE3);
  • pré-anuncia o serviço nos modos extract e both: um serviço listado ganha sua faixa desde o primeiro segmento, sem esperar o primeiro cue. Isso importa para reprodutores que leem a lista de faixas uma única vez na inicialização: um serviço que começa a falar no décimo minuto apareceria no menu só depois de reabrir o stream.

A chave do serviço é CC1CC4 para CEA-608 e SERVICE1SERVICE63 para CEA-708.

O que o reprodutor recebe

Cada serviço que fala vira sua própria faixa de texto com um número fixo: CC1CC4t1t4, SERVICE1SERVICE63t5t67. O número pertence ao serviço e não muda quando o stream reinicia, por isso os links para uma faixa continuam funcionando.

No HLS a faixa chega como um rendition EXT-X-MEDIA com TYPE=SUBTITLES; no DASH, como um AdaptationSet com contentType="text" e mimeType="text/vtt". Os segmentos da faixa ficam em endereços como:

/streaming/v/news/subtitles/t1/1738245600000.vtt

O último segmento do caminho é o início da janela em milissegundos; o fim da janela é decidido pelo servidor pela mesma grade de segmentos do vídeo. Uma janela vazia é um segmento WebVTT vazio válido, não um erro: numa pausa entre cues a faixa não pode se romper.

As legendas são servidas ao vivo, no rewind e do arquivo. Os cues decodificados são sempre gravados no arquivo, independentemente do modo — por isso ligar o extract funciona retroativamente: as legendas aparecem também no arquivo já gravado.

A limitação do modo extract nas saídas TS

No modo extract as legendas ocultas são cortadas do vídeo de saída por completo — em todas as saídas de uma vez, MPEG-TS incluso: push por udp/rtp/srt, segmentos .ts de HLS e tshttp. Numa faixa de texto não há como viajar dentro do MPEG-TS, então neste modo um consumidor de uma saída TS fica sem legendas de todo.

Se o mesmo stream é assistido num navegador e puxado por MPEG-TS ao mesmo tempo, use both: ele mantém as legendas ocultas dentro do vídeo para o consumidor do TS e adiciona a faixa para o navegador.

Migração do Flussonic Media Server

No Flussonic legacy a opção cc.extract não removia as legendas ocultas do vídeo — ela ligava a extração em adição às embutidas. O equivalente direto dela no Sapsan é, portanto, mode: both, e não mode: extract.

Flussonic Sapsan Comportamento
opção não definida mode: passthrough legendas ocultas dentro do vídeo, sem faixa
cc.extract mode: both legendas ocultas dentro do vídeo e uma faixa de legendas
mode: extract comportamento estrito novo: uma faixa no lugar das legendas ocultas embutidas

mode: extract é um comportamento novo, sem análogo no Flussonic legacy. Escolha-o quando nenhum dos seus consumidores precisar das legendas ocultas embutidas: ele remove o item duplicado do menu do reprodutor (as mesmas legendas como closed captions e como faixa) e economiza espaço nos quadros de vídeo.

Verificação

Para confirmar que a faixa apareceu, verifique a playlist mestra:

curl -s http://localhost:8080/streaming/v/news/index.m3u8 | grep SUBTITLES

e o conteúdo do segmento:

curl -s http://localhost:8080/streaming/v/news/subtitles/t1/1738245600000.vtt

Os serviços detectados e o número da faixa de cada um aparecem nas estatísticas do stream (GET /streaming/api/v4/streams/stats/news, a seção captions).

O trabalho do pipeline é mostrado pelas métricas do Prometheus com o prefixo stream_captions_: stream_captions_cc_pairs_total — se as legendas ocultas chegam ao servidor de todo; stream_captions_cues_decoded_total — quantos cues foram decodificados; stream_captions_cues_delivered_total — quantos entraram na faixa. Um stream_captions_unrecognized_payloads_total crescente significa que o stream carrega um wrapper de legendas ocultas que não conhecemos; comunique isso ao suporte.