FFmpeg変換設定のキモ

これは私がiPod用に動画変換を試行錯誤した際のメモです。
たまにブログに書いてる動画関係の記事のネタ帳でもあります。
主にFFmpegでの設定例ですが、Handbrakeも愛用しています。
新しく気が付いたことがあったら随時更新してますが、手元のメモがon goingでここに反映されるとは限りません。

・iPodはアナモフィックなアスペクトを正常に再生出来る。
  -s 320x180とするより、-s 320x240 -aspect 16:9とすると縦の解像度を60ピクセル(25%)も有効に使える。
  しかもファイルサイズはほとんど変わらないという良いことずくめ。
  ディスプレイでは縮小されるのでほとんど意味はないけど、モニタ出力する際には効いてくる。
  実際、PCで全画面表示したらドットの粒子感がかなり緩和された。
  最新のFFmpegでは、-aspectを入れなくてもPARが自動的に設定されてアナモフィックになる模様。
  HandBrakeでは4:3から16:9への伸張係数である「sar=4/3」をアドバンスド設定に入れる。
  てゆか、mencoderのSARは「サンプルアスペクトレシオ」の略で、「スクリーンアスペクトレシオ」じゃないのね。
  つまりピクセルアスペクトレシオと同義。数値も同じ。

・-bufsizeは大きくすると圧縮率が上がってファイルサイズが小さくなるけど、大きすぎると処理能力が追いつかなくなり未処理ブロックが発生する。
  PCの処理能力では発生せず、iPodに移すと出るので厄介。新型で処理能力が向上してると出ないのかも知れない。
  ソースや設定によって出やすさが違うようで、512では出ず1024にすると出る場合もあり。
  アニメか実写か、ソースの解像度によって違うのか、VGAとQVGAではどのくらい差があるのかなどまだまだ検証の余地あり。
  しかし10MB以上サイズが変わるので出来るだけ大きくしたいところ。
  Handbrakeでは2000でも出ないようなので、変換君の方でだけ設定しているコマンドに問題があるのか?
  と思ったら、FFmpegの単位はkbyte、Handbrake(mencoder)の単位はkbit。
  2048kbit=256kbyteなので、2000kbyteどころか512kbyteの半分で問題が出るわけないね。

・-rc_eq "blurCplx^(1-qComp)"について
  FFmpegでは-rc_eqのデフォルト式がx264向けではない為、H.264でエンコードする際にはx264のデフォルトであるこの式が必要だった。
  現在では-rc_eqというコマンド自体が廃止されている。
  最新版を使う限りは必要ないが、rev.9633やそれ以前を使う場合などには忘れないこと。

・-partitions parti4x4+partp4x4について
  パーティションとは16x16であるマクロブロックのサブブロック最大サイズを指定するもの。
  H.264では、マクロブロックを4x4 8x8や、4x8のような変則的なサイズで部分毎に必要に応じて区切ることが出来る。
  それをフレーム別にどの大きさまで許可するかを決めるコマンド。
  小さい方がパーティクルなどの細かい表現が得意だが、大きい方が圧縮効率が高い。
  デフォルトは-partitions parti4x4+partp8x8+partb8x8で、キーとなるiフレームを4x4と小さくして詳細にし、差分であるpフレームを8x8と大きめに取って圧縮効率を上げている模様。
  parti4x4+partp4x4とするのは、QVGAのような低い解像度で最大限に細かい描写を行うため。しかしVGA以上の解像度になると、Pフレームを8x8にした方が広範囲にモーション予測を行えるので動画としての品質がアップするケースが多い。
  iPodではBフレームが無効なのでpartbは指定していない。
  HandbrakeではAdvanced設定のAnalysis項目がこれに相当し、Allにすると全て4x4となるようだ。

