AviSynthでMPEG2-TSを継ぎ接ぎにしてエンコする場合の話

AviSynth+ 3.7.0(r3393 2021年頭に自ビルドした物だった気がする)
DGIndex(https://github.com/maki-rxrz/DGMPGDec の確かlatest )
aacfaw(http://www.rutice.net/ )

で確認してますが、多分最近のバージョンならこの辺は変わらないと思います。

入力プラグインによっては音声が映像より長いことがあります。少なくともaacfawでは確認しました。
クローズドソースなのもあって実際のコードを確認したり逆汗したりはしてませんが、DELAY値分ずらしただけ終端に無音区間がついている可能性があります。

2023/05/04追記
LWLibavAudioSourceで食わせた直後とaacfawで食わせた直後でサンプル数が一致していたのが理由としていましたが、サンプル数の差が16163サンプルで48000で割ると大体336ms、サンプルに使ってたソースのDELAYが-351msらしいので大体そんな感じっぽいです。

一応ぱっと見ではDGIndexでは長さが一致するような出力になっていましたが、深追いはしていないためどちらにせよ調整されていなかった場合の事をメモ書きしておきます。
最初にくっつけたいor最終フレームまで使ってくっつけたいとなった場合、くっつける前にTrim(0,0)を唱えてください。

これがMPEG2Source()とAudioDub(aacfaw())しただけの場合

こっちがその後にTrim(0,0)した後。ちなみにLWLibavAudioSource+DelayAudioしたときは発生しませんでした。aacfaw使うならちゃんと考えて使った方が良いと思います。

Trim関数の第二引数(厳密には暗黙でclipの引数もあるので3つ目だったりしますが2つ目に明示している物という意味でお願いします)の0は最終fを示すわけですが、これが果たしてカットしない処理を行っているのか、ちゃんと最終フレームの終端処理を行っているのかで大きく変わるところで確認してみたところ。後者でした。

映像と音声の長さがそこそこ異なる場合があり得るので、基本的に映像の最終fまで使う場合でも終端処理は行うべきです。単体ならそのぐらいで済みますが、この後に何かしらひっつける場合にはこの差が問題になることがあります。というのが話したかった内容なので、これより先は気になる人が読めば良いと思います。人に説明したものを書き直してるだけなので。

悪い例は、

MPEG2Source("a.ts")+MPEG2Source("b.ts")
AudioDub(aacfaw("a.aac")+aacfaw("b.aac"))

で、この場合は先程の説明通りa.tsとa.aacの長さが一致してないままの可能性があるので音がずれる可能性があります。

映像a 12:00.00 + 映像b 10:00.00
音声a 12:00.45 + 音声b 10:00.24
とか書くとわかりやすいんですがこのように長さが一致していなかった場合、ソースaの終わりがズレているとbの頭の始点の違いの分だけ音ズレが発生するみたいな感じです。

aacfawだとちょっと分かりづらいのですが、AviSynthだと入力ソースを再生するときみたいに映像と音声は同期している保証は有りません。プラグインの実装に寄ると思いますがおそらく単純にソースをペイロードを頭から単純に読むだけの場合が多いはずです。
例としては、aacfawではファイル名のDELAYを参考に勝手にずらしてくれるのでDelayAudioは不要ですし、LWLibavAudioSourceのav_sync=trueはLWLibavVideoSourceで読んでいる前提での同期をとっていたりしてます。後者に関してはlwindex.cをav_syncでgrepして貰えればcalculate_av_gapでやってくれてるのが分かるはずです。
ただ、これらは始点をあわせるための諸々であることを理解しておく必要があります。
ちなみにdropしたTSだと音声がズレることがあるのはこれが原因です。各種Demuxer(例えばDGIndexやts_parserとか)の実装次第ですが、欠けたフレーム分そのまま頭にズレてしまう可能性があります。LWLibavのav_syncならまあなんとかなってくれるかもしれませんが(未確認)、AAC単体で読む場合でしたらts2aacで破損したフレームの補完を行うことを推奨しておきます。それでも欠けた長さのパディングが正しく行われない可能性がありそうですし、欠けた分のフレームは戻らないので破損していない素材を用意するべきですが。

良い例は

a=MPEG2Source("a.ts").AudioDub(LWLibavAudioSource("a.aac").DelayAudio(-0.123).Trim(0,0)
b=MPEG2Source("b.ts").AudioDub(LWLibavAudioSource("b.aac").DelayAudio(-0.456).Trim(0,0)
a+b
(以下略)

でもいいです。これで、いつも通り扱ってOKになります。
厳密には微妙にズレる可能性はありますがそれは音声のサンプリングレート次第で、どこまで映像の終端位置まで寄れるかになるはずなので、これはどのソースでも発生しますし、48kHzの場合、逆数で割ってあげると0.0208ms。強制切り捨て切り上げどちらかを行ったとしてもそのぐらいしかズレないので常識的なレベルのカット数なら困らないはずです。FakeAacWav使ってるときの方が扱う単位が大きいのでこっちは割と現実的ですが(国内の放送波で使われてるAACだと1024サンプル/フレームが主流ですし)

正直継ぎ接ぎするようなソースなら使うべきではないと思いますが、もしFakeAacWav(aacfaw等の互換実装も含みます)使ってる場合はその辺が理由で編集点を一つでも減らしたほうがいいので、最後まで編集してからくっつけることをおすすめいたします。

もしかしたら、これAviSynthに限った話ではないのでは?といわれると他の環境でもあり得る話なので気をつけてみた方が良いんじゃないのかなと思います。まあ早々そんなことはないと思いますが(何も知らない人に触らせるなら最終fで音声ぶった切るのが適切だとは思いますが選択の余地はあるべきです)

おわり

おまけ

もし音声の方が短い場合は無音PCMを欠損分終端に足してあげれば事なきを得られるはずです(未確認)
あと、ts_parserでどうなるかは確認してません。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください