X264の古いバージョンのバグのため、次の3つのプロパティを持つh.264ビデオストリーム。
多くのビデオプレーヤーでは正しく再生されません。ビデオプレーヤーの新しいバージョンmpv
には専用のオプションがあります
--vd-lavc-assume-old-x264
特にこの問題に対処します(参照: https://mpv.io/manual/master/ )。
FFmpegバグトラッカー では、適切なSEI.h264をビデオストリームに追加することをお勧めします(x264バージョン情報を含むと思います)。私はそのようなハックに頼りたくないので、私の質問は次のとおりです:ファイルを新しい(修正済み)でエンコードされているかのように修復する「適切な」方法(理想的にはffmpegを使用)はありますか)そもそもx264のバージョン?
明らかに、私は(多かれ少なかれ)ビデオ品質とファイルサイズを残したいと思います。再エンコードが必要な場合は、古いx264実装のバグのある動作を修正するだけです。 (詳細情報: バグレポート は破損したファイルの例を示しています。古いx264のバグはおそらく ここで紹介 であると推測されます。)
この質問を投稿していただきありがとうございます。私も抱えていた問題の性質を理解するのに役立ちました。私はうまくいくように見える解決策を持っています。
私の場合、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
ビットストリームにはタイムスタンプ情報が含まれていないため、ここで大量の警告が表示されます。また、フレームレートを手動で30 fps(-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_ts1」を使用することです。