FFmpegを使い、ファイル数500弱のmp4を結合して、1つの動画を作成しようと試みた。ところが、何やら大量のメッセージが表示され、総時間の4倍ぐらいあるキングサイズの動画が誕生。うろたえながらも動画を再生してみると、映像は止まったまま動かず、まもなくメディアプレイヤーは応答不能となった。
このあと、正常に再生できる動画の作成に成功するまで、何をやったかというお話。
はじめに
この記事の前提部分。
H265/AACでエンコードしたmp4ファイルが500ほどある。-c:a aac -b:a 128k -c:v libx265 -crf 17という設定でエンコードしてある。映像の幅と高さ、フレームレートは同じ。音声のチャンネルやサンプルレートも同一である。
これらのファイルをffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4というコマンドで結合している。
大量のメッセージ
結合処理が始まってすぐ、ずらずらと次のようなメッセージが表示され始めた。
Non-monotonous DTS in output stream 0:1; previous: 1060864, current: 1059899; changing to 1060865. This may result in incorrect timestamps in the output file.
このメッセージは、-v errorを付けると表示されないので、エラーということではないようだ。調べてみると、個々のファイルのパラメータがぴったり合致していない場合に表示されるらしい。
合致していないって、違っているのはビットレートくらいだろう。これで不適正といわれたらもう手の施しようがない。あとで結合するときは、可変エンコードしてはいけないということを学んだ。
個々のファイルをどうやって確認するか
パラメータを合わせれば良さそうなのはわかったが、また500ものファイルをエンコードし直すというのは避けたい。かといって、各ファイルのパラメータをチェックするというのも面倒だ。そういうのをリストアップできるやつがあるのだろうが、うちのPCにはインストールされていない。
着目するパラメーターがわかっているなら、FFmpegの出力データから特定のワードを検索するなどできるかも知れない。しかし、この道には門外漢なので、目視で舐めてゆくしかない。人力で500はキツいが。
そこで、メディアプレイヤーに全ファイルをフォルダごとぶち込み、メディア情報ウィンドウを開いたまま動画を再生することにした。 これで動画を見がてら確認もできる。
ちなみに、VLCでは「ツール」からメディア情報ウィンドウを開くことができる。
原因判明
割とすぐ相違点を見つけることができた。映像と音声のストリーム番号がバラバラなのだ。
例えばffmpeg -i input.mp4を実行すると、インプットファイルの情報が出力される。このとき、普通の動画ファイル(映像と音声を含む)であれば、「Stream #0:0(und): Video:」「Stream #0:1(und): Audio:」のような項目が見つかるはずだ。この「Stream #0:0」というのは「インプット番号0:ストリーム番号0」を表している。ストリーム番号はコロンの右側なので間違えないようにしたい。
話を戻すが、ストリーム番号0に映像が入っていたり、あるいは音声が入っていたりと、ファイルによって違っていたのである。正常に再生できない動画ができあがった原因はこれだろう。ごめん、違ってるとこあったわ。
なぜストリーム番号が変わったか
調べたところ、エンコード時にフィルタを使っていると、ストリーム番号が変わることがあるらしい。確かに、今回の動画には声とBGMをamixで合成したものが含まれている。フィルタを使う以上は、再エンコードしても結果は同じということだ。
じゃあ、エンコード時にストリーム番号を固定できないかと調べてみたが、方法はわからず。それならば、ストリーム番号を入れ替えられないかとも調べてみたが、同じく方法はわからなかった。
動画をバラして戻す
前述の通り、フィルタを使うとストリーム番号が変わることがあるらしい。それならば逆説的に、何の変哲もない通常の処理なら、ストリーム番号は一定になると考えられる。そこで、映像と音声をコンテナから取り出し、そのまま新しいコンテナに入れるという処理を行った。陳列されている商品を手に取り、違う棚に戻す。おいやめろ。
ffmpeg -i 000.mp4 -map 0:v -map 0:a -c copy new_000.mp4 ffmpeg -i 001.mp4 -map 0:v -map 0:a -c copy new_001.mp4 …
コンテナから映像や音声を取り出すことをdemux、コンテナに入れることをmuxということがある。この処理はエンコードではないので、時間はかからない。品質も劣化しない。できあがった動画をいくつかピックアップして調べてみると、どうやらストリーム番号は揃ってくれているようだ。
再処理したファイルを結合してみると、無事に再生できる動画ができあがった。
おわりに
普通のmp4ファイルならば、今回のように無劣化で分解→戻すことができる。ただ、別のコンテナ・フォーマットでは、もしかすると事情が違うかも知れないということを書き添えておく。
ところで、くだんのメッセージは、あいかわらず大量に表示されていた。もう完全にお手上げである。
0 件のコメント:
コメントを投稿