体系 › 動画圧縮
·無料·10分で読めます

動画圧縮を1から — 動き補償とGOP

1秒30枚の写真を別々に圧縮していては、いまの配信帯域にはまるで届きません。フレーム差分がなぜ破綻するのか、動き補償は何を送っているのか、I/P/BフレームとGOP、CBR・VBR・CRFが何を一定に保つのか。最後は配信担当が実際に決めるキーフレーム間隔まで降りていきます。

対象imageタスクcompression

比喩: 「さっきと同じ、ただし左の人が一歩右へ」

防犯カメラの映像を電話越しに実況する仕事を想像してください。1秒に30回も画面全体を説明し直す人はいません。最初に一度「駐車場、白い車が3台」と伝えたら、あとは「さっきと同じ、ただし左の人が一歩右へ動いた」で済む。動画圧縮も突き詰めればこれだけです。

素朴に桁を確かめましょう。1920×1080は約207万画素。RGBなら1フレーム約6.2MB、30fpsで毎秒約186MB——約1.5Gbpsです。各フレームを独立にJPEGにして10分の1になるとしても150Mbps前後。実際の1080p配信は、多くの場合それより2桁ほど細い帯域に収まります。JPEGを何枚並べても、まるで足りない。

足りない分を埋めるのが時間方向の冗長性です。隣り合うフレームは30分の1秒しか離れておらず、ほとんどの画素は前と同じ値のまま残ります。静止画の圧縮が1枚の絵の中の冗長性を削るのに対し、動画はここを削る。削れる量は桁違いに大きい。

差分を送る、という発想

いちばん素朴な手は、前のフレームとの引き算を送ることです。

dt(x,y)=ft(x,y)−ft−1(x,y)d_t(x,y) = f_t(x,y) - f_{t-1}(x,y)
(1)

つまりこの式は、画素の位置ごとに「いまの値から、1フレーム前の同じ位置の値を引く」と言っているだけです。送るのは、引いて残った分だけでいい。

ftf_t は時刻 tt のフレーム、dtd_t がその差分——「前回から何が変わったか」だけを描いた絵です。三脚のカメラで人が一人歩いているだけなら、絵はほぼ真っ黒で、人のまわりだけが光る。0ばかりの数列はよく縮みます。

ところがこの手は、カメラが動いた瞬間に破綻します。パンで画面が1画素ずれただけで、画面じゅうの輪郭が差分に現れる。被写体が動けば、元の場所と新しい場所の両方が差分に出ます。中身は同じで、ずれているだけです。

動き補償: 「どこから来たか」を送る

ずれているだけなら、ずらしてから引けばいい。これが動き補償です。

フレームをブロックに分け(H.264では16×16画素のマクロブロックが基本単位)、ブロックごとに「前のフレームのどこにいちばん似た絵があるか」を探します。そのずれが動きベクトル (mx,my)(m_x, m_y) です。

rt(x,y)=ft(x,y)−ft−1(x+mx, y+my)r_t(x,y) = f_t(x,y) - f_{t-1}(x + m_x,\, y + m_y)
(2)

つまり、引き算の相手を「前フレームの同じ位置の画素」から「そこから (mx,my)(m_x, m_y) だけずらした位置の画素」に取り替えた、ということです。ブロックの中身が直前にいた場所から引くので、残るのは「ずらしただけでは説明しきれなかった分」になります。

右辺の第2項が「ずらして持ってきた予測」、左辺の rtr_t が残差です。256画素のブロックが、2つの数字とわずかな残差で表せます。

大事なのは、ベクトルをどう探すかが規格の外側にある点です。規格が定めるのは伝え方と小数位置の補間だけ(多くのコーデックは2分の1・4分の1画素の精度で予測します)。探索半径を SS とすれば全探索は1ブロックあたり (2S+1)2(2S+1)^2 回の比較——すぐ非現実的に膨らむので(計算量の記事でいう二乗の壁)、実装は階層探索や近傍ベクトルからの局所探索で削ります。同じ規格・同じビットレートでもエンコーダで画質が違うのは、主にここの差です。

