Corrija corretamente os vídeos que foram codificados com a versão antiga do x264

Corrija corretamente os vídeos que foram codificados com a versão antiga do x264

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

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

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

--vd-lavc-assume-old-x264

abordando especificamente esta questão (ver:https://mpv.io/manual/master/).

NoRastreador de bugs FFmpegsugere-se adicionar o SEI.h264 adequado ao stream de vídeo (contendo as informações da versão x264, eu acho). Prefiro não confiar nesses hacks, então minha pergunta é:Existe uma maneira "correta" (de preferência usando ffmpeg) de reparar os arquivos como se eles tivessem sido codificados com uma nova versão (corrigida) do x264 em primeiro lugar?

Obviamente eu gostaria de continuar (mais ou menos) em vídeoqualidadeetamanho do arquivo. Se a recodificação for necessária, ela não deverá mudar nada, apenas corrigir o comportamento de bugs da antiga implementação x264. (Mais informações:O relatório de errosdá um exemplo de arquivo corrompido. Conjectura-se que o bug no antigo x264 provavelmente foiintroduzido aqui.)

Responder1

Obrigado por postar esta pergunta, ela também me ajudou a entender a natureza do problema que eu estava tendo. 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 a 2.8.6. Após atualizar para 2.8.14 ou 2.8.15, tive os problemas de decodificação que você descreve. Não quero recodificar meus vídeos antigos, só quero consertar 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 eubaixou o binário estático que inclui a versão mais recente do ffmpeg, v4. Vinculei esse binário ffmpeg4em meu sistema para poder controlar qual versão estou usando. Precisamos de alguns dos novos recursos que foram introduzidos após o 2.8 (não tenho certeza de quando). Se você já possui uma versão mais recente do ffmpeg instalada, basta usá-la e substituí-la ffmpeg4nos ffmpegcomandos abaixo.

Agora, extraia o fluxo de bits bruto do seu vídeo quebrado (chame-o de 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,pode ser inserido automaticamentepara este formato.

Agora, coloque o bitstream em um novo contêiner mp4,e corrija as informações sobre a antiga compilação x264 com bugs no cabeçalho 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 carimbo de data/hora, então você receberá muitos avisos aqui. Também descobri que precisava definir manualmente a taxa de quadros para 30fps ( -r 30) porque, caso contrário, ele adivinhava alguma taxa de quadros variável entre 25 e 30fps. Não sei como extrair corretamente os carimbos de data/hora ou misturá-los corretamente no novo contêiner. Por favor, deixe-me saber se você tiver uma solução! Muita gente recomenda -fflags +genpts, mas isso nãoparece fazer qualquer coisapara mim. Por fim, adicionei -avoid_negative_ts 1para que o carimbo de data/hora do primeiro quadro não fosse 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 queconverta primeiro para MP4 e depois para MKV? Parece que o contêiner MKV simplesmente se recusará a prosseguir sem carimbos de data e hora, mas o MP4 fará isso e apenas emitirá avisos. Então você pode converter para MKV sem avisos.

Depois de tudo isso, tenho arquivos MP4 e MKV funcionando. No entanto, inspecionei alguns quadros e há pequenas alterações (alterações de luminância da ordem de ~2 níveis). Não entendo por que isso aconteceu porque 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 carimbos de data/hora eram negativos no contêiner MP4, começando em -0,066667s. Depois de mudar para um contêiner MKV, todos os carimbos de data/hora negativos tornaram-se zeros. Adicionar -output_ts_offset 0.066667ao comando corrigiu isso e fez com que eles começassem do zero. Não entendo por que começou em -0,066667.

Edição 2: A melhor maneira de remover carimbos de data/hora negativos é usar "-avoid_negative_ts 1" ao codificar o mp4.

informação relacionada