Sora によるピア接続の流れ

P2P 接続

WebRTC は Web ブラウザ間でリアルタイムコミュニケーションを可能にする技術であり、その主な通信手段の一つが P2P 接続です。

一般的な P2P 接続のメリットの一つに、サーバーを介さずにユーザー間でメディアデータを送受信できることが挙げられます。 WebRTC でも同様で、 P2P 接続であれば Web ブラウザのみでリアルタイムコミュニケーションが可能です。 WebRTC における P2P 接続のもう一つのメリットとして、送受信されるメディアデータが接続先ユーザーの通信速度に合わせて圧縮されることが挙げられます。 これにより、各接続先ユーザーとメディアデータを安定して送受信できるようになります。

ただし、 P2P 接続がすべての状況で最適な手段になるとは限りません。 メディアデータが各接続先ユーザーの通信速度に合わせて個別に圧縮されると、結果的に接続先ユーザーが増えれば増えるほど通信量と CPU の負荷が大きくなります。 また、 WebRTC の P2P 接続では Web ブラウザ間のみですべての通信が完結するとは限らず、サーバーが不要になるとも言えません。 P2P 接続を行うには、まず接続先の情報を知る必要があります。 接続先の IP アドレスやポート番号、もしくは何らかのサービスを利用しているなら、アカウント名やそのサービスに関する情報を取得しなければなりません。 WebRTC では接続先ユーザー同士で情報を交換するフェーズをシグナリングと呼び、シグナリングサーバーを介して接続先の情報を取得します。 さらに NAT 越えを解決する ICE サーバーも必要であり、 P2P 接続であってもこれらの二種類のサーバーが使われます。

サーバーによる配信: SFU

複数のユーザーにメディアデータを配信する場合、 P2P 接続では配信者の端末の負荷が大きなネックになります。 特にモバイル端末では高負荷の処理によるバッテリーの消費量を無視できません。

この問題はメディアデータの配信をサーバー経由で行うことで解決できます。 サーバーによる配信方法は現在二種類あり、一つが Sora が採用している SFU (Selective Forwarding Unit) 、もう一つが MCU (Multipoint Control Unit) です。 クライアントはサーバーとのみメディアデータの送受信を行えばよく、 P2P 接続と比べて通信と CPU の負荷を抑えられます。 メディアデータがサーバーを経由するため、映像の録画や加工も可能になります。

SFU と MCU の大きな違いは、送受信するメディアデータの圧縮の有無にあります。 P2P 接続では送信側のクライアントはメディアデータを (コーデックに従って) 圧縮し、受信側のクライアントは圧縮されたメディアデータを復元します。 この際、双方のクライアントには圧縮・復元の負荷がかかります。 SFU では受信したメディアデータを加工せずに他のクライアントに分配し、 MCU では受信したメディアデータを一旦復元してから送信先の各クライアントごとに (通信状況に合わせて) 圧縮します。 端末の負荷の軽さでは MCU に分があり、サーバーの負荷の軽さでは SFU に分があり、どちらにもメリットとデメリットが存在します。

Sora におけるピア接続の流れ

この節では Sora を使うピア接続の流れを説明します。 Sora iOS SDK を使えば詳細を知らなくてもアプリケーションを作れますが、 Sora とクライアントの挙動を理解しておくとトラブルに対処しやすいでしょう。

Sora は WebSocket でシグナリングの通信を行い、シグナリングメッセージを JSON フォーマットで送受信します。 WebSocket の接続が切れるとシグナリングを継続できなくなります。

クライアントは WebSocket で Sora サーバーに接続し、以下に示す connect メッセージを送信します (シグナリングメッセージの詳細は Sora のドキュメント を参照してください) 。

connect メッセージ例:

{
    "type": "connect",
    "role": "upstream",
    "channel_id": "Spam",
    "metadata": "1234abcd"
}

Sora サーバーは connect メッセージを受信すると認証を行います。 認証が成功すればクライアント ID (ユニークな値) を発行し、クライアント ID を含む offer メッセージを返します。

offer メッセージ例:

{
    "type": "offer",
    "sdp": "<Offer 用 SDP>",
    "client_id": "<ユニークな ID>"
}

offer メッセージには Offer SDP が含まれます。 クライアントはこの段階でピア接続オブジェクト (WebRTC ライブラリの RTCPeerConnection オブジェクト) を生成し、 Offer SDP を remote description にセットします。 また offer メッセージは ICE に関する設定を含む場合があり、その設定はピア接続オブジェクトに反映されます。

このときにピア接続オブジェクトによって ICE candidate が生成されたら、クライアントは candidate メッセージを生成して ICE candidate の内容を Sora サーバーに送信します。

Offer SDP が無事に remote description にされたら、クライアントは Answer SDP を生成します。 Answer SDP はピア接続オブジェクトの local description にセットされ、それが成功すれば Answer SDP を含む answer メッセージを Sora サーバーに送信します。

answer メッセージ例:

{
    "type": "answer",
    "sdp": "<Answer 用 SDP>"
}

ICE 接続が成功すればピア接続完了です。 ピア接続中は接続状態などの情報がシグナリングで通信されます。 ICE 接続もしくはシグナリング接続が解除されるとピア接続は終了します。

WebRTC ライブラリのメディアストリームと Sora のメディアストリームの違い

WebRTC ライブラリのメディアストリームはそれぞれ一つずつの入出力ストリームを持ちますが、 Sora のメディアストリームはどちらかのストリームしか持てません。 そのため Sora で入出力を同時に扱いたいなら (iOS アプリケーションで端末のカメラ映像をサーバーに送信し、同時にサーバーからリモート映像を受信するなど) 、ストリームごとにピア接続を用意する必要があります。 Sora iOS SDK では接続過程の詳細な処理を隠蔽していますが、内部では一つのチャネルにつき二本 (入力と出力) のピア接続を持っています。