残差もまた画像である

残差 rtr_t とは、ただの画像です。予測が当たっていれば、ほとんどの画素が0付近に張り付いたのっぺりした絵になります。

ならば画像の道具がそのまま使えます。残差はブロック単位で周波数変換され(H.264以降は、エンコーダとデコーダで結果がずれないよう整数演算で定義されたDCT近似の変換)、量子化で丸められ、エントロピー符号化で詰められる。JPEGの記事と同じ道筋です。

違うのは入力だけです。動画の圧縮率が高いのは、変換や符号化が優れているからではなく、変換に入る前の絵がすでに空っぽに近いからです。

FIG 1動画の残差もこれと同じDCT+量子化を通る。違うのは入力が写真ではなく「予測を引いた残り」であること——すでに0に近いので、生き残る係数はさらに少ない

I・P・BフレームとGOP構造

フレームには3種類あります。Iフレーム(intra)は他を一切参照せず自分だけで完結し、中身はほぼ静止画圧縮そのもの。当然いちばん大きい。Pフレーム(predicted)は過去を参照し、Bフレーム(bi-predictive)は過去と未来の両方を参照します。

なぜBが効くのか。第一に遮蔽です。歩く人の背後から現れた壁は、前のフレームには写っていません。過去だけを見ている限り予測しようがない。しかし未来のフレームには、その壁がはっきり写っています。第二に平均化で、前後2つの予測を平均すると誤差が打ち消し合い、残差がさらに小さくなります。

代償は順序の逆転です。未来を参照する以上、それを先に復号しておかねばならない。表示順が I B B P なら、送信・復号順は I P B B。デコーダは並べ替え用のバッファを持ち、そのぶん遅延が生まれます。ライブ配信でBフレームを減らすのは、画質ではなくこの遅延が理由です。

GOP(Group of Pictures)はIフレームから次のIフレームの直前までのひとまとまりで、GOP長=キーフレーム間隔が現場でいちばん頻繁に触る値になります。参照構造は世代とともに複雑になり、複数の参照フレームやピラミッド構造を使う実装もあります。

シーンチェンジで何が起きるか

カットが入った瞬間、時間方向の相関は消えます。動き探索はどのブロックについても似た場所を見つけられず、残差は元の絵とほとんど同じ大きさになる。中身は次々にフレーム内予測へ切り替わり、ビットだけが膨れ上がります。予測が当たらないPフレームは、Iフレームより高くつくことすらあります。

だからエンコーダはシーンチェンジを検出し、そこにIフレームを置きます。判定材料はフレーム間の差の統計や、動き探索を試したときのコスト。検出が働くとGOPは設定より短く切られる。普段はありがたい機能ですが、キーフレーム位置を自分で決めたい場面では邪魔になります。

レート制御: 何を一定に保つのか

レート制御は、量子化パラメータ(QP)をどこに厚く配るかの設計です。QPは量子化の目盛りの粗さで、JPEGの「品質」に当たりますが、動画ではフレームごと・ブロックごとに変えられます。CBR・VBR・CRFの違いは、突き詰めると「何を一定に保つか」の違いです。

CBR(固定ビットレート)はレートを一定に保ちます。回線や放送波の帯域が固定で、超えてはいけない用途向け。代償は画質の変動で、動きの激しい場面でも同じビット数に押し込むためQPが上がり、目に見えて崩れます。

VBR(可変ビットレート)は平均レートを目標に、場面ごとにビットを配り直します。静かな場面から取り上げて激しい場面に回すので画質は安定する。実務では上限(-maxrate)とバッファサイズ(-bufsize)を併せて指定し、瞬間レートが回線を超えないよう縛ります。

