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
extracteboth: 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 é CC1…CC4 para CEA-608 e SERVICE1…SERVICE63 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: CC1…CC4 → t1…t4, SERVICE1…SERVICE63 → t5…t67. 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.