Chrome 66 では、ウェブページで Presentation API を介してセカンダリ接続ディスプレイを使用し、Presentation Receiver API によってそのコンテンツをコントロールします。
背景
これまで、ウェブ デベロッパーは、リモート ディスプレイに表示されるコンテンツとは異なるローカル コンテンツを Chrome で表示し、同時にそのエクスペリエンスをローカルで制御できるエクスペリエンスを構築できました。たとえば、テレビで動画を再生しながら youtube.com で再生キューを管理する、ノートパソコンでスピーカー ノート付きのスライドリールを表示し、ハングアウト セッションで全画面プレゼンテーションを表示する場合などです。
ユーザーが単に接続された 2 つ目のディスプレイにコンテンツを表示したい場合もあります。たとえば、会議室でプロジェクターが用意され、ユーザーが HDMI ケーブルで接続しているとします。ユーザーは、リモート エンドポイントにプレゼンテーションをミラーリングするのではなく、プロジェクターでスライドを全画面表示して、スピーカー ノートやスライドの操作用にノートパソコンの画面を使用できるようにします。サイト作成者は非常に基本的な方法でこれをサポートできますが(たとえば、新しいウィンドウをポップアップして、ユーザーが手動でセカンダリ ディスプレイにドラッグして最大化する必要があります)、この方法は面倒で、ローカルとリモートの表示のエクスペリエンスに一貫性がありません。
ページを画面共有
ここでは、Presentation API を使用して、セカンダリ接続ディスプレイにウェブページを表示する方法について説明します。最終的な結果は、https://googlechrome.github.io/samples/presentation-api/ でご確認いただけます。
まず、セカンダリ接続ディスプレイに表示する URL を含む新しい PresentationRequest
オブジェクトを作成します。
const presentationRequest = new PresentationRequest('receiver.html');
In this article, I won’t cover use cases where the parameter passed to
`PresentationRequest` can be an array like `['cast://foo’, 'apple://foo',
'https://example.com']` as this is not relevant there.
We can now monitor presentation display availability and toggle a "Present"
button visibility based on presentation displays availability. Note that we can
also decide to always show this button.
<aside class="caution"><b>Caution:</b> The browser may use more energy while the <code>availability</code> object is alive
and actively listening for presentation display availability changes. Please
use it with caution in order to save energy on mobile.</aside>
```js
presentationRequest.getAvailability()
.then(availability => {
console.log('Available presentation displays: ' + availability.value);
availability.addEventListener('change', function() {
console.log('> Available presentation displays: ' + availability.value);
});
})
.catch(error => {
console.log('Presentation availability not supported, ' + error.name + ': ' +
error.message);
});
プレゼンテーション表示のプロンプトを表示するには、ボタンのクリックなどのユーザー操作が必要です。そのため、ボタンのクリックに応じて presentationRequest.start()
を呼び出し、ユーザーがプレゼンテーション ディスプレイ(このユースケースではセカンダリ接続ディスプレイ)を選択した時点で Promise が解決されるのを待ちます。
function onPresentButtonClick() {
presentationRequest.start()
.then(connection => {
console.log('Connected to ' + connection.url + ', id: ' + connection.id);
})
.catch(error => {
console.log(error);
});
}
ユーザーに表示されるリストに、Chromecast デバイスをアドバタイズするネットワークに接続されている場合、Chromecast デバイスなどのリモート エンドポイントが含まれることもあります。ミラーリングされたディスプレイはリストに含まれないことに注意してください。http://crbug.com/840466 をご覧ください。
Promise が解決されると、PresentationRequest
オブジェクト URL のウェブページが、選択したディスプレイに表示されます。これで完了です。
これで、次のように「close」イベントと「terminate」イベントをモニタリングできるようになりました。presentationRequest.reconnect(presentationId)
を使用して「閉じた」presentationConnection
に再接続することもできます。ここで、presentationId
は以前の presentationRequest
オブジェクトの ID です。
function onCloseButtonClick() {
// Disconnect presentation connection but will allow reconnection.
presentationConnection.close();
}
presentationConnection.addEventListener('close', function() {
console.log('Connection closed.');
});
function onTerminateButtonClick() {
// Stop presentation connection for good.
presentationConnection.terminate();
}
presentationConnection.addEventListener('terminate', function() {
console.log('Connection terminated.');
});
ページとやり取りする
これは素晴らしいことですが、コントローラ ページ(先ほど作成したページ)とレシーバー ページ(PresentationRequest
オブジェクトに渡したページ)の間でメッセージを受け渡すにはどうすればよいでしょうか。
まず、以下に示すように navigator.presentation.receiver.connectionList
を使用してレシーバーページで既存の接続を取得し、受信接続をリッスンします。
// Receiver page
navigator.presentation.receiver.connectionList
.then(list => {
list.connections.map(connection => addConnection(connection));
list.addEventListener('connectionavailable', function(event) {
addConnection(event.connection);
});
});
function addConnection(connection) {
connection.addEventListener('message', function(event) {
console.log('Message: ' + event.data);
connection.send('Hey controller! I just received a message.');
});
connection.addEventListener('close', function(event) {
console.log('Connection closed!', event.reason);
});
}
接続がメッセージを受信すると、リッスン可能な「message」イベントが発生します。メッセージには、文字列、Blob、ArrayBuffer、ArrayBufferView のいずれかを指定できます。送信方法は、コントローラ ページまたは受信側ページから connection.send(message)
を呼び出すだけです。
// Controller page
function onSendMessageButtonClick() {
presentationConnection.send('Hello!');
}
presentationConnection.addEventListener('message', function(event) {
console.log('I just received ' + event.data + ' from the receiver.');
});
https://googlechrome.github.io/samples/presentation-api/ のサンプルを使用して、サンプルの動作をご確認ください。私と同じようにお楽しみいただけることと思います。
サンプルとデモ
この記事で使用した公式 Chrome サンプルをご覧ください。
Photowall のインタラクティブなデモもおすすめします。このウェブアプリでは、複数のコントローラが協力してプレゼンテーション ディスプレイに写真のスライドショーを表示できます。コードは https://github.com/GoogleChromeLabs/presentation-api-samples から入手できます。
終わりに
Chrome には、ユーザーがウェブサイトにアクセス中にいつでも開くブラウザ メニュー「キャスト」があります。このメニューのデフォルト表示を制御する場合は、前に作成したカスタム presentationRequest
オブジェクトに navigator.presentation.defaultRequest
を割り当てます。
// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;
開発のヒント
レシーバー ページを調べてデバッグするには、内部の chrome://inspect
ページに移動し、[その他] を選択して、現在表示されている URL の横にある [検査] リンクをクリックします。
内部の検出/可用性プロセスの詳細については、内部の chrome://media-router-internals
ページもご確認ください。
次のステップ
Chrome 66 以降では、ChromeOS、Linux、Windows プラットフォームがサポートされています。Mac のサポートは今後提供される予定です。
関連情報
- Chrome 機能のステータス: https://www.chromestatus.com/features#presentation%20api
- 実装のバグ: https://crbug.com/?q=component:Blink>PresentationAPI
- プレゼンテーション API の仕様: https://w3c.github.io/presentation-api/
- 仕様に関する問題: https://github.com/w3c/presentation-api/issues