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


6

x264の古いバージョンのバグにより、次の3つのプロパティを持つh.264ビデオストリーム:

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

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

--vd-lavc-assume-old-x264

特にこの問題に対処していますhttps://mpv.io/manual/master/を参照)。

のFFmpegのバグトラッカーには、ビデオストリーム(私が推測する、x264のバージョン情報を含む)への適切なSEI.h264を追加することが提案されています。私はそのようなハッキングに依存しないことを好むので、私の質問は、最初の場所で新しい(修正された)バージョンのx264でエンコードされているかのようにファイルを修復する「適切な」方法(理想的にはffmpegを使用)はありますか?

明らかに、ビデオ品質ファイルサイズを(多かれ少なかれ)維持したいと思います。再エンコードが必要な場合は、古いx264実装のバグのある動作を修正する以外、何も変更しないでください。(詳細:バグレポートには破損したファイルの例が記載されています。古いx264のバグはおそらくここに導入されたと推測されます。)


いいえ。ffmpegはこのようなストリームを正しくデコードできないため、再エンコードの結果にエラーが発生します。SEI挿入の何が問題になっていますか?
ギャン

@Gyan正しいSEIを挿入するために必要なコマンドを提供してください。
cxrodgers

回答:


2

この質問を投稿してくれてありがとう、それは私が抱えていた問題の性質を理解するのに役立ちました。私はうまくいくように見える解決策を持っています。

私の場合、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)に手動で設定する必要がありました。そうしないと、25〜30fpsの可変フレームレートが推測されたためです。タイムスタンプを適切に抽出する方法や、新しいコンテナに正しく多重化する方法がわかりません。修正がある場合はお知らせください!多くの人がお勧めします-fflags +genptsが、これは私には何もしないようです。最後に、-avoid_negative_ts 1最初のフレームのタイムスタンプを非負にするために追加しました。

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

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

最初にMP4に変換してからMKVに変換するのはなぜですか?MKVコンテナはタイムスタンプなしで続行することを単に拒否するようですが、MP4はそれを行い、警告を発行するだけです。その後、警告なしでMKVに変換できます。

そのため、これらすべての作業後、MP4およびMKVファイルを使用できます。しかし、私はいくつかのフレームを検査し、小さな変更があります(約2レベルの輝度の変更)。これはロスレスであるはずだったので、なぜこれが起こったのか理解できません。これをどのように改善できるかについての提案があれば教えてください。

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

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


@Gyanタイムスタンプについて多くの素晴らしい回答を投稿しているようですが、生のh264ストリームを提供する際にコンテナ内のタイムスタンプを適切に指定する方法を提案してください。ヒントをありがとう!!
-cxrodgers
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.