Copyright © 2023 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
この文書は、現在のタブのディスプレイキャプチャから派生した ビデオトラックを切り抜くための API を紹介する。
この節は、この文書の公開時点における ステータスを説明する。現在の W3C 公開文書の一覧と、この技術報告の最新改訂版は、 https://www.w3.org/TR/ にある W3C 技術 報告索引で確認できる。
この最初の公開作業草案は、閲覧コンテキストの部分キャプチャという ユースケースを解決するために Web Real-Time Communications 作業グループが探求しようとしている方向性を示すものである。 作業グループは、この API の採用候補者から、この方向性が当該ユースケースに どの程度適合しているかについてのフィードバックに特に関心を持っている。この文書は、Web Real-Time Communications Working Group により、 勧告トラックを用いた 作業草案として公開された。
作業草案としての公開は、 W3C およびその会員による支持を意味しない。
これは草案文書であり、いつでも他の文書によって更新、置換、または廃止される 可能性がある。この文書を進行中の作業以外のものとして引用することは 適切ではない。
この文書は、 W3C 特許 ポリシーの下で活動する グループによって作成された。 W3C は、 そのグループの成果物に関連して行われた 特許開示の公開リストを管理している。 そのページには、特許を開示するための 手順も含まれている。個人が、 必須クレームを含むとその個人が考える 特許について実際の知識を有する場合、 W3C 特許ポリシーの第 6 節に従って その情報を開示しなければならない。
この文書は、 2021年11月2日版 W3C プロセス文書に準拠する。
非規範的と記された節と同様に、この仕様におけるすべての作成ガイドライン、図、例、および注記は非規範的である。この仕様のそれ以外のすべては規範的である。
この文書におけるキーワード MUST および MUST NOT は、 BCP 14 [RFC2119] [RFC8174] に記述されているように、かつここに示すようにすべて大文字で現れる場合に限り、解釈されるものとする。
この文書は、[SCREEN-CAPTURE] から、次の概念の定義を用いる: display-surface および browser display-surface。
この節は非規範的である。
複雑なアプリケーションは、多くの場合、別個の 文書 を、同一の iframe
内の複数の
閲覧
コンテキスト 内に表示して構成される。そのようなアプリケーションを考える。
これらの文書の 1 つである CAPTURING-DOC が、getDisplayMedia()
または
getViewportMedia を用いて、現在の 閲覧
コンテキスト 全体をキャプチャすると仮定する。次にこの
文書が、協調する文書 CAPTURED-DOC の一部のサブセクション
CAPTURE-TARGET の座標にビデオトラックを切り抜きたい場合、
CAPTURING-DOC
はどのようにすれば高性能かつ信頼性高くそれを行えるか。特に、スクロール、ズーム、またはウィンドウのサイズ変更によるレイアウトの変化が追加の課題をもたらすことを思い出されたい。
同一タブ内の異なる iframe にホストされる 2 つの主要な部分、すなわちビデオ会議アプリケーションと生産性スイート
アプリケーションからなる複合アプリケーションを考える。ビデオ会議側が
getDisplayMedia()
および/または getViewportMedia などの既存/今後の API を用い、
タブ全体をキャプチャすると仮定する。今度は、生産性スイートの特定のセクション以外のすべてを切り抜いて除去する必要がある。
結果として得られる切り抜かれたビデオをリモートに送信する前に、自身のビデオ会議コンテンツ、発表者ノート、および生産性スイート内のその他の私的および/または無関係なコンテンツを切り抜いて除去する必要がある。
さらに、協調する 2 つのアプリケーションは互いにクロスオリジンである可能性が高いことを考慮する。それらはメッセージを投稿できるが、すべての通信は 非同期であり、かつそれらの間で情報を控えめに送信する方が容易で高性能である。 これは、フレーム全体を投稿する解決策や、レイアウトの変化(例: スクロール、ズーム、ウィンドウサイズの変更)への反応が遅すぎる 解決策を排除する。
ほとんどのアプリケーションは、そのようなシナリオでは
getViewportMedia を使うことを好むであろう点は注目に値する。しかし、この執筆時点では、
getViewportMedia はまだ仕様化されておらず、実装もされていない。それには
採用にいくらかの時間と労力を要する、些細でない要件がある。そのため、多くの
アプリケーションは、今後しばらくの間、getDisplayMedia()
と
Region Capture の組み合わせを使用する可能性が高い。
領域キャプチャ機構は 2 つの部分で構成される:
Element を
切り抜き機構の潜在的なターゲットとして タグ付けするための機構。
Element の輪郭に合わせて
ビデオトラックの切り抜きを開始するようユーザーエージェントに指示する、またはそのような切り抜きを停止してトラックをその
未切り抜き状態に戻すための機構。
ビデオトラックについて、2 つの 切り抜き状態、すなわち 切り抜き済み および
未切り抜き を定義する。トラックは
未切り抜きで開始し、
それらに対して
cropTo が正常に呼び出されたとき、
切り抜き済みに変わりうる。
この文書で提示される 切り抜き機構
(cropTo) は、直接的なノード参照ではなく、
Crop-session Target に依存する。
これは二重の目的を果たす。
CropTarget は、意図的に空で不透明な識別子である。その目的は、入力として
cropTo に渡されることである。
WebIDL[Exposed=(Window,Worker), Serializable]
interface CropTarget {
[Exposed=Window, SecureContext] static Promise<CropTarget> fromElement(Element element);
};
fromElement
をセキュアコンテキストを越えて公開すべきかどうかについては、
まだ合意がない。
fromElement()
サポートされる型の Element を指定して
fromElement を呼び出すと、その
Element は
CropTarget に関連付けられる。この CropTarget は、
cropTo
への入力として使用できる。
CropTarget.fromElement()
の呼び出しによって返され、
かつまだ アクティブな
文書 内にあるものを、
有効な
CropTarget と定義する。
指定された element で
fromElement が呼び出されたとき、ユーザー
エージェントは element を入力として CropTarget を作成する。
ユーザーエージェントは Promise p を返さ
MUST。
ユーザーエージェントは、新しい CropTarget
に関連付けられた状態の必要な内部伝播をすべて完了した後に限って
p を解決し MUST、その時点でユーザーエージェントは、新しい
CropTarget を
cropTo への有効な
パラメーターとして受け取る準備ができていなければ MUST ならない。
以前に fromElement が呼び出された
Element をクローンする場合、
そのクローンはいかなる CropTarget
とも関連付けられない。後でそのクローンに対して
fromElement が呼び出された場合、
新しい CropTarget がそれに割り当てられる。
CropTarget の生成を、
CropTarget.fromElement()
のような非同期メソッドの呼び出しによって行うべきか、
それとも
入力として Element を受け取る
CropTarget コンストラクターによって行うべきかについては、
まだ合意がない。これは
issue #17
でさらに議論されている。
element を入力として CropTarget を作成するには、次の手順を実行する:
cropTarget を、型 CropTarget
の新しいオブジェクトとする。
weakRef を element への弱参照とする。
weakRef に初期化された cropTarget.[[Element]] を 作成する。
cropTarget は、それが表す要素への弱参照を保持する。言い換えると、 cropTarget はその要素のガベージコレクションを妨げない。
CropTarget オブジェクトはシリアライズ可能である。
value、serialized、および真偽値 forStorage が与えられたときの
シリアライズ
手順は次のとおりである:
forStorage が true の場合、
name 属性の
値が "DataCloneError" である
新しい DOMException
オブジェクトで例外を投げる。
serialized.[[CropTargetElement]] を
value.[[Element]] に設定する。
serialized および value が与えられたときの デシリアライズ 手順は次のとおりである:
value.[[Element]] を
serialized.[[CropTargetElement]] に設定する。
[SCREEN-CAPTURE] によれば、
getDisplayMedia()
が呼び出されたとき、
それは Promise<MediaStream>
を返し、
この MediaStream
には、
型が MediaStreamTrack
である
ビデオトラックが正確に 1 つ含まれることを思い出されたい。
ユーザーが browser display-surface のキャプチャを選択した場合、ユーザー
エージェントはビデオトラックを MediaStreamTrack、
または MediaStreamTrack
の何らかの
サブクラスとしてインスタンス化しなければ MUST ならず、
かつ cropTo はこのトラックで公開されなければ
MUST ならない、と規定する。簡単のため、この文書では、ユーザーエージェントによって
BrowserCaptureMediaStreamTrack
と呼ばれるサブクラスが使用されると仮定する。
トラックは初期状態で 未切り抜きでなければ MUST ならない。
WebIDL[Exposed = Window]
interface BrowserCaptureMediaStreamTrack : MediaStreamTrack {
Promise<undefined> cropTo(CropTarget? cropTarget);
BrowserCaptureMediaStreamTrack clone();
};
cropTo()
このメソッドの呼び出しは、ビデオトラックを cropTarget.[[Element]] の
境界クライアント矩形
に合わせて切り抜くことを開始/停止するようユーザーエージェントに指示する。トラックは
display-surface の可視ビューポートに制限されるため、キャプチャされる
領域は、可視ビューポートと要素の境界クライアント矩形との交差部分になる。
cropTo が呼び出されるたびに、
ユーザーエージェントは次のアルゴリズムを実行しなければ MUST ならない:
cropTarget が 有効な CropTarget でも
null でもない場合、
ユーザーエージェントは UnknownError で
拒否された Promise を返さなければ
MUST ならない。
Promise とする。次の手順を並列に実行する:
undefined
でも 有効な CropTarget
でもない場合、
p を NotAllowedError
で拒否し、これらの手順を中止する。
cropTarget が undefined
または 有効な
CropTarget のいずれかである場合、
ユーザーエージェントは cropTarget に従って this
ビデオトラックの 切り抜き状態を更新しなければ
MUST ならない:
undefined
に設定された場合、
ユーザーエージェントは
切り抜きを停止しなければ MUST ならない。This ビデオトラックは
未切り抜き状態に戻る。
CropTarget
によって参照される要素の輪郭に合わせて
切り抜き始めなければ MUST ならない。これは、
トラック上で生成される各新しいフレームについて、ユーザーエージェントがその要素に属するピクセルの境界ボックスを計算し、
この境界ボックスの座標に合わせてフレームを切り抜くことを意味する。
このメソッド呼び出し前のトラックの状態を PRE-STATE と呼び、 このメソッド呼び出し後の状態を POST-STATE と呼ぶ。ユーザーエージェントは、 PRE-STATE に従って切り抜かれた(または未切り抜きの)フレームがそれ以上アプリケーションに配信されないこと、 およびアプリケーションに配信される追加のフレームがしたがって POST-STATE または それ以降の状態のいずれかに従って切り抜かれる(または未切り抜きになる)ことが保証されたとき、 p を解決しなければ MUST ならない。
cropTo promise の解決タイミングおよびビデオフレームの実際の切り抜きタイミングは、 MediaStreamTrack transforms を通じて JavaScript から観測可能である。 最初の新たに切り抜かれたビデオフレームは、cropTo promise が解決された直後に MediaStreamTrack ReadableStream にキュー投入されることが期待される。
clone()
BrowserCaptureMediaStreamTrack
がクローンされるとき、ユーザーエージェントは、元のトラックの
切り抜き状態に関係なく、
初期状態で 未切り抜きであるトラックを生成しなければ
MUST ならない。
fromElement の呼び出しを通じて
CropTarget が生成された
Element を、
潜在的な
切り抜きターゲット と定義する。
cropTo の正常な呼び出しによって
ターゲットにされた
潜在的な切り抜きターゲットを、
crop-session target と定義する。
切り抜き済みビデオトラック上に生成されたフレームを考える。ユーザーエージェントは、 (i) 最上位 閲覧コンテキストのビューポートと、(ii) crop-session target に属するすべてのピクセルの境界 ボックスとの交差部分を計算する。この交差部分を、そのフレームにおける crop-session target の座標と定義する。
指定された crop-session target TARGET に切り抜かれた ビデオトラック VT 切り抜き済みを考える。 TARGET が被る変化に直面した際の、VT の crop-session の動作を定義する。
crop-session target が DOM に接続されているものの、 最上位 閲覧コンテキストのビューポート内に描画されるピクセルが 0 個である場合を、 空の crop-session target と定義する。
これが起こりうる例には次のものが含まれる:
ユーザーエージェントは、空の crop-session target を持つトラック上で新しいフレームを生成しては MUST NOT ならない。そのようなトラックについて、トラックが 未切り抜きになるか、またはその crop-session target が 空でなくなった場合、ユーザーエージェントは フレームの生成を再開しなければ MUST ならない。
DOM から切り離された crop-session target を、 切断された crop-session target と定義する。
空の crop-session target と 切断された
crop-session target の違いは、切断されたものは
到達不能になる可能性があり、
その場合は新しいフレームを生成しないことである。それにもかかわらず、ユーザーエージェントは
切断された crop-session
target を、
空の crop-session
target と同じように扱わなければ MUST ならない。アプリケーションは、
cropTo を
トラックに対して undefined または
新しい CropTarget のいずれかで呼び出すことができ、それによりトラック上の
フレーム生成を再開できる。
キャプチャ対象内のコード:
const mainContentArea = navigator.getElementById('mainContentArea');
const cropTarget = await CropTarget.fromElement(mainContentArea);
sendCropTarget(cropTarget);
function sendCropTarget(cropTarget) {
// postMessage() を使って、またはその他の任意の手段を使って、
// このタブ内の別の文書に crop-target を送信できる。
// 場合によっては他の文書がなく、これは単にローカルで消費される。
}
キャプチャ文書内のコード:
async function startCroppedCapture(cropTarget) {
const stream = await navigator.mediaDevices.getDisplayMedia();
const [track] = stream.getVideoTracks();
if (!!track.cropTo) {
handleError(stream);
return;
}
await track.cropTo(cropTarget);
transmitVideoRemotely(track);
}
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: