前回の実装編1では、作業準備の処理フローとしてPeerJSの初期化とMediaStreamの取得まで進めました。ここまでで、スマートグラスと監視端末はそれぞれユニークIDが採番されてシグナリングサーバと接続しており、自身のカメラやマイクへのアクセスも可能となっています。
では次に通常作業時の処理フローとして、シグナリング処理からスマートグラスのカメラ映像をリアルタイムに監視端末へ表示する部分まで進めます。
PeerJSを用いて他のPeerとP2P接続する場合、接続先PeerのユニークIDを指定しなければなりません。今回はシンプルに、スマートグラスの接続待ち画面(device画面②/下図左)に表示したユニークID(下図であればf9uyrhv2lzwljtt9)を、監視端末(monitor画面②/下図右)の入力フォームに転記する形で実装しました。
接続要求の送信画面監視端末の「CALL」ボタンをクリックすると、MonictorClassのmakeCallメソッドが呼び出され、シグナリング処理が開始されます。
monitor.coffee$('#make-call').click ->calltoId = $('#callto-id').val()video = $('#device-video')mc.makeCall(calltoId, video, connecting, waiting) # 接続処理実施
MonitorClassのmakeCallメソッドでは、MediaConnectionの接続要求とDataConnectionの接続要求を一挙に実施します。
まずはMediaConnectionの接続処理から追ってみましょう。
MediaConnectionWebRTCのRTCPeerConnectionによって交換されるMediaStreamをラップしたオブジェクト。
MediaConnectionの確立最初に@peer.call()を呼び出すことで、監視端末側からスマートグラスに向けてMediaConnectionの接続要求を出します(Offer送信)。この際、接続済みの監視端末のMediaStreamを引数に渡します。
監視端末側ではこの段階でMediaConnectionオブジェクトが取得できますが、P2P接続が確立していないため、まだ利用できません。
remote-monitor.coffeeclass MonitorClass extends BaseClass...makeCall: (callto, video, connecting, waiting) -> ... # MediaConnectionの接続要求処理 mediaConnection = @peer.call callto, @ls # calltoに向かってMediaConnectionの接続を要求(Offer送信) @connect mediaConnection, video, waiting # BaseClassから継承したメソッドconnect呼び出し# DataConnectionの接続要求処理 ... # DataConnectionのイベント処理 ...
BaseClassに実装されたconnectメソッドには、MediaConnectionの接続が確立した際のイベントハンドラと接続が閉じられた場合のイベントハンドラが記述されています(後述)。
スマートグラスがシグナリングサーバに中継された接続要求を受信すると、@peer.on('call', callback)イベントが発生し、設定したcallback関数が呼び出されます。
下記のように、接続要求受信時には、接続済みのスマートグラスのMediaStreamを引数に接続受託を返信(Answer送信)することになります。
remote-monitor.coffeeclass DeviceClass extends BaseClass...onCall: (video, connecting, waiting) -> console.log "onCall" # @peer.on('call', callback)イベント発生 @peer.on 'call', (mediaConnection) =># 監視端末からの接続要求を受信した際の処理console.log "peer.on 'call'"mediaConnection.answer @ls # 接続元(監視端末)へ接続受諾を返信(Answer送信)@connect mediaConnection, video, connecting, waiting # BaseClassから継承したメソッドconnect呼び出し
MediaConnectionに設定できるイベントハンドラにはいくつかありますが、重要なのは次の2つです。
remote-monitor.coffeeclass BaseClass...connect: (mediaConnection, video, connecting, waiting) -> ... # MediaConnectionのイベント処理 mediaConnection.on 'stream', (stream) =># 接続相手先のMediaStreamが利用可能となった際の処理console.log "mediaConnection.on 'stream'"video.prop 'src', URL.createObjectURL(stream) # 接続相手のMediaStreamをvideoタグのsrcに接続connecting() # 通常作業画面を表示 mediaConnection.on 'close', =># 自分もしくは接続相手先がMediaConnectionを切断した際の処理console.log "mediaConnection.on 'close'"@ls.getAudioTracks()[0].enabled = false # 自分自身のマイクをOFFにする@ems.close() if @ems? # 切断されたMediaConnectionはcloseしておくwaiting() # 接続待ち画面を表示
MediaConnection.on('stream', callback)イベントの発生時には、取得した接続相手のMediaStreamをvideoタグのsrcに接続し、通常作業画面を表示します。
また、MediaConnection.on('close', callback)イベントの発生時には、自分自身のマイクをOFFにした後に切断されたMediaConnectionをcloseし、接続待ち画面へ戻ります。
カテゴリー
関連記事
ホット記事