Region Capture を使用したタブ共有の改善

François Beaufort
François Beaufort

ウェブ プラットフォームでは、ウェブアプリが現在のタブの動画トラックをキャプチャすることがすでに許可されています。これらの動画トラックを切り抜くメカニズムである領域キャプチャが搭載されるようになりました。ウェブアプリは現在のタブの一部を対象領域として指定し、ブラウザはその領域外のすべてのピクセルを切り抜きます。

以前は、ウェブアプリで動画トラックを「手動で」切り抜くことができました。つまり、ウェブアプリで各フレームを直接操作することができました。これは堅牢でもパフォーマンスが高いわけでもありませんでした。Region Capture は、こうした欠点を解消します。ウェブアプリは、ブラウザに代行処理を指示できるようになりました。

リージョン キャプチャについて

Dynamic Content™ を使用してウェブサイトを作成しました。これは最高のウェブアプリであり、ユーザーは頻繁に共同で利用しています。次のステップとして、仮想会議機能を埋め込むことが考えられます。あなたはそれを選択することにしました。既存のビデオ会議サービス プロバイダと提携し、そのウェブアプリをクロスオリジン iframe として埋め込みます。ビデオ会議ウェブアプリは、現在のタブを動画トラックとしてキャプチャし、リモートの参加者に送信します。

メイン コンテンツ領域とクロスオリジン iframe をハイライト表示するウェブアプリのブラウザ ウィンドウのスクリーンショット。
メイン コンテンツ エリアは青色で、クロスオリジン iframe は赤色です。

ちょっと待ってください。ユーザー自身の動画をユーザーに送信するのは、あまり意味がありません。その部分を切り取った方がよいでしょう。これには、埋め込み iframe は、公開するコンテンツとその場所を認識していないため、何らかの助けなしに切り抜くことはできません。理論的には、目的の座標を渡すことができます。しかし、ユーザーがウィンドウのサイズを変更した場合はどうなるでしょうか。ビューポートをスクロールしますか?ズームイン / ズームアウトしますか?レイアウトの変更が発生するような方法でページを操作しますか?新しい座標をキャプチャ iframe に送信しても、タイミングの問題により、一部のフレームが正しく切り取られない可能性があります。

では、領域キャプチャを使用しましょう。ページに Element(おそらく <div>)があり、メイン コンテンツが含まれています。これを mainContentArea とします。ビデオ会議ウェブアプリで、この要素のバウンディング ボックスで定義された領域をリモートでキャプチャして共有したい。したがって、mainContentArea から CropTarget を導出します。この CropTarget をビデオ会議ウェブアプリに渡します。この CropTarget を使用して動画トラックを切り抜くと、そのトラックのフレームは mainContentArea のバウンディング ボックス内に収まるピクセルのみで構成されます。mainContentArea のサイズ、形状、位置が変更されると、ウェブアプリからの追加の入力なしで、動画トラックが追従します。

手順をもう一度確認しましょう。

ウェブアプリで CropTarget を定義するには、任意の要素を入力として CropTarget.fromElement() を呼び出します。

// In the main web app, associate mainContentArea with a new CropTarget
const mainContentArea = document.querySelector("#mainContentArea");
const cropTarget = await CropTarget.fromElement(mainContentArea);

CropTarget をビデオ会議ウェブアプリに渡します。

// Send the CropTarget to the video conferencing web app.
const iframe = document.querySelector("#videoConferenceIframe");
iframe.contentWindow.postMessage(cropTarget);

ビデオ会議ウェブアプリは、メイン ウェブアプリから受け取ったクロップ ターゲットを使用して、セルフキャプチャ動画トラックで cropTo() を呼び出し、CropTarget で定義された領域にトラックをクロップするようブラウザに要求します。

// In the embedded video conferencing web app, ask the user for permission
// to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
  preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();

// Start cropping the self-capture video track using the CropTarget
// received over window.onmessage.
await track.cropTo(cropTarget);

// Enjoy! Transmit remotely the cropped video track with RTCPeerConnection.

Et voilà! これで完了です。

詳細

特徴検出

CropTarget.fromElement() がサポートされているかどうかを確認するには、次のコマンドを使用します。

if ("CropTarget" in self && "fromElement" in CropTarget) {
  // Deriving a target is supported.
}

CropTarget の導出

mainContentArea という Element に注目してみましょう。そこから CropTarget を導出するには、CropTarget.fromElement(mainContentArea) を呼び出します。成功した場合、返された Promise は新しい CropTarget オブジェクトで解決されます。そうでない場合は、不当な数の CropTarget オブジェクトを生成していると、拒否されます。

const mainContentArea = document.querySelector("#mainContentArea");
const cropTarget = await CropTarget.fromElement(mainContentArea);

Element とは異なり、CropTarget オブジェクトはシリアル化可能です。たとえば、Window.postMessage() を使用して別のドキュメントに渡すことができます。

切り抜き

タブキャプチャの場合、動画トラックは BrowserCaptureMediaStreamTrackMediaStreamTrack のサブクラス)としてインスタンス化されます。このサブクラスは cropTo() を公開します。track.cropTo(cropTarget) を呼び出して、mainContentArea(cropTarget の派生元である Element)の輪郭に合わせて切り抜きを開始します。

