古いバージョンのx264でエンコードされたビデオを適切に修正します

古いバージョンのx264でエンコードされたビデオを適切に修正します

古いバージョンの x264 のバグにより、h.264 ビデオ ストリームには次の 3 つの特性があります。

  1. x264 ビルド 150 以前でエンコード
  2. 4:4:4クロマサブサンプリングを使用
  3. ビットストリームに x264 バージョン情報が含まれていない

多くのビデオプレーヤーでは正しく再生されません。ビデオプレーヤーの新しいバージョンにはmpv専用のオプションがあります

--vd-lavc-assume-old-x264

この問題に具体的に対処する(参照:https://mpv.io/manual/master/)。

上のFFmpeg バグトラッカー適切な SEI.h264 をビデオ ストリームに追加することが推奨されています (おそらく x264 バージョン情報が含まれています)。私はそのようなハックに頼りたくないので、質問は次のとおりです。そもそも新しい(修正された)バージョンのx264でエンコードされたかのようにファイルを修復する「適切な」方法(理想的にはffmpegを使用)はありますか??

明らかに私は(多かれ少なかれ)ビデオのままでいたい品質そしてファイルサイズ再エンコードが必要な場合、古い x264 実装のバグのある動作を修正する以外は何も変更する必要はありません。(詳細情報:バグレポート破損したファイルの例を示します。古いx264のバグはおそらくここで紹介

答え1

この質問を投稿していただきありがとうございます。この質問のおかげで、私も抱えていた問題の性質を理解することができました。うまくいくと思われる解決策があります。

私の場合、Ubuntu リポジトリの ffmpeg を使用しています。libx264 ファイルをデコードできた最後のバージョンは 2.8.6 でした。2.8.14 または 2.8.15 にアップグレードした後、説明されているデコード問題が発生しました。古いビデオを再エンコードしたいわけではなく、元のエンコード中に発生したエラーを ffmpeg が適切に識別して適切に再生できるようにヘッダーを修正したいだけです。

まず最初にffmpegの最新バージョンv4を含む静的バイナリをダウンロードしましたffmpeg4。使用しているバージョンを制御できるように、このバイナリをシステムにリンクしました。2.8 以降に導入された (いつ導入されたかは正確にはわかりません) 新機能がいくつか必要です。ffmpeg の新しいバージョンが既にインストールされている場合は、それを使用して、以下のコマンドの を にffmpeg4置き換えてください。ffmpeg

次に、破損したビデオから生のビットストリームを抽出します (BROKEN.mkv と呼びます)。

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

h264_mp4toannexbフラグが必要かどうかはわかりませんが、自動的に挿入される可能性がありますこの形式の場合。

さて、ビットストリームを新しいmp4コンテナに入れます。SEIヘッダー内の古いバグのあるx264ビルドに関する情報を修正しました

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

ビットストリームにはタイムスタンプ情報が含まれていないため、大量の警告が表示されます。また、フレームレートを手動で30fps ( -r 30) に設定する必要があることがわかりました。そうしないと、25fpsから30fpsの間の可変フレームレートが推測されます。タイムスタンプを適切に抽出する方法や、新しいコンテナに正しく多重化する方法がありません。修正方法があれば教えてください。多くの人が推奨しています-fflags +genptsが、これは役に立ちません。何でもするようだ-avoid_negative_ts 1私の場合は、最後に、最初のフレームのタイムスタンプが負にならないようにするために追加しました。

最後に、これはオプションですが、結果をMKVコンテナに入れたい場合は、次のようにします。

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

なぜまずMP4に変換し、次にMKVに変換します? MKV コンテナはタイムスタンプがないと単純に続行を拒否するようです。しかし、MP4 はタイムスタンプなしで続行を拒否し、警告のみを発します。その後、警告なしで MKV に変換できます。

結局、MP4 と MKV ファイルが機能するようになりました。ただし、いくつかのフレームを調べたところ、小さな変化 (輝度の変化が約 2 レベル) がありました。ロスレスであるはずなのに、なぜこのようなことが起こるのかわかりません。これをより良く行う方法についてご提案がありましたら、お知らせください。

編集: MP4 コンテナ内のタイムスタンプの一部が負で、-0.066667 秒から始まっていることに気付きました。MKV コンテナに移動した後、負のタイムスタンプはすべてゼロになりました。-output_ts_offset 0.066667コマンドに追加することでこの問題は修正され、ゼロから始まるようになりました。ただし、なぜ -0.066667 から始まったのかはわかりません。

編集 2: 負のタイムスタンプを削除するより良い方法は、mp4 をエンコードするときに「-avoid_negative_ts 1」を使用することです。

関連情報