・720x480のDVDソースで、4:3の動画に16:9の画像が入ってる場合、クロップする上下は-croptop 60 -cropbottom 60。
  無効領域をクロップしないなら、およそ-croptop 56 -cropbottom 56。(720/16*9/11*10 = 368.181818)
  逆に16:9に4:3が入ってる動画のクロップする左右は-cropleft 90 -cropright 90。
  無効領域のクロップを含めて計算するなら-cropleft 96 -cropright 96。(640*((704/16*9)/480)=528)
  ただし、特に上下のレターボックスで同じ幅とは限らない場合があるので注意。
  どっちにしろVGA(640x480)サイズを割り込むので、どうしてもVGAにしたいなら縦か横に拡大することになる。

・DVDソース左右端の無効領域について
  iPodで扱う動画用としてなら絶対に削るべし。
  DVDのピクセルアスペクト比は1:1ではなく、NTSCの通常時と同じく10:11。正方形ではなく少し縦長の長方形。
  スクリーンアスペクト比4:3の時の解像度を高さが480ピクセル固定として求めた場合、幅は704ピクセルとなる。(480/10*11*(4/3)=704)
  つまり16ピクセル余分であり、付けたままだとiPodの限られた解像度ではどうやったって歪むかロスが出る。
  ちなみにNTSCのワイド画面の時は、ピクセルアスペクトは40:33とされる。今度は横長の長方形。
  この場合でもスクリーンアスペクト16:9で高さが480ピクセル固定なら幅は704ピクセルである。(480/40*33*(16/9)=704)
  ただし、ネット配信していた動画をDVDにパッケージングしたもの等で特に、無効領域を考慮せずにスクリーンを丸々720x480にスケーリングしているものがあるようだ。
  配信バージョンのアスペクト比が正しいとすると、DVD版は横に16ピクセル広がった間違ったアスペクト比ということになるので、エンコードの際に無効領域を削らずに元の正しいアスペクト比に戻す方が良いこともある。

・FFmpegで2pass時の-passlogfileについて。
  1pass目でモーション予測データを保存するファイルを指定し、2pass目でそれを読み込む先を指定する。つまり両方同じパスを指定。
  ・・・と習ったが、実は変換君付属のFFmpeg以外では正常に機能してるのを見たことがない。
  一応そのパスのファイルは作成されるが、中身のない0バイトのファイルになる。
  もしその実体のないファイルを2pass目で読み込んでしまうと、参考にするべきデータが存在しないので、2passにする意味がない。
  実際の挙動は、1pass目で勝手にテンポラリファイルを作ってそこにログを書き出し、2pass目でそれを読んでる模様。
  2pass目で-passlogfileに存在しないパスを指定するとエラーになるので、存在チェックはやってるようだけども。
  無くても動作するなら、一々無意味なファイル作って、わざわざそれを消すという工程を踏まなくても良いのではないか?
  1pass目の-passlogfileは、本来はデータをバックアップするためのものなんじゃないかと思うのだけど、0バイトになるならどっちにしろバグ。

・FFmpegには今のところPsy-RDを設定する項目は無い?
  最近のx264ではデフォルトでPsy-RDが入ってるらしいので、FFmpeg側で明示的に設定する必要は無いのかも。
  ちなみにデフォルト値は1.0:0.0。
  どうしても切りたいシチュって考えつかないんだけど、無駄に高解像度高容量で忠実性最優先なファイルを作りたい場合くらいか。
  FGO等と競合するので、そっちを使いたくて切りたい場合があるのかも知れないけど、自分的にはFGOよりもPsy-RDを推したい。
  つかFGOを設定する項目ってどれだ?
  ちなみにPsy-RDは、細部のディテイルを忠実に再現するよりも、心理的にそれっぽく見えるように誤魔化すオプション。
  高いビットレートや解像度に頼らずに、微細な表現をそれっぽく再現出来る。
  イメージとしては、MP3などのような不可逆圧縮で心理的に聞こえない音を間引いてビットを節約してるような感じ。

