この質問を投稿してくれてありがとう、それは私が抱えていた問題の性質を理解するのに役立ちました。私はうまくいくように見える解決策を持っています。
私の場合、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」を使用することです。