第5話: WebRTC の雑多なメモ 〜 REAL WORLD HTTP第7章より 〜
の第5話です。
WebRTC(Web Real-Time Communication)
WebRTCはブラウザ/サーバー間の通信だではなく、ブラウザとブラウザのP2P通信で使用します。 RTCは「リアルタイムコミュニケーション」の略で、テレビ電話などのリアルタイムコミュニケーションを 実現するための基盤として設計されています。
実現したいアプリケーションも他のプロトコルとは大きく異なるため、使われる機能群も大きく変わります。 通信の基盤に使うトランスポート層は、再送処理の面倒を見てくれるTCPではなく、 エラー処理や再送処理を行わないUDPをメインで使います。
またP2P通信なので、相手もブラウザを探すシグナリング、ルーター内部のプライベートアドレスしか 持たないコンピューターで動いているブラウザのため、NATを超えてプライベートアドレスだけで通信 できるような技術も使われています。
RTCPeerConnection
WebRTCの技術要素について説明していきますが、 ブラウザから使われるAPIという観点で説明していきます。
- RTCPeerConnection: 通信経路の確保とメディアチャンネルのオープン
- mediaDevices.getUserMedia: カメラ、マイクと動画・音声のハンドリング
- RTCDataChannel: データチャンネルの通信
WebRTCのベースになっているのはIP電話です。 IP電話で使われている技術を一つにまとめ、JavaScriptのAPIを定めたものです。 NAT超えなどの基礎をなすプロトコルはどれも古くからあるものです。
IP電話についてはこちら: http://www.pc-master.jp/internet/ip-denwa.html
P2P通信を確立するまで
ブラウザ間でP2P通信を行うには、相手のIPアドレスを知らなくてはなりませんし、 動的に割り振られるUDPのポート番号も知る必要があります。 また、その通信でやり取りできる内容についても、お互い合意しておく必要があります。 そのためP2P通信が確立するまでに、WebRTCではいくつかの情報をやり取りしています。
ICE(Interactive Connectivity Establishment)
ICEはNATを超えてP2P通信の接続を確立する手法です。 STUNとTURNのどちらかのサーバーを利用します。
(今回はSTUNで説明します)
NATを越えてP2P通信するには、シグナリング処理でお互いに自分の知らないグローバルの情報を 交換する必要があります。
画像: https://html5experts.jp/mganeko/20618/
自分で知らない情報は、誰かから教えてもらうしかありません。 それを可能にするのがSTUNです。
STUNの仕組みはシンプルです。 NATで変換されたIPアドレス/ポートを、外側にいるSTUNサーバーに教えてもらいます。 先ほどの例で言えば、このようになります。
画像: https://html5experts.jp/mganeko/20618/
自分のグローバル情報が分かったら、それをシグナリングサーバー経由で相手に渡します。 STUNサーバーから得られた情報は、シグナリングの過程でICE Candidateとして取得できます。 これをシグナリングサーバーなどを経由して相手に送ることができ、P2P通信が実現しています。
画像: https://html5experts.jp/mganeko/20618/
SDP(Session Description Protocol: セッション記述プロトコル)
SDPはP2Pのネゴシエーション時に互いのIPアドレストポート、双方で利用できるオーディオや動画の コーデック情報を共有するためのものです。
コーデック (Codec) は、符号化方式を使ってデータのエンコード(符号化)とデコード(復号)を双方向 にできる装置やソフトウェアなどのこと。 また、そのためのアルゴリズムを指す用語としても使われている。
参照: https://ja.wikipedia.org/wiki/コーデック
WebRTCでは「自分が使えるコーデック情報やIPアドレスなどをSDPというプロトコルのフォーマットで 記述して相手に渡し、相手からも互いに利用可能なコーデック情報のレスポンスをもらう」という手続きを 定めていますが、「相手に渡す」手段は定めていません。
渡す手段とかはこちらを参照すると良いとのことです。
https://html5experts.jp/mganeko/19814/
メディアチャンネルとgetUserMedia
相手との通信が確立したら、実際に通信を行います。 音声やビデオを取り扱うのがメディアチャンネルです。
navigator.mediaDevices.getUserMedia()
ビデオ会議などで使うウェブカメラやオーディオデバイスの、設定と取得を行うブラウザAPIです。
カメラは解像度、フレームレート、フロントカメラ/リアカメラなどを指定することもできます。 取得されたものはストリームという名前で呼ばれます。 このAPIは単独でも使うことができ、HTMLのvideoタグ上にカメラの映像を表示できます。
APIについて: https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/getUserMedia
オーディオはWeb Audio APIを利用することで高度な制御やモニタリングが行えます。 ステレオの音位の指定やミキシング、ボリューム調整などができます。 Audio Workerを利用すると音声信号をJavaScriptで分析できるようになるため、 しゃべっている人の検出なども可能となります。
Web Audio APIについて: https://developer.mozilla.org/ja/docs/Web/API/Web_Audio_API
DTLS
WebRTCのデータ通信には、メディアチャンネルとデータチャンネルの2つがあります。 どちらも、DTLS上の通信となっています。
DTLSについてはこちら
参考: http://www.nttpc.co.jp/yougo/DTLS.html
メディアチャンネル
音声・動画を伝送するWebRTC Mediaチャンネルです。 WebRTC MediaチャンネルはDTLS上のSRTPというプロトコルをつかっています。
- S: セキュリティ
- RTP: リアルタイムプロトコル
音声や動画のストリーミングで情報が入れ替わってしまうのは問題なので、 順序の整列機能だけをUDPに追加しています。
データチャンネル
データチャンネルは音声以外のデータをP2Pで送受信するためのものです。 ユースケースにはファイルをチャットの相手に送信したり、 通信対戦のゲームの捜査情報を共有するのに使用していました。 データチャンネルはDTLSの上でSCTP(Stream Control Transmission Protocol)という プロトコルを載せています。
データのユースケースは映像・音声よりも多少幅があります。 データファイルのデータが途中で消失してしまったり、一部欠落すると困ることもあれば、 それより応答性が損なわれる方が問題になることもあります。
そこでSCTPではパフォーマンスとトレードオフで信頼性を設定できるようになっています。 UDP側に寄せるか、TCP側に寄せるか、選べるようになっています。
TCP | UDP | SCTP | |
---|---|---|---|
信頼性 | 到達保証あり | 到達保証なし | 変更可能 |
配送順序 | 順序付けあり | 順序つけなし | 変更可能 |
転送方式 | バイト指向 | メッセージ指向 | メッセージ指向 |
輻輳制御 | あり | なし | あり |
データチャンネルの初期化は以下のように行います。 2つ目の引数が特性を制御するパラメータです。 省力時はTCP同等の配送順序保証の高信頼性モードになります。 このサンプルコードは順序を保証せず、再送もしないというUDP互換のモードを設定しています。 maxRetransmitTimeかmaxRetransmitsのどちらかを設定し、再送方式を手動にすると非信頼モードになります。
const connection = new RTCPeerConnection() const dataChannel = connection.createDataChannel('data channel', { orderd: false, // 順序保証? maxRetransmitTime: 0, // 再送し続ける期間 maxRetransmits: 0 // 再送回数 })
ファイル送信などのユースケースであればデフォルトの高信頼性モードが適しています。 例えば、画像ファイルやEXCELファイルのデータの一部が変えたり順序が入れ替わってしまったら、 ファイルとして用をなさないからです。 ゲームのステータスで、UDPの1パケットに治るサイズであれば、少なくとも順序保証はありません。
参考になりそうなサイト: https://www.html5rocks.com/ja/tutorials/webrtc/datachannels/