NALU Explorer - Ferramenta de visualização de NAL Units de streams de vídeo H.264
(nalu.funnify.org)Contexto de desenvolvimento e ideia de implementação
- Durante o desenvolvimento/depuração do codec de vídeo H.264, surgiu a necessidade de verificar visualmente a estrutura das NAL Units
- A análise é possível pela linha de comando do FFmpeg, mas eu queria clicar em cada NAL Unit e vê-la junto com a imagem real do frame
- Era necessário um parser Annex B que funcionasse diretamente no navegador, e com FFmpeg baseado em WebAssembly também seria possível decodificar os frames
- Foi desenvolvida a biblioteca própria
h264-parser, capaz de fazer parsing até SPS/PPS/Slice Header (publicada como pacote NPM) - Saída baseada na estrutura de sintaxe do padrão H.264: os campos são exibidos em estrutura hierárquica (indentação), seguindo fielmente a árvore de sintaxe de parsing da especificação ITU-T H.264
Como funciona
- Parsing Annex B: detecção dos start codes
00 00 00 01ou00 00 01 - Parsing de parâmetros:
- SPS/PPS: extração de parâmetros pelo parser
- Slice Header:
first_mb_in_slice,slice_type,pic_parameter_set_idetc. - Conformidade com a sintaxe do padrão: exibição fiel da estrutura da especificação H.264, como
nal_unit()→seq_parameter_set_rbsp()→vui_parameters()
- Decodificação de frames:
- Cálculo do intervalo de GOP ao qual a NAL Unit selecionada pertence (busca do IDR anterior/próximo)
- Reconstrução do Annex B junto com os cabeçalhos SPS/PPS
Principais recursos
Parsing
- Separação de NAL Units com base no Annex B Start Code
- Parsing por tipo de NAL Unit:
- Type 7 (SPS): profile, level, resolution, frame rate etc.
- Type 8 (PPS): entropy coding mode, slice groups etc.
- Type 1/5 (Slice): slice_type, first_mb_in_slice, frame_num etc.
- Type 6 (SEI): metadados (parsing limitado)
- Saída em árvore de sintaxe do padrão H.264: parsing condicional (blocos
if), estrutura hierárquica e ordem de leitura do bitstream exibidas exatamente como no padrão - Dump Hex de RBSP: permite verificar dados brutos em formato offset, bytes hex e ASCII
Exemplo de saída real do parsing de SPS:
nal_unit()
forbidden_zero_bit: 0
nal_ref_idc: 3
nal_unit_type: 7
seq_parameter_set_rbsp()
profile_idc: 100
constraint_set0_flag: 0
constraint_set1_flag: 0
constraint_set2_flag: 0
constraint_set3_flag: 0
constraint_set4_flag: 0
constraint_set5_flag: 0
reserved_zero_2bits: 0
...
Decodificação de frames
- Cálculo automático do intervalo por GOP (busca do IDR anterior/próximo)
- Busca automática dos cabeçalhos SPS/PPS e inserção prévia
- Extração de BMP com FFmpeg.wasm e renderização em Canvas
Extração de dados
- Download de NAL Unit individual (Annex B Start Code + rawData)
- Download por unidade de GOP (SPS/PPS + NAL Units do intervalo do GOP)
- Visualização das NAL Units em formato de timeline (cores por tipo, tamanho proporcional)
Limitações
- Slice Data não suportado: o parsing vai apenas até o Slice Header. A área
slice_data, como dados de macroblocos, MVD e coeficientes residuais, não é analisada - Formato AVC não validado: o código de parsing baseado em comprimento foi implementado, mas não foi testado
- Carregamento inicial do FFmpeg.wasm: no primeiro uso, é feito o download de uma biblioteca de ~10-20MB
Links
- Demo ao vivo: https://nalu.funnify.org
- Biblioteca NPM: https://www.npmjs.com/package/h264-parser
Ainda não há comentários.