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

