AviUtl で出力したときにどのような場合に音ずれするのか

2022年現在はrigaya氏のブログを参照。
rigayaの日記兼メモ帳 AACエンコーダディレイとx264guiExでの対処方法について

検証方法


  • 3つの出力方法でエンコードする
  • 1つ目は ffmpeg 単体でエンコード、2つ目が AviUtl と拡張x264出力プラグインEx、3つ目が AviUtl と ffmpegOut
  • エンコード素材には固定フレームレートの動画と、音声を音声波形の映像にエンコードした動画の2種類
  • 映像エンコーダには x264(libx264)を使い、音声エンコーダにはコーデックに各種AACと比較のために Vorbis, lame(libmp3lame), nellymoser, alac, flac を使った

音声波形の動画は音声から波形を映像出力したもので、波形の開始と音声の開始が一致するものである。フレームレートは厳密には指定できず、可変フレームレートになる。1秒だけなら音ずれはほぼないが、時間が長いのを remux するとフレームレートが一定でないので映像と音声がずれる(遅れる)。

動画素材の作り方(動画でも音声でも可能)
r=fps(数値) 動画の場合は動画と同じ値にする。音声は100にする。
しかし、設定した値と同じになることはあまりない。
ffmpeg -i input.mp4 -filter_complex showwaves=r=30 -t 1 -acodec copy output.mkv

詳しい使い方:音声波形を表示する showspectrum, showwaves の使い方

結果のまとめ


  • ffmpeg 単体での結果は libaacplus 以外は正常である
  • AviUtl から mp4box で mux するとすべてのAACエンコーダで音声の開始が遅れる
  • AviUtl で編集した拡張x264出力プラグインExで出力する場合は nero(lc, he, h2_v2)か qaac_lc でエンコードして、出力コンテナは mkv。そして、ffmpeg で remux して mp4 に変える。それ以外のAACエンコーダは少し開始が遅れる。これは 音声エンコーダの遅延問題 の通りになる
    remux コマンド:ffmpeg -i in.mkv -c copy out.mp4

    AviUtl で編集して拡張x264出力プラグインExで音声を AAC で出力する場合は nero(lc, he, h2_v2)か qaac_lc の mp4 で出力する場合はディレイカット「音声カット」 を指定する。ディレイカット「音声カット」 を指定しない場合は少し開始が遅れる(初期ディレイ)。これは 音声エンコーダの遅延問題 の通りになる。mkv で出力する場合はディレイカット「補正なし」でよい
  • libaacplus は3つの出力方法の全てにおいて音声がずれる
  • AviUtl ffmpegOut で出力する場合は libfaac と libaacplus 以外は正常である
  • AviUtl ffmpegOut で音声エンコーダに libfaac を使い mkvコンテナに入れて AviUtl で確認したところ、シークバーを戻すと音声波形が消える。ffmpeg 単体で libfaac でエンコードした場合にはそうならない
  • 音声波形の動画を mkv から mp4 に remux すると可変フレームレートなので映像と音声がずれる。なのでこの方法で確認する場合は影響を最小限にするために1秒にしている
  • 拡張x264出力プラグインExで出力した mkv から mp4 に remux すると初めはほぼ一致し、後ろのほうが mkv より少しずれる

つまりどうしたら良いか


  • ffmpeg 単体の場合は libaacplus を使わなければ良い
  • 拡張x264出力プラグインEx の場合で mp4 コンテナで出力する必要がある場合は mkv で一度出力して ffmpeg で remux する ディレイカット「音声カット」 を指定する。
  • ffmpegOut の場合は libaacplus を使わなければ良い

使用ツール


  • AviUtl 1.0
  • ffmpegOut 0.0.4
  • 拡張x264出力プラグインEx 1.7.5
  • L-SMASH_Works_r559_plugin
  • MP4Box_0.4.6-r3745
  • mkvtoolnix-unicode-6.1.0
  • エンコーダは 音声エンコーダの遅延問題 と同じ

コマンドとエンコーダ