CRF(constant rate factor)は品質のほうを一定に保ち、レートを成り行きに任せます。x264やx265が持つモードで、数値が小さいほど高品質・大サイズ(x264の既定値は23。エンコーダが違えば同じ数値の意味も変わります)。人の見え方には素直ですが、出来上がりのサイズが読めないのが弱点です。

どの方式にも影のように付いてくるのがバッファの制約です。デコーダ側の入力バッファが枯れても溢れてもいけないので、CRFやVBRにも -maxrate と -bufsize を添えます。

現場ではこう使う

動画配信のエンコード設定を決める担当が、実際に手を入れるのは次の5点です。

キーフレーム間隔をセグメント長に合わせる。 HLSやDASHでは動画が数秒のセグメントに切り分けられ、プレイヤーはセグメント先頭から復号を始めます。つまり各セグメントはIフレームで始まらなければならない。キーフレーム間隔はセグメント長に一致させるのが基本です。ffmpeg なら -g(GOP長=フレーム数)と -keyint_min を揃え、シーンチェンジによる勝手な挿入を止めます(x264系なら -sc_threshold 0 や scenecut=0、位置を明示するなら -force_key_frames)。合っていないと、パッケージャが境界で無理やり切ることになり、断ち切られたGOPの分だけビットが無駄になる。さらにABRラダーの各解像度でキーフレーム位置が揃っていないと、画質切替のたびに映像が飛んだり固まったりします。

GOP長そのもののトレードオフ。 長くすればIフレームが減り、同じ画質でもビットが節約できます。代わりにシークの起点が減り、プレイヤーは直前のIフレームまで戻るため、シーク後の表示や途中参加時の初期表示が遅れる。画質効率と、シーク・起動の速さのトレードオフであって、どちらかが正解ということはありません。VODならセグメント長に合わせた数秒、低遅延ライブならもっと短く、が典型的な着地です。

2パスが効く場面を見分ける。 1パス目で各フレームの複雑さを測り、2パス目でビットを配分するのが2パスです。効くのは最終サイズや平均ビットレートが先に決まっているとき——契約帯域、ラダー各段の目標レート、アーカイブの容量制約。サイズが自由ならCRFの1パスで足りることが多く、ライブでは未来を先に見られないので選択肢に入りません。

再エンコードの劣化累積を避ける。 一度エンコードした動画をもう一度エンコードすると、量子化誤差が世代ごとに積み上がります。しかも2世代目のエンコーダは、1世代目が作ったブロックノイズやリンギングを「本物の絵」だと思って忠実に符号化するので、ビットを無駄遣いしながら画質が落ちる。マスターは高品質(できれば中間コーデックか可逆)で保管し、配信用は毎回マスターから作る。編集→書き出し→字幕の焼き込み→再書き出し、のような工程が事故の温床です。

画質は指標と目の両方で見る。 ビットレートだけでは画質を語れないので、現場ではPSNR・SSIM・VMAFを併用します(VMAFは特にラダー設計で使われます)。ただしシーンチェンジ直後や暗いグラデーションのような弱点は、必ず目で確認するのが実務です。

設計レビューでよく問われるのは「なぜライブ配信ではBフレームを減らすのか」です。未来のフレームを参照するために表示順と符号化順が入れ替わり、その並べ替えがそのまま遅延になるから——即答できれば十分です。

まとめ

次は、この枠組みの上で世代ごとに何が変わったのか——H.264からAV1までを見ていきます。

出典

  1. x265 Documentation: Command Line Options. x265.readthedocs.io資料を開く(取得日 2026-10-21)
  2. FFmpeg Codecs Documentation. ffmpeg.org資料を開く(取得日 2026-10-21)

本文の定義・数値は、上の一次資料で確かめています。食い違う場合は一次資料が正です。

運営: TechAthletes · 編集方針 · 出典の付け方 · 訂正の記録

コメント

コメントにはログインが必要です