私的映像エンコーディング概論

少し前にTwitter(自称X)の相互フォローの更に先あたりで学級会が開催されていたらしく、「そんなことよりもエンコーディング論とかやってくれ」という話があったので。

そこで、本記事では自分の認識の整理も兼ねて、映像をエンコードするときにどの程度の設定にすればよいかについて、現状の認識を記述しようと思う。

先に結論

フルHDH.264ならx264のpreset veryslowで8Mbpsの2passエンコードにしとけば、まあ十分でしょう

エンコード形式の"画質"って何だ

日常会話において、映像のエンコードについて言及するときによく曖昧なままにされがちなのが、「〇〇形式は画質が良い/悪い」という言葉である。

これについてもう少し詳しく考えると、映像をエンコードするにあたって、「最も画質が良い」とは、「エンコード元の映像データと比較して何も値が変わっていない、言い換えれば差がない状態」*1である。
エンコード結果はその原理目的から考えれば"画質"は最良でも同じ、それ以外は悪くなる方向にしかならないので、前述の"差"のことを損失と呼ぶことが多い。

反対に、「最も画質が悪い」について考えると、実はこれは結構難しいのだが、映像のエンコードというのは人間が目で見て初めて役立つものなので、この記事では「人間がエンコード後のデータを再生したときに、エンコード元の映像データに映っているものを何も判別できない状態」という説明とする。

これで、最も良い状態と最も悪い状態の二つの説明が定義できたので、本記事における「画質」の評価軸はその2点を結んだ中間、「人間がエンコード後のデータを再生したときに、エンコード元の映像データと比べてどれだけ損失が少ないと感じるか」であると考えることができる。

損失の少なさを評価する試み

直前にも述べたが、映像のエンコード形式の最終的な受益者は人間である。つまり人間が良いと感じれば良いのである。

…という話で終わってしまっては各エンコード形式の画質の良さを比較することはできない。

そこでどうするのかというと、人間をそこそこの数連れてきて、映像を見せるのである。 そして画質はどれくらい良く感じましたか?と点数を付けさせる。

これのことを、人間の主観に基づく評価なので主観評価と呼ぶ。

ただし、主観評価では人間が評価するということは当然、評価する人や時期によって評価基準にブレが生じる。なんなら見せた順番によっても結果が影響を受ける。すなわち、異なる時期に行われた試験の評点を比較することはできないという弱点がある。
ブレを小さくするための様々な見せかた*2が検討、提案されているが、主観評価なので、ブレを0にするのは原理的に不可能であると言ってよい。

この弱点に対し、エンコードの前後の映像をもとに、画質の良さを数式から計算できる評点にしようと言う試みもある。
これを客観評価と呼び、よく言及されるのはPSNRまたはSSIM*3である。
しかし、それらの指標は、主観評価と緩やかな相関を示すとされるものの、主観評価を完全に代替できるほどの強い相関ではないと評価されている。

これら主観評価、客観評価といった学術的、あるいは標準化団体的なアプローチに対して、実産業からアプローチするものとして、Netflixのvmafがある。
これは、エンコード前後の画の数値的な差と、人間が感じる画質の主観評価値という具体的な関係式が明らかでない2値の間を機械学習によって近似しようとする試みである。

その評点が主観評価とどの程度の相関があるか、それが客観評価よりも強い相関なのかについての評価は定まっていないが、少なくとも同じ機械学習モデルを用いる限りは決定的*4なはずなので、異なる時期に行った評価の評点でも比較可能と考えられる。

国内でのvmafの実用例としては、DMMがvmafも含めた画質評価によってAV1のパラメータをチューニングし、従来使用していたH.264と同等評点の画質でビットレートを削減した、と主張する事例を観測している。

最も画質が良いエンコード形式、それは

さて、「エンコード元の映像データと比較して何も値が変わっていない状態」は実は簡単に実現できる。
頓智のような答えになるが、エンコードしなければよいのだ。つまり無圧縮である。
圧縮しなければ、圧縮による画質の損失もない。