mkvコンテナとflvコンテナ
ffmpeg -i input -vcodec libx264 -acodec aac -strict -2 -y ffmpeg_aac.mkv
ffmpeg -i input -vcodec libx264 -acodec libfaac -y libfaac.mkv
ffmpeg -i input -vcodec libx264 -acodec libfdk_aac -y libfdk-lc.mkv
ffmpeg -i input -vcodec libx264 -acodec libfdk_aac -profile:a aac_he -ab 70k -y libfdk-he.mkv
ffmpeg -i input -vcodec libx264 -acodec libfdk_aac -profile:a aac_he_v2 -signaling explicit_sbr -ab 20k -y libfdk-he2.mkv
ffmpeg -i input -vcodec libx264 -acodec libaacplus -ab 20k -y libaacplus_he2.mkv
ffmpeg -i input -vcodec libx264 -acodec libaacplus -ab 70k -y libaacplus_he.mkv
ffmpeg -i input -vcodec libx264 -acodec vorbis -strict -2 -y vorbis.mkv
ffmpeg -i input -vcodec libx264 -acodec nellymoser -ac 1 -y nellymoser.flv
ffmpeg -i input -vcodec libx264 -acodec libmp3lame -y libmp3lame.mkv
ffmpeg -i input -vcodec libx264 -acodec alac -y ffmpeg_alac.mkv
ffmpeg -i input -vcodec libx264 -acodec flac -y ffmpeg_flac.mkv

mp4コンテナ
ffmpeg -i input -vcodec libx264 -acodec aac -strict -2 -y ffmpeg_aac.mp4
ffmpeg -i input -vcodec libx264 -acodec libfaac -y libfaac.mp4
ffmpeg -i input -vcodec libx264 -acodec libfdk_aac -y libfdk-lc.mp4
ffmpeg -i input -vcodec libx264 -acodec libfdk_aac -profile:a aac_he -ab 70k -y libfdk-he.mp4
ffmpeg -i input -vcodec libx264 -acodec libfdk_aac -profile:a aac_he_v2 -signaling explicit_sbr -ab 20k -y libfdk-he2.mp4
ffmpeg -i input -vcodec libx264 -acodec libaacplus -ab 20k -y libaacplus_he2.mp4
ffmpeg -i input -vcodec libx264 -acodec libaacplus -ab 70k -y libaacplus_he.mp4

  • AviUtl で 拡張x264出力
    出力コンテナは mkv と mp4 の双方で確認

    nero(lc, he. h2_v2)
    lame
    ac3
    qaac(lc, he)
    refalac
    fdk_aac(lc, he. h2_v2)
    flac

  • AviUtl で ffmpeg パイプ出力
    音声エンコーダは「WAV」を選択し、ffmpeg で動画と音声を一緒にエンコードする
    出力コンテナは mkv と mp4 の双方と flv で確認

    -acodec aac -strict -2
    -acodec libfaac
    -acodec libfdk_aac -ab 128k -afterburner 1
    -acodec libfdk_aac -profile:a aac_he -ab 70k -afterburner 1
    -acodec libfdk_aac -profile:a aac_he_v2 -signaling explicit_sbr -ab 20k -afterburner 1
    -acodec libaacplus -ab 70k
    -acodec libaacplus -ab 20k
    -acodec vorbis -strict -2
    -acodec nellymoser -ac 1
    -acodec libmp3lame
    -acodec alac
    -acodec flac

追記 2013/08/03
外部 muxer を無効にして音声の一時ファイル(または外部ファイル)をコピーし x264_LSMAH でエンコードと マルチプレクス し、priming を指定することでズレを修正できるそうだ。今は検証する時間が取れないので検証は後回し。

priming の値は LSMAH の作者である、muken氏のページに書いてある。
寒咲豊呼 's page | Online Video Editing | Sprasia

各AAC encoderのpriming frames

iTunes/QuickTime: 2112
faac: 1024
Nero: 2624

対応するAAC decoderはそれぞれのpriming framesを仮定し、デコード時に除外するため、注意が必要。

