概要
業務にてwebrtcを用いたボイスチャットルームを作成する機会があったため、技術的な仕様や概要を記事としてまとめておく
前提
- ピュアP2Pで実装
- Skywayやagoreなどの外部SDKは利用しない
WebRTCとは
WebRTC (Web Real-Time Communications、ウェブリアルタイムコミュニケーション) は、ウェブアプリケーションやウェブサイトにて、仲介を必要とせずにブラウザー間で直接、任意のデータの交換や、キャプチャしたオーディオ/ビデオストリームの送受信を可能にする技術です。 WebRTC に関する一連の標準規格は、ユーザーがプラグインやサードパーティ製ソフトウェアをインストールすることなく、ピア・ツー・ピアにて、データ共有や遠隔会議を実現することを可能にします。
要約するとWeb上でメディア(音声や映像)を扱ったり、データをリアルタイムに送受信するためのJavaScriptのAPIのこと。
WebRTCを利用してどのようにビデオチャットルームを実装するのか
WebRTCではブラウザ上で取得したメディア(マイクからの音声,カメラの映像など)をMediaStreamとして他のユーザーにP2P通信で渡すことができる
ルームに存在するユーザー全てと相互に通信を行うことでボイスチャットルームを実装することができる。
フロー図
デカい上にフローチャートなのかシーケンスなのか分かりずらい謎図形で申し訳ない...(メモ程度のガバ図なので参考までに)
フロー詳細
1.ルーム作成フェーズ/ルーム検索フェーズ/ルーム入室リクエスト
WebRTCとしては関連しない処理部分、ルームを作成できる、ルームを検索できる、認証が必須といったドメインをこちらで実装(お好みで)
2.SDPの交換
※この段階でホストがルームを立て、ルームIDが採番されている(ルームが特定できるようになっている)前提。
- 入室しようとしている部屋に属する自分以外のユーザー(ホスト・ゲスト)に対するOfferSDPを作成しWebサーバーへ送信する
- Webサーバーは2で受け取った人数分のOfferSDPをWebSocketで各ユーザーへ通知(送信)
- WebSocketサーバーからSDPを通知された各ユーザーは受け取ったSDPをremoteSDPとして保存し、返送用のAnswerSDPを生成する
- 3で生成したAnswerSDPをOffer元ユーザーに返送する(Webサーバー,WebSocket経由)
- OfferSDP送信元クライアントは4のAnswerSDPをremoteSDPとして保存する
3.ICE Candidateの交換
ICE Candidate(通信経路情報)をPeer同士で交換することでリアルタイムでの音声通信が可能になる
- GetICECandidateEventからICECandidateを取得し、Room内の他のユーザーにWebサーバー,WebSocket経由で送信
- ICE Candidateを受け取ったユーザーはICE Candidateとユーザー情報を保存
1,2のステップを通信するPeer同士で行い、通信可能な経路が判明した時点で接続される
基本動作原理
- SDPに基づいて相手と接続情報(メディアの圧縮方式など)を交換する。
- 接続情報(通信経路情報)の交換はICEを用いて行う
- 交換した情報を互いにセットする(local,remoteの接続情報)※接続情報の交換に関する仕様は定義されていない。よってXhrHttpRequest,Email,手紙,口頭何を使って接続情報を交換しても良い。一般的にはシグナリングサーバーが立てられ、peer - signalingServer - peerの通信を行う。
- SDPとICE Candidateの交換を双方の端末で終え次第P2P通信のための準備が完了する
WebRTCで使われるプロトコル
-
Session Description Protocol (SDP)
- P2P通信を実現する際に交換する端末の接続情報に関するプロトコル
-
Interactive Connectivity Establishment(ICE)
- 後述のSTUNやTURNサーバーを利用してブラウザをPeerと接続できるようにするフレームワーク
-
Session Traversal Utilities for NAT (STUN)
- パブリックアドレスの発見、ピアとの直接接続を制限するルーターの制限を特定するプロトコル
-
Network Address Translation (NAT)
- ローカルネットワークの端末にパブリックIPアドレスを割り当てるために使用されるプロトコル
- ルーターがSymmetricNATなどでローカルネットワークへのピアからの接続に制限をかけている場合は後述のTURNサーバーが用いられる
-
Traversal Using Relays around NAT (TURN)
- 前述のSymmetric NATが用いられている場合、ピアからの直接接続は不可能なため、このTURNサーバーを利用して接続する
- P2Pと比較しオーバーヘッドが大きくなるためSTUNでP2Pが不可能と判別された場合のみ利用する
所感
- ピュアP2Pでルーム(多人数)通信はクライアントの負荷が大きく、品質が担保できないため利用できない(WebSocketでのICECandidate,SDPの交換や、接続後のメディアの送受信の負荷)
- フロー図上だと通信相手の特定のための情報をクライアントから渡しているがサーバー上で管理すべき
- 実装もそこそこの難易度ながらturnサーバーやwebsocket関連の設定がなかなかに面倒だった。ネットワーク構成がWebRTCだけで一気に複雑になる。
- WebRTCが利用できればテキスト、音声、ビデオなど基本全てのRealTimeCommunicationが可能なので非常に有用
- 商用アプリには現時点でSFU方式での実装がクライアント/サーバー両者の負荷とパフォーマンス面で一番最適である。一方、実装コストが非常に高いため、中小規模のアプリではSkywayやagora.ioなどのSDKが用いられることがほとんど。