3.3 シグナリングのシーケンス RTCPeerConnection オプジェクトの生成 時に接続する場合はその接続数だけオプジェクトを生成することになります。 このオプジェクトは 1 接続につき 1 つずつ必要です。ビデオ会議のように複数人と同 シグナリングは主にこのオプジェクトのメソッドを呼び出しあうことで行われます。 生成しています。 RTCPeerConnection は WebRTC 接続の基礎となるオプジェクトで、 図 3.1 ではアリスとポプのどちらも、最初に RTCPeerConnection オプジェクトを メディアストリームの登録 横に置いといてください。 コンストラクター引数の内容と意味については第 4 章で説明しますので、今はいったん iceTransportP01icy: ' a11 ' 'stun: stun ・ 1 ・ google ・ com: 19302 ' } ] , iceservers : let pc = new RTCPeerConnection ( { マリスト 3.1 RTCPeerConnection 次に、人力デバイスから取得したメディアストリームを相手に送信するために アストリームのトラックを RTCPeerConnection オプジェクトに登録します。 Y リスト 3.2 addTrack(addStream) / / メディアストリームは事前に取得しておく 1et 10ca1Stream = await navigator. mediaDevices . getUserMedia( {audio: true, video : true} / / 送信したい自分のメディアストリームを登録する / / ※ pc は RTCPeerConnection オブジェクト if ( 'addTrack' in pc){ / / 新仕様 10ca1Stream. getTracks() . forEach( (track) = > { pc. addTrack(track, 10ca1Stream) ; }else{ / / 旧仕様 pc. addStream(10ca1Stream) ; メディ 現在の仕様では、 addTrack メソッドを呼び出してメディアストリームに含まれるト ラック単位で登録を行います。以前の仕様では、 addStream メソッドを呼び出してメディ 39
このボタンを押すと、 8.3 ローカルサーバーに外部から接続できるようにする (HTTPS 対応 ) ージが起動します。このページが表示されている状 テノヾック、ノ 態で getUserMedia でメディアストリームを取得したり WebRTC で通信を行ったりする と、統計情報が表示されます。なお、デバイスの使用許可は必ず「常に許可」するように してください。一時的な許可では統計情報を取得できず、動作しません。 十 WebRTC E 対書 n 5 、十一①ー張第能 ( we TC E 0 「「は引 moz - e 対印・に 龕 ト Create Dump GetUserMed ia Req 5t5 http引″ d9314 ( 56. ap. れ q 「 Ok.io / [hu1dhd1it3-Ol h ps : / / d9314 ( 56. 叩 . ng 「 ok. io /. (object Objectl, undefined 石 m ・ 2017 / 10 / 7 18 : 20 : 16 2017 / 10 / 7 1 & 20 : 16 2017 / 10 / 7 1820 : 16 2017 / 10 / 7 1 & 20 : 16 2017 / 10 / 7 18 : 20 : 16 201 〃 10 / 7 18 : 20 : 16 2017 / 10 / 7 1820 : 16 2017 / 10 / 7 18 : 20 : 16 2017 / 10 / 7 1820 : 16 2017 / 10 / 7 18 : 20 : 16 E ・ n 【 ト addTrack onnegotiationneeded ト addTrack 5 獸 Remo 【を De 、 ( ⅱ p ⅱ on addlceCandidate (host) ト ontrack ト Ontrack ト Onaddstream 0 れ引 gnaling 、い t を ( hang ~ ト、に一 Rem 20e5 ( ⅱ p 【 iOnOnSu ( ( es 、 △図 8.14 WebRTC Externals の表示 (Firefox) WebRTC ExternaIs は、 WebRTC に関する統計情報を取得する JavaScript を Web ページ内に埋め込むことで動作しています。そのため、 WebRTC を使用するべージを表 示するよりも前にデバッグページを起動しておく必要があります。デバッグページを起 動する前に表示されていたページについては統計情報を取得できないので注意してくだ 0 8.3 ローカルサーバーに外部から接続できるようにする (HTTPS 対応 ) WebRTC に直接関係するものではありませんが、開発を行う上で大変便利なサービス を紹介します。 たとえば手元のマシンで WebRTC を利用した Web アプリの開発を行っていて、開発中 のアプリを実行できるサーバーが起動しているとしましよう。このマシンでアプリを実行 する場合、アクセスする URL は http://localhost:xxxx/になります。 Chrome およ び safari では HTTPS のページでないと getUserMedia を利用できませんが、 localhost だけは例外として実行できるのでこの場合は間題ありません。 93
第 3 章通信相手を見つけて、つなげる・・・シグナリング 42 pc. addStream(10ca1Stream) ; / / 旧仕様 }else{ pc. addTrack(track, 10ca1Stream) ; 10ca1Stream. getTracks ( ) . forEach( (track) = > { / / 新仕様 if ( 'addTrack' in pc){ / / ※メディアストリームは事前に取得できている想定 / / ※ IocaIStre は web カメラ等から取得したメディアストリーム iceTransportP01icy: ' a11 ) iceservers : [{urIS : ' stu Ⅱ : stu Ⅱ・ 1 ・ google. com : 19302 ' } ] , let pc = new RTCPeerConnection({ function createRTCPeerConnection(){ / / 各種コールバック関数の設定は発信側・着信側の両方で行うので、関数化しておくと便利 / / RTCPeerConnection オブジェクトの生成や、メディアストリームの登録、 V 発信側・着信側共通 await pc . setRemoteDescription(new RTCSessionDescription(). data. sdp) ) ; / / 相手から送られてきたオファー SDP を RemoteDescription に設定 if (e . data. event = = 'answer' ) { WS. onmessage = async (e) = > { / / WebSocket メッセージを受信 マ再びアリス sdp : answerSdp event : answer ) to: 'A1ice' ws . send({ / / アリスにアンサー SDP を送信 await pc . setLoca1Description(answerSdp) ; / / 生成したアンサー SDP を LocaIDescription に設定 1et answerSdp = await pc. createAnswer() ; / / オファーに対するアンサー SDP を生成 await pc. setRemoteDescription(new RTCSessionDescription(). data. sdp) ) ; / / 相手から送られてきたオファー SDP を RemoteDescription に設定 1et pc createRTCPeerConnection ( ) ; if (e . data. event ws . onmessage = async (e) = > { / / WebSocket メッセージを受信 マボブ ( 着信側 ) sdp: 0fferSdp event : ) offer ) t 0 : ' Bob ' ws . send({ / / ※この部分は仕様で定められていないので自由に実装できる / / ※ ws は WebSocket 接続オブジェクト / / ボブにオファー SDP を送信し、通話開始を要求 await pc . setLoca1Description(offerSdp) ;
第 6 章映像・音声以外をやり取りする・・・アータチャネル アリス サーバー RTCPeerConnection オプジェクトを生成 オファー SDP を生成 オファー ( 自分側 ) SDP を保存 ボとの接続を要求 生成した SDP を送信 DataChannel を生成 アンサー ( 相手劇 SDP を保存 メッセージを転送 ポプ RTCPeerConnection オプジェクトを生成 オファー ( 相手側 ) SDP を保存 アンサー SDP を生成 アンサー ( 自分側 ) SDP を保存ー 生成した SDP を送信 メッセージを転送 △図 6.1 データチャネルでのセッション情報の交換シーケンス 唯一異なるのは、 RTCPeerConnection オプジェクトを生成してから SDP を生成する までの部分です。 メディアストリームの送受信のときは送信したいメディアストリーム ( のトラック ) を addTrack メソッドで登録していましたが、今回はこの手順は必要ありません。というか そもそも送信すべきメディアストリームが存在しないので実行しようがありません。 データチャネルの場合はメディアストリームを登録する代わりに、データチャネルを利 用することを RTCPeerConnection オプジェクトに伝えることになります。 発呼側 発呼側では RTCPeerConnection オプジェクトの createDataChanne1 メソッドを呼 び出し、データチャネルの利用を同オプジェクトに伝えると同時に、 RTCDataChanneI オプジェクトを生成します。 RTCDataChanneI オプジェクトはデータチャネルの接続完 了後、データを実際に送受信するときに必要になるので、あとで参照できるように変数に 人れておきましよう。 createDataChanne1 メソッドは 2 つの引数を受け取ります。 第 1 引数にはラベルとして 65 , 535 バイト以内の任意の文字列を指定します。ラベル といいつつ別にユニークである必要はないので、適当な固定値を指定しておけばよいで 66
第 3 章通信相手を見つけて、つなげる・・・シグナリング アストリーム単位で登録していました。 40 うな操作をするためには、トラック単位で扱えるほうが都合がよいのです。 替えたり、複数の映像トラックを同時に送信したりすることができます。そのよ 本書では説明していませんが、 WebRTC では送信する映像トラックを動的に切り からです。 なぜこのような仕様変更があったかというと、そのほうが都合がよい場合がある 比べると少し冗長なように思えます。 新旧 2 つの仕様を見比べると、旧仕様のほうがシンプルで、現在の仕様はそれに トラックとメディアストリーム event . stream ; remoteVideoEIem. srcObj ect pc. onaddstream = (event) = > { / / 旧仕様 }else{ remoteVideoEIem. srcObject = event. streams [ 0 ] ; if (event . track . kind 'video' ) { / / ontrack イベントは video と audio で 2 回発火するが、 video のときのみ処理を行う pc. ontrack = (event) = > { / / 新仕様 if (typeof pc . ontrack ! = 'undefined' ) { / / ※ remoteVideoE1em は映像の再生を行う video 要素 / / 相手のメディアストリームを表示する マリスト 3.3 ontrack(onaddstream) どうかで処理を分けるとよいでしよう。 Edge は旧仕様のみの対応となっているため、。 ntrack イベントハンドラーが存在するか きます。こちらもやはり Firefox と Safari は新仕様に対応しているのに対し、 Chrome と で、これを video 要素の srcObject として設定すれば相手のメディアストリームを再生で イベントが発火します。これらのイベントの引数にメディアストリームが含まれているの 一方、相手のメディアストリームが利用可能になると、 ontrack または onaddstream ソッドが存在するかどうかを判定して、処理を分ける必要があります。 に対応していますが、 Chrome と Edge は旧仕様にしか対応していません。 addTrack メ プラウザーによって対応状況が分かれており、執筆時現在、 Firefox と Safari は新仕様
2.3 メティアストリームの構造 console. 10g(mediaStream. getTracks() ) ; マリスト 2.15 getTracks メソッドの動作イメージ ソッドで取得できる配列の並び順は順不同で、決まりはありません。 dioTracks メソッドで音声トラックだけが含まれる配列の取得もできます。これらのメ 配列で取得できます。同様に、 getVideoTracks メソッドで映像トラックだけが、 getAu getTracks メソッドを呼び出すと、メディアストリームに含まれるすべてのトラックを を取得した場合は、含まれるトラックは「音声」 1 つだけです。 は、「映像」と「音声」という 2 つのトラックが含まれます。一方、マイクから音声のみ たとえば、 Web カメラから映像を、マイクから音声を取得したメディアストリームに "label't "BUFFALO BSW50KM02 USB Camera ( 0411 : 0263 ) " "id" "61dff5da—11a7—48ee-aa5d-6028d5fb9dcc" mediaStreamTrack { "BUFFALO BSW50KM02 USB Camera" "label" ・ "id" : "c0cb7f01-e8bf-4f2c-b431-e4f2ea902edb" "kind" "audiot' mediaStreamTrack { ません。しかし、メディアストリームに含まれるトラックは固定ではなく、 addTrack メ ディアストリームでは、映像トラックと音声トラックはそれぞれ最大 1 つまでしか含まれ 列であることを不思議に思われたかもしれません。たしかに getUserMedia で取得したメ ところで、 getVideoTracks と getAudioTracks のメソッド名が複数形で、戻り値が配 35 具体的なトラックの操作については、第 3 章で改めて説明します。 こではとりあえずメディアストリームとトラックの関係性だけ理解しておいてくださ め、実際に映像または音声トラックが複数存在することはあり得るのです。 ソッドで新しく追加したり、逆に removeTrack メソッドで削除したりできます。そのた い
第 2 章メディアストリームを取得する・・・ Media Capture API 結果は表 2.8 のとおりです。 表 2.8 順番を入れ替えた場合の条件クリア状況と取得結果 第 1 条件 60. Ofps 第 2 条件 30. Ofps 第 3 条件 15. Ofps 第 4 条件 1 , 920 x 1 , 080 第 5 条件 1 , 280 x 最低条件 640 ~ x 480 ~ 結果画面サイズ フレームレート 720 デバイス A 〇 〇 〇 〇 〇 〇 640 X 480 60.0fps デバイス B 30.0fps 1 , 280 X 720 〇 〇 〇 〇 〇 デバイス C 〇 〇 〇 〇 30.0fps 640 x 480 デバイス D 15.0fps 640X480 〇 〇 こんどはフレームレートのほうが優先される結果となります。デバイス A は、画面サ メディアストリーム 本章の最後に、メディアストリームの構造を確認しておきましよう。 2.3 メディアストリームの構造 x 480 / 60.0fps となります。 出力に対応している画面サイズで条件に合うのは 640 x 480 だけなので、取得結果は 640 イズ 1 , 920 x 1 , 080 や 1 , 280 x 720 のときは 60. ()fps 出力に対応していません。 60. ()fps getVideoTracks() getAud i0Tracks() 音声トラック 1 getTracks() 映像トラック 1 映像トラック 2 removeTrack() 削除 ・不要トラック 新しいトラック 追加 addTrack(track) △図 2.4 メディアストリームの構造イメージ メディアストリームの構造を知る上で重要な概念がトラックです。「トラック」とは、簡 単にいえばメディアストリームに含まれる「映像」や「音声」ひとつひとつのことです * 9 。 * 9DTM で音楽を作るときに、ギターやポーカル、ドラム、べースなど各パート単体で録音した音声のこと を「トラック」と呼びますが、それと同じようなイメージです。 34
8.1 プラウザーの挙動を変える Chrome の場合 起動オプションを指定して Chrome を起動するには少し準備が必要です。 Windows の 起動オプションではさらに実験的な機能を利用できます。 起動オプション ウザーとの間でビデオの送受信ができなくなる可能性があります。 この機能はデフォルトで有効になっています。無効化すると Safari など他のプラ H. 264 ソフトウェア工ンコーダー / デコーダーを使用するかどうかを切り替えます。 WebRTC H. 264 software video encoder/decoder 有効化すると addTrack 、 ontrack など新仕様の API が使えるようになります。 ExperimentaI Web PIatform features 有効化すると新型のエコーキャンセラーが使われるようになります。 WebRTC Echo CanceIler 3. これもまたあまり気にする必要はありません。 有効化すると STUN サーバーへのリクエストにオリジンヘッダーを送出します。 WebRTC Stun origin header を向上しようという機能 * 2 ですが、これもあまり気にする必要はありません。 シテイプな情報が含まれることがあるため、ヘッダー拡張部分も暗号化して機密性 が、付加情報を格納するヘッダー拡張部分は暗号化されません。付加情報にはセン メディアストリームの送受信時、通常はペイロード部分については暗号化されます Negotiation with encrypted header extensions fO 「 SRTP in WebRTC ようになります、 1 。通常はあまり気にする必要はありません。 有効化すると送受信するメディアストリームの暗号化に AES ー GCM を利用できる Negotiation with GCM cipher suites fO 「 SRTP in WebRTC すが、この中に WebRTC に関連した項目がいくっか含まれています。 Chrome では chrome://flags で実験的機能の有効・無効を切り替えることができま chrome://flags Chrome では chrome://flags と起動オプションの 2 つの方法が利用できます。 83 https : / / t001S . ietf .org/htm1/rfc6904 https : / / t001S. ietf .org/htm1/rfc7714 場合はショートカットを作成して右クリックでプロバティを開き、「リンク先」の末尾に * 2 * 1