・インタレース解除について。
  DVDなどのアナログテレビ出力を前提としたソースでは、PCモニタなどで見ると動く物体に櫛状にノイズが入る。
  これはインタレースであることが原因。
  FFmpegでのインタレ解除は、-deinterlaceコマンドしかない。
  アルゴリズムがどうなってるのかわからん。あまり良い評判を聞かないから単純なものなんだろう。
  どうしても凝ったデインタレースがしたいなら、AviSynthを経由して好きなインタレ解除プラグインを通すのも手。
  Handbrakeではインタレ解除の設定がFast Slow Slowerの3つが揃ってる。前のバージョンではアルゴリズム名だったのに。
  Fastは単純にリニア補完。単純な分だけ処理は速いが、線がガタガタになったりゴーストが出たりする。
  Slowはピクセル補完。そのピクセルの右上と左下のピクセルを参照する。変換速度は遅くなるけどFastの問題は解消されるので、出来ればこれをデフォルトに。
  Slowerは、Slowに加え更に前後フレームのピクセルも参照する。最も高精度だがやたら重い。Slowで特に問題が出ることはあまり無いので、使うなら時間が有り余ってる時にお試し程度で。
  Deinterlaceとは別にDecombなる項目も追加された。
  これは、櫛状ノイズが出る部分だけにSlowerをかけるようにして、スピードと画質を両立した設定のようだ。
  インタレ解除と別になってる意味がわからん。

・AviSynthについて。
  FFmpegは.avsファイルを食わせることが可能。(ビルド時にオプション付けていれば)
  それで好きなだけインタレ解除したりフィルタかけたり編集すればいいさ。
  ただ、VOBを直接読めるプラグインって無いの?
  d2vに分離してやれば良い事なんだけど、VOBのまま読めないと変換君の簡便性が著しく損なわれるよね。
  ・・・あった。FFmpegSourceプラグイン。
  名前の通りFFmpegのソースを利用して、FFmpegで対応するフォーマットをフィルターとして提供するプラグイン。
  安定版の1.21なら大丈夫だけど、最新の2.0betaはフィルタ名が変わってたり音声読み込みフィルタが搭載されてなかったりと、本当にまだベータ版。
  VOBのMPEG2とAC3やLPCMを読む程度なら1.21で充分。
  FFmpegからAviSynthを呼び出してるのに、そこからFFmpegSorceでファイルを開いてるってのは結構皮肉だね。
  てゆか、DirectShowがDVD読めるようになってればDS経由で読めた。
  DSで読んだらYV12に変換しないとFFmpeg側で不具合出るかも。
  ただAC3読ませると最後にエラーが発生?不安定?まだ未確認。

・"-f ipod"について。
  iPodで再生出来る動画には、Appleの特殊なuuidアトムが登録されていることが必須。
  昔は外部アプリのNicMP4BoxやAtomicParsleyを通すのが一般的だったが、最近のFFmpegには専用のコマンドが用意されている。
  それが "-f ipod"。
  意味がわからなくても、オマジナイとして入れておけばOK。
  FFmpegの出力結果と外部エンコーダでの音声ファイルをMP4BoxでMUXすると、コンテナが変わればもちろんuuidは変わってしまうので、後で別途何とかすること。
  Handbrakeの場合は見てそれとわかるチェックボックスがある。

・2pass時のそれぞれのコマンド設定とか。
  基本的には、pass1とpass2のコマンドは同一のものとする。
  全く同じ設定であればそれだけ精密なデータが取れるため、2passでのエンコードが最適化される。
  しかし、同じ処理を2回行うことになるので、エンコードにかかる総時間は単純に2倍になる。
  せめてモーション予測しかしないpass1だけでも時間を短縮したいなら、品質にそれほど大きく影響しない部分だけでも軽いパラメータに変えるのも手。
  例えば、両方とも-me_method umhにしてるのをpass1だけhexにするとか、-me_range 32を16に抑えるとか。
  ちなみに画像関係以外のコマンドは無視されるので、あってもなくても関係ない。

