比較的新しい Web API の1つである MediaDevices インターフェースを使って、HTML と JavaScript だけで(PCの)画面共有が実現できるようになりました。とりあえず使ってみるには PC のウェブブラウザ※で以下のサイトにアクセスしてみてください:
https://dotnsf.github.io/display_media_stream/
※対応ブラウザはこちら:
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia#Browser_compatibility
対応ブラウザで上記 URL にアクセスすると、画面共有のダイアログが表示されます:
何かひとつ(下図の例では「アプリケーションウィンドウ」タブの「タスクマネージャー」)選択して、「共有」ボタンをクリックすると、、
選択したアプリケーションのウィンドウ内画面がストリームでウェブブラウザに表示されます。最初に「全画面」を選んでいればウィンドウ全体がブラウザ内に表示されます:
この機能を停止するには共有ダイアログの「共有を停止」ボタンをクリックしてください:
以下、上記デモのソースコードを紹介します。コードそのものはこちらで公開しています:
https://github.com/dotnsf/display_media_stream
上記デモは実質的に index.html ファイルだけで実現しています。つまり HTML と JavaScript だけで実現しています。まず HTML 部(<body>部)は以下の通り、かなりシンプルです:
<div> 要素の中に <video> 要素が1つだけ、autoplay 属性と playsinline 属性がついた状態で存在しています。一応初期サイズの指定もしていますが後で JavaScript で修正します。
次に肝となる JavaScript 部はこちらです:
実質的には $(function(){ ... }); 部分が最初に実行されます。まずは window.parent.screen にアクセスして実画面のサイズを取得し、その縦横割合に合わせて上述の video 要素をリサイズ(縦は 480 に固定して、横を同割合になるようリサイズ)します。
そしてこの画面共有を実現しているのはこの1行です:
mediaDevices インターフェースの getDisplayMedia メソッドを、{ video: true } というオブジェクトを引数に実行しています。これがカメラやマイクではなくディスプレイ画面のストリームを取得するための処理で、成功すると gotLocalMediaStream 関数がコールバックされます。
その gotLocalMediaStream 関数は以下のような内容になっています:
getDisplayMedia メソッドで取得したメディアストリームを引数にコールバックされ、その値を video 要素として取得済みの localVideo 変数の srcObject 属性に代入しています。これだけで後はディスプレイ画面の動画ストリームが video 要素の中で自動再生(autoplay)されます。
mediaDevices インターフェースや getDisplayMedia メソッドがまだ限られたブラウザ(Chrome, FireFox, Edge)の比較的新しいバージョンでしか使えず、スマホ系ブラウザでは全滅という状況ではあるのですが、ネイティブアプリを使わなくてもブラウザの JavaScript だけでここまでできるようになっていたんですね。video 要素として使えるということはスクリーンショットとかいろいろ応用できそう・・・
https://dotnsf.github.io/display_media_stream/
※対応ブラウザはこちら:
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia#Browser_compatibility
対応ブラウザで上記 URL にアクセスすると、画面共有のダイアログが表示されます:
何かひとつ(下図の例では「アプリケーションウィンドウ」タブの「タスクマネージャー」)選択して、「共有」ボタンをクリックすると、、
選択したアプリケーションのウィンドウ内画面がストリームでウェブブラウザに表示されます。最初に「全画面」を選んでいればウィンドウ全体がブラウザ内に表示されます:
この機能を停止するには共有ダイアログの「共有を停止」ボタンをクリックしてください:
以下、上記デモのソースコードを紹介します。コードそのものはこちらで公開しています:
https://github.com/dotnsf/display_media_stream
上記デモは実質的に index.html ファイルだけで実現しています。つまり HTML と JavaScript だけで実現しています。まず HTML 部(<body>部)は以下の通り、かなりシンプルです:
<body> <!-- Video element (live stream) --> <div> <video autoplay playsinline id="video" width="640" height="480"></video> </div> </body>
<div> 要素の中に <video> 要素が1つだけ、autoplay 属性と playsinline 属性がついた状態で存在しています。一応初期サイズの指定もしていますが後で JavaScript で修正します。
次に肝となる JavaScript 部はこちらです:
<script> var localVideo = null; function gotLocalMediaStream( mediaStream ){ localVideo.srcObject = mediaStream; } function handleLocalMediaStreamError( error ){ console.log( "navigator.getUserMedia error: ", error ); } $(function(){ //. 画面サイズ取得 var sw = window.parent.screen.width; var sh = window.parent.screen.height; //sw : sh = x : 480; => x = 480 * sw / sh; var x = Math.floor( 480 * sw / sh ); $('#video').css( { width: x } ); var mediaStreamConstraints = { video: true }; localVideo = document.querySelector( "video" ); navigator.mediaDevices.getDisplayMedia( mediaStreamConstraints ).then( gotLocalMediaStream ).catch( handleLocalMediaStreamError ); }); </script>
実質的には $(function(){ ... }); 部分が最初に実行されます。まずは window.parent.screen にアクセスして実画面のサイズを取得し、その縦横割合に合わせて上述の video 要素をリサイズ(縦は 480 に固定して、横を同割合になるようリサイズ)します。
そしてこの画面共有を実現しているのはこの1行です:
navigator.mediaDevices.getDisplayMedia( mediaStreamConstraints ).then( gotLocalMediaStream ).catch( handleLocalMediaStreamError );
mediaDevices インターフェースの getDisplayMedia メソッドを、{ video: true } というオブジェクトを引数に実行しています。これがカメラやマイクではなくディスプレイ画面のストリームを取得するための処理で、成功すると gotLocalMediaStream 関数がコールバックされます。
その gotLocalMediaStream 関数は以下のような内容になっています:
<script> var localVideo = null; function gotLocalMediaStream( mediaStream ){ localVideo.srcObject = mediaStream; }
getDisplayMedia メソッドで取得したメディアストリームを引数にコールバックされ、その値を video 要素として取得済みの localVideo 変数の srcObject 属性に代入しています。これだけで後はディスプレイ画面の動画ストリームが video 要素の中で自動再生(autoplay)されます。
mediaDevices インターフェースや getDisplayMedia メソッドがまだ限られたブラウザ(Chrome, FireFox, Edge)の比較的新しいバージョンでしか使えず、スマホ系ブラウザでは全滅という状況ではあるのですが、ネイティブアプリを使わなくてもブラウザの JavaScript だけでここまでできるようになっていたんですね。video 要素として使えるということはスクリーンショットとかいろいろ応用できそう・・・