……しかし、それではあまりにもデータ量が大きくなりすぎる。
具体的に計算すると、いわゆる1080p60の映像データの場合、縦1080px、横1920px、1画素あたりRGBで3Byte、秒間60フレームであるので1秒あたり約373.25MB必要になる。3秒で1GB強だ。

これではいくら画質が良いと言っても現実的に扱えるデータ量ではない。

ということで、映像のエンコードという課題を解決するにあたっては暗黙に、「データ量が現実的に扱える範囲に収まること」という制約の存在がこれによりわかる。

「現実的に扱えるデータ量」とは何か

そして実は、「現実的に扱えるデータ量」、というのも少し定義が難しい。

現在広く用いられているH.264や、その次世代であるH.265、AV1といった映像エンコード形式はその系譜をたどるとH.261にたどり着くが、これはISDN回線を用いてビデオ会議を行うために策定されたものであった。
したがって、その「データ量」というのは人間がどれくらいまでの遅延ならばどの程度違和感なく会話できて、その遅延に収めるためにはアルゴリズムがどの程度の計算量であるから当時または将来のCPUの計算力を鑑みてエンコードとデコードでどの程度の時間がかかり、残った分がデータ転送に使える時間で、複雑な動きをするときにはより多くのデータ量を割いて画質を良くしたいので、そのデータ量の変動を吸収して映像を途切れることなく伝送するためにどの程度のバッファ量が必要、あるいは遅延の観点から許容されて…
といったようなモデル化がされているわけだ……が!

この記事ではインターネット回線を介さない記憶装置に格納されているデータを読みだして再生し、計算力もGPUないしCPUの再生支援なども活用するためデコードに係る計算量は心配いらない環境を対象と定めるので、そのレベルの話はしないこととする。

したがって、本記事における「現実的に扱えるデータ量」というのは「記憶装置に十分な時間の映像が記録できる程度のビットレート」ということになる。

例えば3時間の映像を記録した片面2層のBlu-ray Disc*5。 これは180分、10800秒の映像を50GB=50000MB=400,000Mbitに記録していることになるので、平均すると約37.04Mbpsのビットレートということになる。 これをH.264 high profileで記録しているので、H.264としてはかなりの高ビットレートだ。 しかし、BDはDVDの後継、すなわち映画を1枚のディスクに可能な限り高画質で収めるための規格なので、ディスクに収まり、人の手で交換できさえすれば「現実的に扱える」という条件を満たすと言える。

それでまあ、現代は1000GBのUSB3.2 Gen1接続のSSDが1万円前後で買えるわけだが、 冒頭に結論が書いてあるにも関わらずこの記事をわざわざこんなところまで読むような物好きな読者の皆さんは、 おそらくBDと同じビットレートを使って1000GBで60時間記録できます、ではいくら高画質とはいっても足りないのではないだろうか。

裏を返すと、これは1,000GB=1,000,000MB=8,000,000Mbitで何秒の動画を記録できれば十分ですか、という質問に変換できる。

といっても記録できればできるほど良いのは間違いなくキリがないので、一つの目安を示すとYouTubeH.264 1080p60fpsはだいたい4.5~5Mbps程度である。

ならばということで、僕個人としては目標平均ビットレートとして8Mbpsを使うことにしている。
それならば1TBあたり1,000,000秒、約277.78時間記録できるはずだし、ユーザのインターネット回線速度の都合もあってビットレートを高くしづらいYouTubeよりはさすがに良い画質を実現できるはずだからだ。

平均ビットレートが同じときにより良い画質を実現するには

というわけで目標平均ビットレートが決まったら、次はその範囲でいかに高画質を実現するかになる。

