はじめに
開発しているオープンソースの動画編集アプリ Timeline Studio に、ブラウザ内で動画の深度を推定する機能を実装しました。
通常の動画から相対的な奥行きを取り出し、深度に応じたぼかしや再ライティングに利用したり、独立した深度動画として書き出したりできます。本記事では、実装の構成と、深度動画を生成AIの参照素材として使った実験を紹介します。
左がカラー映像、右が同じ時刻の深度推定結果です。
深度マップは距離の実測値ではない
使用しているモデルは Depth Anything V2 Small です。RGB画像から単眼の相対深度を推定します。
現在の表示では、通常は明るい画素ほど手前、暗い画素ほど奥を表します。表示の反転にも対応しています。
ただし、相対深度の値をそのままメートルに換算することはできません。編集用の空間的な手がかりとして利用するものであり、カメラを校正して得た3D計測結果とは異なります。
全体の処理構成
動画クリップ
↓ タイムライン時刻をソース時刻に変換
フレームのデコードと縮小
↓ Web Workerへ転送
Depth Anything V2による推論
↓ 正規化・エッジを考慮した平滑化
深度フレーム
├─ 深度に応じたぼかし
├─ 深度を利用した再ライティング
└─ 深度動画のエンコード
モデルの読み込みには Transformers.js、推論には WebGPU を使用し、現在の構成は Q4F16 です。中心となる呼び出しは次のようになります。
const estimator = await pipeline(
"depth-estimation",
modelPath,
{
device: "webgpu",
dtype: "q4f16",
progress_callback: reportProgress,
},
);
実際の実装では、モデルの固定リビジョン、ミラーからの読み込み、ダウンロード進捗、任意のキャッシュ利用、失敗時の処理も必要です。
推論は独立した Web Worker で行います。メインスレッドは編集操作、フレームの準備、進捗表示を担当します。ただし、Workerを使ってもGPUやデコーダーの競合はなくなりません。同時処理数とメモリ使用量を制限する必要があります。
この深度解析経路では動画フレームをブラウザ内で処理します。書き出した深度動画を外部の生成サービスに渡す場合は、別途アップロードが発生します。
タイムライン時刻とソース時刻を合わせる
編集アプリへの組み込みで重要だったのが、時刻の対応です。
クリップにはトリミング、倍速、スロー、速度カーブが設定されることがあります。タイムラインの3秒地点が、元動画の3秒地点とは限りません。
そこで、深度解析にも編集アプリ共通のソース時刻変換を使います。
const sourceTime = getVisualSourceTime(segment, localTime);
この時刻のフレームを取得して推論し、プレビューと深度動画の出力でも同じ変換を使います。
解析キャッシュの識別情報には、素材、トリミング範囲、再生速度、速度カーブ、品質設定、モデルのリビジョンを含めています。関連する条件が変わった場合は、古い解析を再利用しません。
深度推定自体が正しくても、別の時刻の画面に適用すると輪郭がずれます。動画編集では、この時間的一致が欠かせません。
解析コストを抑える
現在の解析プリセットは次のとおりです。
| プリセット | 目標サンプリング頻度 | 入力の長辺上限 |
|---|---|---|
| 高速 | 8 fps | 392 px |
| バランス | 16 fps | 504 px |
| 高品質 | 24 fps | 518 px |
これは解析のサンプリング設定であり、実測したリアルタイム処理性能ではありません。実際の速度はブラウザ、GPU、動画の条件によって変わります。
1回の解析は最大720サンプルに制限しています。長いクリップで上限に達する場合は、実効サンプリング頻度を下げて全体をカバーします。
また、現在のフレームの推論と次のフレームの準備を重ねつつ、処理中のタスク数を制限しています。動画全体を一度にデコードしてメモリに保持する方式は採用していません。
独立した深度動画は24 fpsで出力します。高速・バランス設定ではRIFEによる補間を利用しますが、補間で新しい実測情報が増えるわけではありません。速い動きや遮蔽の変化では確認が必要です。
深度からぼかしを作る
現在のぼかし処理では、鮮明な画像、ぼかした画像、深度から作るマスクを合成します。
選択した焦点深度に近い領域は鮮明に保ち、焦点範囲から離れるほどぼかした画像を混ぜます。境界には滑らかな遷移を設けます。
深度画像には、隣接画素の深度差と元画像の色差を考慮した軽量な平滑化も行います。前景と背景の境界をまたぐ混合を減らすためです。元画像の模様を新しい凹凸として付け加える処理ではありません。
この方式は画像合成による近似です。髪、透明な素材、複雑な遮蔽の境界には限界があり、実際のレンズによる光学的な被写界深度と同一ではありません。
深度動画を素材として書き出す
解析した深度は独立した動画として「マイアセット」に保存できます。
現在のブラウザ出力はWebMコンテナとVP9を使い、元の縦横比を維持しながら長辺を最大1080 pxに制限しています。元の音声がある場合は、クリップの時刻に対応する音声も準備します。
出力解像度と推論解像度は別です。大きなサイズで書き出しても、モデルが予測していない細かな形状まで復元されるわけではありません。
生成AIの参照に使った実験
さらに、次の3つを組み合わせて動画生成を試しました。
- 深度動画:輪郭、前後関係、遮蔽、構図変化の参照
- キャラクター画像:顔、衣装、材質の参照
- テキスト:動作の段階、背景、表現スタイルの指定
重要なのは、今回の実験では深度専用の条件入力APIではなく、通常の参照動画として深度動画を渡したという点です。生成モデルがグレースケールの構造を解釈する必要があります。
横向きから正面への変化や、後半で人物がカメラに近づく流れは見られました。一方で、手前の腕や袖の形状を別の身体動作として解釈したり、頭や肩の画面内の大きさがずれたりする結果もありました。
別の2人の人物が袖を振る実験では、元のカラー動画を参照した方が、主要な動作と遮蔽による切り替えに近い結果になりました。ただし、抽出フレームで比較した範囲でも手の細部は一致していません。
深度は空間構造を強調しますが、カラー動画には手の動き、布、物体を理解するための意味情報が残っています。目的に応じて参照を選ぶ必要があります。
また、相対深度マップから校正済みのカメラFOVが直接得られるわけではありません。構図の一致は、人物の画面占有率、切り取り位置、カメラ変化を実際に比較して判断します。
実装から得られた知見
ブラウザでモデルが動くことと、編集機能として使えることの間には、多くの作業があります。
今回とくに重要だったのは、ソース時刻の共有、解析予算の制限、キャンセル、進捗表示、キャッシュの有効性、そして結果を再利用可能な素材にすることでした。
現在はブラウザ内の深度解析から、編集可能な効果と独立した深度動画の出力まで接続できています。生成実験については、厳密な動作転送を保証するものではありません。時間方向の安定性、複雑な境界、深度専用の生成インターフェースとの連携は、引き続き改善したい点です。
デモ・ソースコード
ブラウザAIや動画編集を開発している方の実装例・フィードバックも歓迎します。
※本記事の日本語原稿の作成には生成AIを使用しています。実装の記述はプロジェクトのコード、生成結果の記述は実験記録に基づいています。