成功した場合、後続のすべての動画フレームが mainContentArea のバウンディング ボックス内に収まるピクセルで構成されることが保証されると、Promise は解決されます。

成功しなかった場合、Promise は拒否されます。これは、次のような場合に発生します。

  • CropTarget が別のタブで作成されました。(現時点では - 今後の展開にご期待ください)。
  • CropTarget は、存在しなくなった Element から派生しました。
  • トラックにはクローンがあります。(問題 1509418 を参照)。
  • 現在のトラックがセルフキャプチャ動画トラックではない。以下を参照してください。

cropTo() メソッドは、自己キャプチャだけでなく、タブキャプチャのすべての動画トラックで公開されます。そのため、トラックを切り抜く前に、ユーザーが現在のタブを選択したかどうかを確認することをおすすめします。これは、キャプチャ ハンドルを使用して実現できます。preferCurrentTab を使用して、ブラウザにユーザーが自分でキャプチャするように促すこともできます。

// Start cropping the self-capture video track using the CropTarget.
await track.cropTo(cropTarget);

切り抜き前の状態に戻すには、null を指定して cropTo() を呼び出します。

// Stop cropping.
await track.cropTo(null);

遮蔽するコンテンツと遮蔽されるコンテンツ

領域キャプチャでは、ターゲットの位置とサイズのみが重要であり、z-index は重要ではありません。ターゲットを遮るピクセルがキャプチャされます。ターゲットの隠れた部分はキャプチャされません。

これは、領域キャプチャが基本的に切り抜きであることの帰結です。別の方法として、要素レベルのキャプチャがあります。これは、将来独自の API になる予定です。要素レベルのキャプチャでは、オクルージョンに関係なく、ターゲットに関連付けられたピクセルのみをキャプチャします。このような API には、単純な切り抜きとは異なるセキュリティとプライバシーの要件があります。

領域キャプチャ API と要素レベル キャプチャ API のさまざまな結果の画像。
コンテンツが隠れている場合の領域キャプチャの動作。

セキュリティとプライバシー

領域キャプチャを使用すると、タブ内のすべてのピクセルをすでに監視しているウェブアプリが、それらのピクセルの一部を自発的に削除できます。新しい情報を取得できないため、明らかに安全です。

リージョン キャプチャを使用すると、リモート参加者に送信される情報を制限できます。たとえば、スライドは共有したいが、スピーカー ノートは共有したくない場合などです。

スライドと発表者ノートが表示されたブラウザ ウィンドウのスクリーンショット。
スライドとスピーカー ノートを含むウェブアプリ。
ノートをリモートで共有することは望ましくありません。キュー リージョン キャプチャ。

ローカルでは、リージョン キャプチャによってセキュリティ保証が追加されることはありません。トラックを別のドキュメントに渡す場合、受け取り側のドキュメントは、トラックの切り抜きを解除して、キャプチャされたタブのすべてのピクセルにアクセスできます。

Chrome は、キャプチャしたタブの周囲に青い枠線を表示します。通常、Chrome は切り抜きを行うと、切り抜きの対象の周囲に青い枠線を描画します。

デモ

デモを実行して、領域キャプチャを試すことができます。

ブラウザ サポート

Browser Support

  • Chrome: 104.
  • Edge: 104.
  • Firefox: not supported.
  • Safari: not supported.

Source

領域キャプチャは、パソコン版 Chrome 104 以降でのみご利用いただけます。

次のステップ

ウェブでの画面共有を改善するために、近いうちに導入される予定の機能をご紹介します。

  • 領域キャプチャで他のタブのキャプチャがサポートされます。
  • 条件付きフォーカスを使用すると、キャプチャするウェブアプリは、キャプチャされたディスプレイ サーフェスにフォーカスを切り替えるか、そのようなフォーカス変更を回避するようブラウザに指示できます。
  • 要素レベルのキャプチャ API が提供される可能性があります。

フィードバック

Chrome チームとウェブ標準コミュニティは、リージョン キャプチャに関する皆様のご意見をお待ちしています。

デザインについて教えてください

領域キャプチャについて、期待どおりに動作しない点がありましたらご記入ください。アイデアを実装するために必要なメソッドやプロパティが不足している場合はどうすればよいですか?セキュリティ モデルについて質問やコメントがある場合

  • GitHub リポジトリで仕様に関する問題を提出するか、既存の問題に意見を追加します。

実装に関する問題ですか?

Chrome の実装にバグが見つかりましたか?それとも、実装が仕様と異なるのでしょうか?

  • https://new.crbug.com でバグを報告します。できるだけ詳細な情報と、再現するための簡単な手順を記載してください。

サポートを表示

領域キャプチャを使用する予定はありますか?皆様からの公開サポートは、Chrome チームが機能の優先順位を決定するうえで役立ち、他のブラウザ ベンダーにサポートの重要性を示すことにもつながります。

@ChromiumDev にツイートして、どこでどのように使用しているかをお知らせください。

謝辞

この記事のレビューにご協力いただいた Joe Medley に感謝いたします。