Document Picture-in-Picture
Document Picture-in-Picture(以下、Document PiP)APIを使用すると、通話UI全体を常に他のウィンドウの上に表示される別のブラウザーウィンドウに分離できます。アプリケーションは、複数のビデオエレメントとコントロールエレメントを希望のレイアウトで自由に構成したHTMLをこのPiPウィンドウ内にレンダリングでき、これによりユーザーが他のタブやウィンドウで作業している間も、引き続き通話UIを表示し続けることができます。
| 対応する通話タイプ | SDKの最低バージョン |
|---|---|
| 1対1通話、グループ通話(カンファレンス) | WebPlanetKit 6.0 |
概要
WebPlanetKitは、Document PiPウィンドウを開き、その中に空のコンテナエレメントを作成して提供します。このコンテナ内に通話UI(ビデオエレメント、コントロールエレメント、レイアウト)を描画するのは、アプリケーションが担当します。
ブラウザーの対応状況を確認する
Document PiP APIは、ChromeやEdgeのようなChromium系のデスクトップブラウザーでのみ使用できます。したがって、UIでPiPのエントリーポイントを公開する前に、必ず現在のブラウザーの対応状況を確認する必要があります。
現在のブラウザーがDocument PiP APIに対応しているかを確認するには、静的メソッドisDocumentPipSupported()を呼び出します。CallやConferenceオブジェクトを作成しなくても使用でき、通話を開始する前にも呼び出せます。Call.isDocumentPipSupported()とConference.isDocumentPipSupported()は、常に同じ値を返します。
Document PiPを使用する
Document PiPウィンドウを開く
openDocumentPip(options)を呼び出すと、PiPウィンドウが開きます。このメソッドは、新しく開かれたPiPウィンドウと、その中に生成された空のコンテナエレメントを一緒に含むDocumentPipResultを結果として返します。アプリケーションでは、このコンテナ内に通話UIを直接描画します。同じDocumentPipResultがevtPipOpenedイベントにも渡されます。openDocumentPip()の戻り値(Promise)をawaitで受け取って使用してもよく、evtPipOpenedイベントで受け取って使用してもかまいません。アプリケーションで都合のよい方を選択してください。
DocumentPipOptionsのフィールド | タイプ | 説明 |
|---|---|---|
width | number | (任意)PiPウィンドウの初期の幅(ピクセル)。 |
height | number | (任意)PiPウィンドウの初期の高さ(ピクセル)。 |
disallowReturnToOpener | boolean | (任意)trueの場合、PiPウィンドウから元のタブに戻るコントロールエレメントを非表示にします。 |
preferInitialWindowPlacement | boolean | (任意)trueの場合、以前に開かれていたPiPウィンドウの位置を記憶せず、最初から新しく配置します。 |
DocumentPipResultのフィールド | タイプ | 説明 |
|---|---|---|
pipWindow | Window | PiPがレンダリングされる別のブラウザーウィンドウです。 |
container | HTMLDivElement | pipWindow内に生成された空のコンテナエレメントで、ここにビデオとUIを描画します。 |
openDocumentPip()は、通話が開始される前には呼び出せません。まず通話を開始する必要があり、makeCall()、verifyCall()、joinConference()のいずれかを呼び出した後は、どの通話状態でもPiPウィンドウを開くことができます。- 1つのページにはDocument PiPウィンドウが1つだけ存在できます。別のインスタンスがすでにPiPウィンドウを持っている状態で
openDocumentPip()を呼び出すと、ブラウザーがリクエストを拒否します。
Document PiPウィンドウを閉じる
ユーザーがPiPウィンドウを直接閉じたり、通話が終了したり、接続が切断されたりすると、PiPウィンドウは自動的に閉じます。この場合はブラウザーやSDKが自動的に処理するため、アプリケーションで別途行うことはありません。
アプリケーションから明示的にPiPウィンドウを閉じるには、closeDocumentPip()を呼び出します。このときevtPipClosedイベントが発生します。開いているPiPウィンドウがない状態で呼び出すと、何も起こらずに正常終了し、evtPipClosedも発生しません。
Document PiPウィンドウが開いたり閉じたりするときの処理を実装する
PiPウィンドウが開いたり閉じたりするタイミングでアプリケーションが処理するロジックがある場合は、通話delegateにevtPipOpenedとevtPipClosedを登録します。evtPipOpenedには、openDocumentPip()が返すものと同じDocumentPipResultが渡されます。evtPipClosedイベントを通じてPiPウィンドウが閉じた理由を確認でき、DocumentPipClosedInfoが渡されます。
DocumentPipClosedInfo.reasonの値 | 意味 |
|---|---|
'user' | ユーザーがPiPウィンドウを閉じた |
'disconnect' | 通話が終了したか、接続が切断された |
'api' | アプリケーションがcloseDocumentPip()を呼び出した |
現在のDocument PiPウィンドウとコンテナを取得する
現在開いているPiPウィンドウのWindowやコンテナエレメントを取得したい場合は、getDocumentPipWindow()とgetDocumentPipContainer()を使用します。開いているPiPウィンドウがない場合、両方のメソッドともnullを返します。
例:タブ移動時にDocument PiPを自動で開く実装
Chromium系のブラウザー(Chrome 120以上)には、通話中のタブからユーザーが他のタブに移動したり、ウィンドウを最小化したりするときに、PiPウィンドウを自動的に開く機能があります。アプリケーションがブラウザーのenterpictureinpictureアクションに対するハンドラーを登録しておくと、ユーザーがタブを離れるたびにChromeがこのハンドラーを呼び出します。ハンドラー内でopenDocumentPip()を呼び出すと、PiPウィンドウが開きます。ユーザーが元のタブに戻ると、ChromeがPiPウィンドウを自動的に閉じるため、アプリケーションがウィンドウの開閉処理を毎回直接管理する必要はありません。
- マイクとカメラをまったく使用しない通話では、自動PiP(auto-PiP)を使用できません。
enterpictureinpictureアクションとDocument PiP APIは、Chromium系のブラウザー(Chrome 120以上)でのみ使用できます。
実装方法
次のコードは、ブラウザーの対応状況の確認、アクションハンドラーの登録、PiPウィンドウが開いたときにローカルユーザーのビデオを描画する処理、通話終了時のハンドラーのクリーンアップまでの全体的な流れを示しています。
if (!PlanetKit.Call.isDocumentPipSupported()) {
// Unsupported browser.
return;
}
// When the user leaves the tab, Chrome calls this handler, which opens the PiP window.
navigator.mediaSession.setActionHandler('enterpictureinpicture', () => {
planetKit.openDocumentPip({ width: 480, height: 360 });
});
planetKit.makeCall({
...,
delegate: {
evtPipOpened: ({ pipWindow, container }) => {
// Draw the local user's video in the container inside the PiP window.
const video = pipWindow.document.createElement('video');
video.srcObject = planetKit.getMyMediaStream();
container.appendChild(video);
video.play();
},
evtDisconnected: () => {
// When the call ends, clean up the registered action handler.
navigator.mediaSession.setActionHandler('enterpictureinpicture', null);
}
}
});
自動PiPの動作条件
Chromeがenterpictureinpictureアクションを呼び出すには、次の2つの条件をすべて満たす必要があります。
- アプリケーションが事前に
enterpictureinpictureアクションハンドラーを登録しておく必要があります。 - ユーザーがタブを離れる時点で、そのタブがマイクやカメラを実際に使用中である必要があります。ここでの「使用中」とは、ブラウザーがマイクおよびカメラのストリームを実際に開き、ブラウザーのタブやアドレスバーの横にマイクおよびカメラの使用インジケーターが点灯している状態を意味します。
上記の2番目の条件に関して、留意すべきいくつかの事項を見てみましょう。
1つ目に、WebPlanetKitは、ユーザーにすぐには必要のない権限の許可を要求することを避けるため、次の2つの場合には通話開始時点でマイクおよびカメラにアクセスしません。
micOn: falseで開始した音声通話micOn: falseかつcameraOn: falseで開始したビデオ通話
したがって、上記の2つの場合で通話を開始すると、ブラウザーがマイクおよびカメラを使用していると認識しないため、enterpictureinpictureアクションが発生せず、結果として自動PiPが動作しません。それ以外の場合、つまりマイクとカメラのいずれか一方でも実際に使用して通話を開始する場合は、SDKが該当するメディアストリームを開くため、自動PiPが正常に動作します。
2つ目に、通話中にミュート(mute)や一時停止(pause)を実行したとき、マイクとカメラの動作が異なります。
- マイク:マイクのミュートはデータの流れを一時的に止めるだけの方式で、ミュートしてもSDKはマイクストリームを閉じずにそのまま維持します。したがって、通話開始時にマイクが一度でもオンになった通話では、その後ミュート状態でバックグラウンドに切り替えても、自動PiPが引き続き動作します。
- カメラ:一時停止すると、SDKはカメラのLEDを消すためにカメラストリームを完全に閉じます。したがって、カメラをオンにした後、一時停止した状態で、マイクが使用中でない場合は、自動PiPが動作しません。
3つ目に、MediaStreamManagerを通じてメディアストリームを生成して通話に使用する場合、MediaStreamManagerが内部でマイクおよびカメラのストリームを開いておくため、micOnやcameraOnの値に関係なく自動PiPが動作します。
関連API
Document PiPに関連するAPIは次のとおりです。
共通
1対1通話
-
CallのisDocumentPipSupported() -
CallのopenDocumentPip() -
CallのcloseDocumentPip() -
CallのgetDocumentPipWindow() -
CallのgetDocumentPipContainer() -
MakeCallDelegateのevtPipOpened -
MakeCallDelegateのevtPipClosed -
VerifyCallDelegateのevtPipOpened -
VerifyCallDelegateのevtPipClosed
グループ通話
-
ConferenceのisDocumentPipSupported() -
ConferenceのopenDocumentPip() -
ConferenceのcloseDocumentPip() -
ConferenceのgetDocumentPipWindow() -
ConferenceのgetDocumentPipContainer() -
ConferenceDelegateのevtPipOpened -
ConferenceDelegateのevtPipClosed