H.264が頑張っている動画圧縮の要素技術をざっくり用語だけ並べると、

  • 色空間をRGBからYUVに変換
  • 4:2:0にダウンサンプリング
  • マクロブロックに分割して各マクロブロックの動きベクトルを推定
  • 推定した各マクロブロックの動きベクトルから動き補償予測で生成した予測画像と実画像の差分を取る
  • 取った差分を離散コサイン変換で周波数成分に変換
  • 隣接するマクロブロックの対応する周波数成分の差分を取る
  • 高周波部分を捨てたり揃えたりして値の出現確率を更に偏らせる
  • 最後に算術符号*6エントロピー圧縮する

…という手順をざっくり踏んでいるわけだが、これらは非常に単純化して言うと要するに、「同じフレーム内で近い画素同士は似た色をしていることが多い。また、時間軸的に近いフレーム同士では似た領域がある*7ことが多い」という映像の性質を利用している。
この性質を利用して、「いま圧縮しようとしているフレームの各領域に最も似た、時間的に近い別のフレームの領域はどこか」を探して、あとはそれからの差分を計算するとよりデータサイズを小さくできる、ということである。

似た領域の探索を頑張れば頑張るほど、もっと似た領域を探し出せるので、同じ画質ならデータサイズを小さくできるし、同じデータサイズならより高画質にできる。 逆に言えば探し方を雑にすると、画質は悪くなるがエンコードにかかる時間を短くできる。

というわけで、同じソフトウェアエンコーダーを使う場合は、エンコードに長い時間を費やせば同じデータサイズでより高画質を実現できると考えてよい。ただしそれにも限度があり、使う時間を増やせば増やすほど、増やした時間に対しての画質向上の効果は減っていく。要するにコストパフォーマンスが悪くなっていき、度が過ぎると使った時間の割に絵がどう変わったのか人間には区別できなくなる。そうなったらもう、人間が受益者である以上それ以上の時間をかける意味はない。

ハードウェアエンコーダとソフトウェアエンコーダを比較する場合は、エンコードにかかる時間に制限を設けない同一ビットレートにおいてハードウェアエンコーダが実現できる画質はソフトウェアエンコーダのそれよりも絶対に悪くなると言ってほぼ間違いない。
なぜならばハードウェアエンコーダは圧縮処理の全てまたは一部をハードウェアとして実装して速度を稼ぐ代わりに、ソフトウェアエンコーダがやっているような隅々までの似た領域の探索はできないからだ。

ということで、画質を重要視するならばソフトウェアエンコーダ一択というのは現在も変わらない。

1passエンコードと2passエンコードも当然、2passエンコードのほうが良い画質を実現できる。
なぜならば2passエンコードは1pass目で映像の傾向を分析することで、2pass目で実際にエンコードする際により適切なビットレートの割り振りを行えるからだ。

と、ここまで書いたところでそろそろお分かりかもしれないが、映像のエンコードという課題を解決するにあたっての暗黙の制約2つ目として、「エンコードにどれだけの時間を費やせるか、待てるか」の存在がこれにより判明した。

そしてこれについて僕は、x264を使ってエンコードするならもうpreset veryslowの2passエンコードを使ってしまって良いと思っている。
僕の使っているデスクトップPCのCPUであるCore i9-9900K*8では、それでフルHDの映像を実時間の2~3倍程度の時間でエンコードできるからだ。

つまり、3時間の映像をエンコードするのに最大で9時間程度かかるということだが、それくらいならば寝ている間や仕事をしている間に動かしておけば終わる。

なんせH.264なんて今も現役のような顔をしているが、勧告されたのは2003年。21年前である*9
そんなのもう、重いプリセットを今のCPU計算力でごり押してしまえばいい。

画質の評価手法の節で出てきたVMAFを使ってプリセットを比較した下記記事でも、presetを重くすればそれだけVMAFの評点が向上していることがわかる*10

ただし、placeboプリセットは今でも激重だし、2つめの記事に書いてある通りvery slowに比べてむしろ画質が下がるという説もあるので使わないほうがよいだろう。

