要点
スマートフォンのカメラセンサーは、本体に横向きで固定されています。スマートフォンを縦に持って撮影しても、センサーが記録するのは横長のフレームで、スマートフォンはファイルに「90° 回転して表示すること」というフラグを書き込むだけです。スマートフォン上のプレーヤーはどれもこのフラグに従います。一方、ほかの環境のソフトウェアの一部(古い編集ソフト、一部の Web プレーヤー、特定のアップロード処理)はこれを無視したり削除したりし、その結果、動画が横倒しで再生されます。フラグを戻すのはメタデータの編集です。ファイルサイズにかかわらず一瞬で終わり、何も再エンコードしません。
フラグの正体
MP4 や MOV のファイルは、ボックスの木構造でできています。映像トラックの表示方法を記述するボックスは tkhd(トラックヘッダー)と呼ばれ、3 × 3 の変換行列(9 個の数値、36 バイト)を含んでいます。プレーヤーは各フレームを描画する前にこの行列を適用します。回転していない動画では行列は単位行列で、スマートフォンを縦にして撮った動画では 90° の回転です。ファイル内のピクセルは横長で、行列が「回転させよ」と指示しています。Android は同じ情報を別の rotation の値として書き込み、ffmpeg はどちらもストリームのメタデータで rotate: 90 と表示します。
これは意図的な設計です。録画中に実際のピクセルを回転させると、フレームごとにエンコーダーをもう 1 回まるごと通す必要があり、それをバッテリー駆動で行うことになります。9 個の数値を書くだけなら負荷はありません。写真の EXIF の向き情報と同じ考え方で、失敗の仕方も同じです。タグを読まないソフトウェアは、元の向きのまま表示します。
フラグを落とすもの
- 古いデスクトップの編集ソフトやプレーヤー。 スマートフォンで縦長の動画を撮る時代より前に書かれたものです。VLC と QuickTime は何年も前から行列に従っていますが、一部の企業向け動画システムや古いビルドの Windows Media Player は従いません。
- 映像ストリームをコピーしつつコンテナを作り直す変換ツール。 「再エンコードなし、ロスレス」をうたうツールでも、単位行列の新しい
tkhdを書き込むことがあります。ピクセルは残っても、指示は残りません。 - 一部の Web アップロード。 アップロード時に再多重化するサイトはタグを失うことがあります。再エンコードするサイトは、たいてい回転を正しく焼き込みます。
- 連結。 縦向きのクリップと横向きのクリップを 1 つのファイルにつなぐと、結合後のトラックには行列が 1 つしかありません。どちらか半分の向きが間違ったままになります。
2 つの修正方法(うち 1 つはコストなし)
行列を書き換える。 tkhd の行列(または回転のフィールド)を、動画が正しく表示される値に設定します。数 GB になりうるファイルに数十バイトを書き込むだけで、映像と音声のストリームは手を加えずにそのままコピーされます。0.5 秒、画質の劣化なし、ファイルサイズも同じです。動画回転が既定で行うのはこの処理です。端末上でファイルを読み、修正したヘッダーを書き込み、ファイルを返します。何もデコードしないので、4 GB の録画でも 4 MB のファイルと同じ速さで処理できます。
回転を焼き込んで再エンコードする。 すべてのフレームをデコードし、ピクセルを回転させ、もう一度エンコードします。必要になるのは、再生する側が行列を無視することがわかっていて、その再生側を変えられない場合だけです。デジタルサイネージのプレーヤーや古い CMS がその例です。動画の長さと同じだけの時間(ハードウェアエンコーダーがなければそれ以上)がかかり、1 世代分の画質劣化が生じます。動画回転ではこれを 2 つ目の選択肢として、ブラウザの WebCodecs エンコーダーを使って提供しており、コストの高い経路であることを画面上に表示しています。
「コストなし」の修正が効かないことがある理由
ある 1 つのプログラムでだけ横倒しになり、ほかでは正しく再生されるなら、そのプログラムが行列を無視しているので、書き換えても効果はありません。効くのは回転の焼き込みだけです。どこで再生しても横倒しなら、行列が失われているので、書き換えれば直ります。簡単な確認方法があります。最新のブラウザ(Chrome、Safari、Firefox はどれもタグに従います)でファイルを開いてください。ブラウザで横倒し → 行列が間違っているか欠けている → 書き換える。ブラウザでは正しく、ほかのプログラムで横倒し → 問題はそのプログラム → 焼き込む。