例えばfaacでエンコードされたAACをiTunesでデコードすると 1024 - 2112 = 1088samples分のエンコード前のデータ成分が先頭から欠落する。

priming framesはmp4のmeta領域にiTunSMPBが存在するならば、2番目の32bit fieldにその値が示されている。




40n: priming samples (AAC encoder)

QuickTime: 2112
Nero: LC = 2624, HE = 2336, HEv2 = 2808
faac: 1024
ffaac (libavcodec's aac): 1024
libvo-aacenc: 1600



Audio Priming - Handling Encoder Delay in AAC
ffmpeg wrong audio file after conversion in AAC - Stack Overflow

AAC requires data beyond the source PCM audio samples in order to correctly encode and decode audio samples due to the nature of the encoding algorithm. AAC encoding uses a transform over consecutive sets of 2048 audio samples, applied every 1024 audio samples (overlapped). For correct audio to be decoded, both transforms for any period of 1024 audio samples are needed. For this reason, encoders add at least 1024 samples of silence before the first ‘true’ audio sample, and often add more. This is called variously “priming”, “priming samples”, or “encoder delay”.

The lack of explicit representation for encoder delay and remainder samples is not a problem unique to AAC encoding. With MPEG-4 and ADTS/MPEG-2 bitstreams and file containers, there is still no satisfactory, explicit representation for either the encoder delay or remainder samples. MP3 also has these data dependencies and delays in its bitstream, as do proprietary codecs such as AC-3 and others.



L-SMASHの簡易(?)FAQ

Q. muxerのトラックオプション encoder delay (priming samples)ってなんですか?
A. MDCTという技術を使う音声コーデックでは、二つの隣り合った音声フレームが意図した音を出すのに必要なデータを共有しています。
これにより、最初の音声フレームからは完全な音を出すことができません。
そのために、余白的なデータを最初の音声フレームとして付加してデコーダに復号させ、
次の音声フレーム以降に完全な音を出すことを実現しています。
この時に付加した余分なデータの長さを表すのがencoder delayです。
これをファイルに記述することで、再生時にこの部分の音をスキップすることを明示でき、ギャップレスを実現します。
iTunes/QuickTimeのAACエンコーダでは2112サンプル分がencoder delayとなっています。
他にもNero AACエンコーダでは2624サンプル分といったように、エンコーダや設定によってその大きさが異なります。
これとは別に、ランダムアクセス(シーク)においてもMDCTによる不完全な音声は構築されるので、
ランダムアクセスのたびに実際に再生したい音声フレームより1つ前のフレームからデコードしておく必要があります。
その明示方法はiso2以降のISO Base MediaまたはMOVで定義されているので、プレイヤーまたはdemuxerに伝えるには, --isom-version 2または--file-format movが必要です。



EncoderDelay · uupaa/AAC.js Wiki
LAME Technical FAQ
Audio Priming - Handling Encoder Delay in AAC

追記 2014/12/19
拡張x264 出力 の設定で音声エンコードでディレイカット「音声カット」を指定することで音声の遅延分をカットできるに伴って記事を書き直した。
関連記事

コメント

名無しさん

L-SMASHのmp4muxでも遅延が出るね・・・
遅延って普通無い物なんじゃないのか?ただ合成してるわけだしさ

素人意見だから何とも言えないけど、
わざわざ約8フレーム分ぐらい音声カットしてエンコードしたり、mkvにしてからの別ツールで合成しないといけないのかなぁ

ロベルト

Re: タイトルなし
報告ありがとうございます。L-SMASH も追加すると記事が長くなりすぎて読みにくくなるのであえて調べていませんでした。L-SMASH と x264_L_SMASH も後で調べてみます。
非公開コメント

プロフィール

ロベルト

お問い合わせはこちらまで
robelt2525[at]gmail.com

中の人 @nico_lab

広告リンク
Amazon
楽天市場

ブログ更新用 @blo_nico_lab

詳しいプロフィールはこちら

当ブログは、Amazonアソシエイトに参加しています。