将来的なエンコード形式の話

今回はH.264に的を絞って述べたが、基本的にはH.265やAV1でも同じことが言えると思う。

  • 画質の良さとファイルサイズの小ささを取るならエンコードに時間をかける必要がある
  • エンコード時間の短さとファイルサイズの小ささを取るなら画質は妥協せねばならない
  • 画質の良さとエンコード時間の短さを取るならファイルサイズは大きくせざるを得ない

H.265やAV1、更にはその次の世代として勧告されたH.266は、理論上はそれぞれの前世代に比べ同等画質で30~50%程度少ないビットレートを実現するとしているが、実際にはその分エンコードの処理内容が非常に複雑化していて、非常に時間がかかるというのが実情である。 それを将来のCPU性能向上、GPUによる再生支援、ハードウェアデコーダ・エンコーダの実装に期待して策定、勧告していると考えてよいと思う。

YouTubeやDMMといった同じ映像データを大量のユーザにむけて配信する事業者はそれだけの計算量をかけてでもビットレートを低く抑えたほうが大きなメリットがあるのは理解できるが、いくら僕がかなりのパワーユーザ寄りとはいえ、個人でエンコードして個人で再生するような映像のエンコード形式をH.265やAV1、ましてH.266にする日が来るのかどうか……というと今はまだ想像できない。

まとめ

というわけで、結論としては冒頭にも書いた通り、フルHDH.264ならx264のpreset veryslowで8Mbpsの2passエンコードにしとけば、まあ十分でしょう。

実は5年前にもこういった画質vsエンコーディングネタの記事を書いたことがあるのですが、そのときは「ニコ動のアップロード容量制限である3GBギリギリになるようなビットレートでハードウェアエンコードしてしまえ」という結論でした。
というのも、その記事では自分で動画を制作することを想定していたので、間違えた場所を見つけてもすぐに修正できるように、エンコードにかけた時間が無駄になってやる気を失ってしまわないように、しかもどうせ数十Mbpsになるので結果に大した差は出ない、という意図込みでその結論にしています。
一方、今回はソース映像は完全に固定で存在し、また目標ビットレートを8Mbpsといった普通な値に定めた場合の話をしているため、ソフトウェアエンコードで時間をかけて*11CPUパワーでごり押しせよ、という結論なのでした。

更に余談ですがHDMIキャプチャなどからの映像を撮るときにはRTX 3060Tiに乗っているNVEncのH.264ロスレスプリセットを使ってSSDに記録しています。 こうすると映像の傾向にも寄りますが250~300Mbps、ファイルサイズにして2分半を5GB程度で色空間がYUV420に変換された以外は可逆な映像が撮れるので、それをx264のvery slowプリセットを使ってゆっくり画質良くエンコードするのが良いです。

*1:現実世界の光景を撮影して映像データ化するときに、レンズの収差やセンサーのノイズ、センサーとヒトの目のダイナミックレンジの差などによって現実世界の光景とは異なる画になる、という観点での画質はこの記事の対象範囲の外であることに注意

*2:NTT 技術解説 – 映像品質評価法電子情報通信学会知識ベース2群5編9章3節

*3:電子情報通信学会知識ベース2群5編9章2節

*4:入力が同じなら同じ出力になること 決定的アルゴリズム - Wikipedia

*5:以降BDと表記

*6:プロファイルによってはハフマン符号の場合もあったはず

*7:物が動いているように見えるということは、考え方を変えるとあるフレームに映っている物体は次のフレームでは少しだけ場所が変化しているということ

*8:あくまでベンチマークスコアベースになるが、Core i5-11600Kや Core i5-13420Hでも同等のCPU性能らしい

*9:なんならmain profileまでとはいえ、2004年発売のPSPが策定中のH.264に基づいて再生に対応している

*10:本当は自分でやったほうがいいのはわかっているんだけど面倒くさかった

*11:といってもたかが実時間3倍