🛠️

WebMファイルで映像の回転を扱う方法

2024/12/15に公開

この記事は NTT Communications Advent Calendar 2024 の 15 日目の記事です。

WebM ファイルにおける映像の回転について調査と実験を行いました。

映像回転の 2 つの手法

WebM 形式のファイルに限らず動画ファイルを回転させる方法は2つあります。

  1. エンコード前に回転

エンコードする前に映像を回転させる方法。
デコード → 回転 → エンコードといった感じで処理が増えるため、処理負荷は高い。

  1. コンテナの回転機能

WebM や MP4 といったメディアコンテナが用意している回転機能を使う方法。
処理負荷が低い。

WebM で回転を指定する方法

WebM は Matroska フォーマットをベースにしています。映像の回転は Matroska の仕様で定義されている VideoProjection 要素内の ProjectionPoseRoll で指定可能です。

ProjectionPoseRoll によって回転角度を指定すると、プレーヤーは再生時にその角度で映像を回転させます。その仕様は以下の RFC に詳細が記載されています。

https://www.rfc-editor.org/rfc/rfc9559#name-rotation

WebM に詳しい方だとこの時点で、この仕様だと複数回回転させるのが難しいことに気付かれると思います。

ProjectionPoseRoll はコンテナのいわゆるヘッダー部で定義されているので、動画の進行に合わせて回転角度を更新できるような仕様ではないのです。

複数回回転させたい

それでも複数回回転させたいので、もがいてみました。
次の 2 つの方法を試しましたが、結論から言うといずれも少なくとも Chrome 上では上手く動作しませんでした。。。

  • 複数のヘッダーとセグメント
  • 複数のトラック

複数のヘッダーとセグメント

WebM の親の仕様である Matroska の RFC には 1 ファイル内に複数の EBML Header と Segment を持つことができる、みたいな記述があります。

A more complex Matroska file consisting of an
EBML Stream (consisting of two EBML Documents) could be represented like this:

EBML Header
Segment
EBML Header
Segment

https://www.rfc-editor.org/rfc/rfc9559#name-data-layout

この仕組みを利用し、回転させるタイミングで新たなセグメントとヘッダーを挿入すれば、再生中に異なる回転情報を参照させられるのではと考えました。

しかし、実際に試した結果は次の通りでした

  • mkvToolNix (webm ファイルなどの構造を見るソフト)
    • ファイル構造が最初のヘッダーとセグメントしか表示されない
  • chrome
    • 最初のセグメントまでしか再生されない

おそらくこの仕様を実装している実装が現存しない or 自分の実装が何かおかしいという結論になりました。

複数のトラック

もう一つの手段は、回転のたびに異なる Track を用意する方法です。

chrome の標準の動画プレイヤーだとトラック選択の UI が無いので、自動的に読み込み位置の SimpleBlock のトラックで再生されるはずという淡い期待を抱いて実験してみました。

具体的にはこんな流れです。

  1. 録画開始時はヘッダー部なしでセグメント部のみ作成
  2. 回転させるタイミングで simple block の track number をインクリメントする
  3. 録画完了時に回転した回数分の track を含むヘッダー部作成する
  4. ヘッダー部とセグメント部を結合する

これで回転するたびに新しい track を使う WebM ファイルが完成しました。

しかし Chrome での動作確認の結果は

  • すべての track が認識されたものの、実際に再生されたのは、最初の Track のみ
  • Track を選択するボタン等もないので Track の切替もできず

という残念な結果でした。

複数のTrackを認識している様子
複数の Track を認識している様子

ワークアラウンド:プレイリスト分割

再エンコードなしで複数回回転させる方法が全くないかというとそうではありません。

先ほどの複数セグメントと考え方が似ていますが、要するに回転するたびにコンテナファイルを分ければよいわけです。

動画プレイヤー側で複数の動画ファイルをプレイリストとして持って再生すれば疑似的に複数回回転させることができます。

ただしプレイリスト機能に対応した動画プレイヤーを探してくるか、自分で動画プレイヤーを実装する必要があって、素晴らしい解決策とは言い難いです。。。

まとめ

WebM ファイルの場合、コンテナ側での複数回回転が難しい。
複数回回転が必要なら、エンコード前に回転させよう!

その他の方法

https://github.com/mpv-player/mpv/issues/6718

ここでは MKV を対象とした非標準的な方法について話されています。MKV と WebM は同じ Matroska ベースのコンテナなので、この議論で挙げられた方法に対応するプレイヤーがあれば、WebM でも応用可能かもしれませんが非標準の方法なので Chrome では動かなそう。

Discussion