Corrigir corretamente os vídeos codificados com a versão antiga do x264

5

Devido a um bug em versões antigas do x264, o vídeo h.264 transmite com as três propriedades a seguir:

  1. codificado com x264, compilação 150 ou anterior
  2. usando subamostragem de croma de 4: 4: 4
  3. bitstream não contém informações sobre a versão x264

não será reproduzido corretamente por muitos players de vídeo. Novas versões do player de vídeo mpv têm uma opção dedicada

--vd-lavc-assume-old-x264

abordando especificamente esse problema (consulte: link ).

No rastreador de bugs do FFmpeg , sugere-se adicionar o próprio SEI.h264 ao fluxo de vídeo (contendo x264 informações de versão, eu acho). Eu prefiro não confiar em tais hacks, então a minha pergunta é: Existe uma maneira "adequada" (idealmente usando o ffmpeg) para reparar os arquivos como se eles tivessem sido codificados com uma nova versão (fixa) do x264 no primeiro lugar ?

Obviamente, gostaria de permanecer (mais ou menos) vídeo qualidade e tamanho do arquivo . Se a recodificação for necessária, ela não deverá alterar nada, mas corrigir o comportamento de bugs da antiga implementação x264. (Mais informações: O relatório de bug dá um exemplo de arquivo corrompido. É conjecturado que o bug no x264 antigo era provavelmente introduzido aqui .)

    
por videoguy 10.03.2018 / 20:23

1 resposta

1

Obrigado por postar esta pergunta, isso me ajudou a entender a natureza do problema que eu estava tendo também. Eu tenho uma solução que parece funcionar.

No meu caso, estou usando o ffmpeg dos repositórios do Ubuntu. A última versão que conseguiu decodificar meus arquivos libx264 foi 2.8.6. Após atualizar para 2.8.14 ou 2.8.15, tive os problemas de decodificação que você descreve. Eu não quero recodificar meus vídeos antigos, só quero corrigir o cabeçalho para que o ffmpeg possa identificar corretamente o erro que foi introduzido durante a codificação original e reproduzi-los corretamente.

Então, primeiro eu baixei o binário estático que inclui a versão mais recente do ffmpeg, v4 . Eu vinculei esse binário a ffmpeg4 em meu sistema para que eu possa controlar qual versão estou usando. Precisamos de alguns dos novos recursos que foram introduzidos após o 2.8 (não sei exatamente quando). Se você já tem uma versão mais nova do ffmpeg instalada, use-a e substitua ffmpeg4 por ffmpeg nos comandos abaixo.

Agora, extraia o bitstream bruto do seu vídeo quebrado (chame-o BROKEN.mkv).

ffmpeg4 -i BROKEN.mkv -vcodec copy -an -bsf:v h264_mp4toannexb raw.h264

Não tenho certeza se o sinalizador h264_mp4toannexb é necessário, ele pode ser inserido automaticamente formato.

Agora, coloque o fluxo de bits em um novo contêiner mp4, e corrija as informações sobre a antiga compilação x264 com bugs no cabeçalho do SEI .

ffmpeg4 -r 30 -i raw.h264 -avoid_negative_ts 1 -bsf:v h264_metadata='sei_user_data=dc45e9bde6d948b7962cd820d923eeef+x264 - core 150' -c copy FIXED.mp4

O fluxo de bits não contém informações de registro de data e hora, portanto, você receberá muitos avisos aqui. Eu também achei que tinha que definir manualmente a taxa de quadros para 30fps ( -r 30 ) porque caso contrário, adivinhava alguma taxa de quadros variável entre 25 e 30fps. Eu não sei como extrair corretamente os timestamps ou mux-los corretamente no novo contêiner. Por favor, deixe-me saber se você tem uma correção! Muitas pessoas recomendam -fflags +genpts , mas isso não parecem fazer qualquer coisa para mim. Por fim, adicionei -avoid_negative_ts 1 para que o timestamp do primeiro quadro não seja negativo.

Finalmente, e isso é opcional, se você quiser colocar os resultados em um contêiner MKV, você pode fazer isso

ffmpeg4 -i FIXED.mp4 -c copy FIXED.mkv

Por que converte primeiro para MP4 e depois para MKV ? Parece que o contêiner MKV simplesmente se recusará a prosseguir sem timestamps, mas o MP4 fará isso e apenas emitirá avisos. Então você pode converter para MKV sem avisos.

Então, depois de tudo isso, eu tenho arquivos MP4 e MKV funcionando. No entanto, inspecionei alguns quadros e houve pequenas alterações (mudanças de luminância na ordem de ~ 2 níveis). Eu não entendo porque isso aconteceu porque isso deveria ter sido sem perdas. Por favor, deixe-me saber se você tem sugestões sobre como isso pode ser feito melhor.

Editar: notei que alguns dos meus timestamps eram negativos no contêiner MP4, começando em -0,066667s. Depois de se mudar para um contêiner MKV, todos os timestamps negativos se tornaram zeros. A adição de -output_ts_offset 0.066667 ao comando corrigiu isso e os iniciou em zero. Eu não entendo porque começou em -0,066667 embora.

Editar 2: Uma maneira melhor de remover carimbos de hora negativos é usar "-avoid_negative_ts 1" ao codificar o mp4.

    
por 29.10.2018 / 23:11

Tags