・ノイズリダクション(平滑化)とか。
  ノイズ除去フィルタのコマンドは、FFmpegでは-nr、HandbrakeではDenoiseの3段階から選ぶ。
  しかし「ノイズが目立たなくなる」のと「微細なディテイルが潰れる」のトレードオフなので、付けるかどうかは好みで。
  自分的には、アナログ撮影したソースを自前でオーサリングするような場合ならまだしも、完パケしたデジタルソースに存在するノイズは作品としての表現の一部だと思うので、除去するよりも生かす方向で行きたい。
  MPEGのような圧縮動画形式はノイズなどの微細な表現はあまり得意ではないのだけど、心理的にそれっぽく再現するPsy-RDはかなり有効。
  ただ、アニメのように塗りが平坦な(つまり微細ではない)画面を平滑化しても劣化がわかりにくく、その上ビットの節約になり圧縮率の向上に繋がるというメリットの方が大きくなるので、それを目的にかけても良いかも知れない。
  そうするならばPsy-RDは外すか、かけるにしてもパラメータは0.3,0とか低くした方が良いかも。

・Handbrakeの横幅指定
  HandbrakeでCLIに渡す横幅指定コマンドには「-w」と「-X」の2種類があり、-Xで指定すると後続の-lでの高さ指定を無視してアスペクト比を維持したスケールにリサイズされる。
  16:9のソースを4:3からのアナモフィックにエンコードする際には、高さ指定が生かされる-wを使うことが絶対条件だが、何故かGUIは隙あらば-Xの方を使おうとするので注意が必要。
  サイズ指定を変更する等で勝手に-Xになってしまうようで、エンコード開始やキューに登録する前にクエリエディタで確認し、-Xになってしまっていたらその都度修正すること。
  ユーザープリセットに-wで登録しておけばそのまま-wになるので便利だけど、何らかの原因で-Xに変わってしまった場合に、見た目ではわからないものなので気を抜かないように。

・音声マルチトラックについて。
  FFmpegでやる方法は未確認だが、Handbrakeでは音声トラックを複数持ったファイルを簡単に作れる。
  そんなファイルをiTunesに登録した場合でも、再生するトラックを選べるコントロールがUIできちんと用意されているので全く問題はない。
  iPod上では、最初のトラックだけが再生対象のようだ。

・no-dct-decimateについて。
  DCT Decimateとは、Pフレームの量子化係数が小さいものを間引いてしまう機能。
  動きの変化が細かすぎる部分を「あまり変化しなかった」と見なすことによってビットの節約になり、他の部分に余ったビットを回して有意義に使ったり、他に使う部分がなければカットしてファイルサイズが減少したりする。
  x264ではこの機能がデフォルトでONなので、これをOFFにするコマンドという意味で頭にnoが付いていることに注意。
  ただ、ビットを節約してファイルサイズを抑えるより、一回りファイルサイズが大きくなっても動きの安定度が高い方が良いならば、是非とも切っておきたい所。
  HandbrakeではAdvance設定にあるが、残念ながらFFmpegにはこれに相当するコマンドが今のところない。
  OFFにして効果があるのは、高解像度で高ビットレートか、またはアニメのように塗りがはっきりしてるものをエンコードする場合など。
  特にアニメのように色の境界がくっきりしているものでは、タイミングによってブロックが崩れるのを抑えることが出来るらしい。
  逆に言えば、実写ソースをiPod用QVGAにする場合などには効果は低く、無駄にファイルサイズが肥大化するだけになる可能性もあり。

・エンコード時のCPU負荷について。
  複数アプリケーションが並列動作しているなどでエンコード時のCPU負荷が高くなっていても、エンコード速度が遅くなるだけでバイナリとしては同じ物が出力されるはず・・・と普通は思うのだけど、実際は何故か動画品質に影響する。
  これまでに経験した問題としては、ムービーと音声がずれたり、シーンチェンジが上手く検出されずにマクロブロックが崩れたりなど。
  CPU負荷が動画品質に影響する要素は未確認だけど、回避する策としてはbitexactフラグ立ててバイナリレベルで厳密にするとか、スレッドを一本にしてシリアルコーディングさせるなどが有効か?やったことないけど。
  どっちにしろ処理速度に影響するので、非実用的なくらい時間がかかる可能性もあり。
  実用的な対処方法としては、エンコード時には他のアプリは全て終了し、寝てる間に終わらせてしまうのが一番かも。