Open8
WebRTCについて理解する

WebRTC(Web Real-Time Communication)とは、ブラウザ間でリアルタイムの音声、映像、データ通信を可能にするオープンソースの技術。
特別なプラグインやソフトウェアをインストールすることなく、ウェブブラウザだけでビデオ通話やファイル共有がおこなえます。Googleが開発を主導し、W3CとIETFによって標準化が進められいる。
ビデオ通話やチャット、P2P(Peer-to-Peer)通信を容易に構築できるのが特徴。

WrbRTCの仕組み
- シグナリングサーバー
- どの相手と通信するか、その通信の条件を交渉するプロセス
- シグナリング自体はWebRTCの仕様に含まれておらず、WebSocketやHTTPを使って実装する必要がある
- STUN/TRUNサーバー
- STUN(Session Traversal Utilities for NAT):クライアントのグローバルIPアドレスを取得し、P2P通信を確立。
- TURN(Traversal Using Relays around NAT):直接通信ができない場合、リレーサーバーを経由して通信。
- SFUサーバー
- 複数のクライアント間でのメディアデータの中継をおこない、効率的な通信環境を構築する
- サーバーを間に挟むことで、動画の視聴者増加などによる、端末への負荷軽減
ref: https://blog.stackademic.com/understanding-webrtc-and-how-to-use-it-in-android-mobile-applications-d313dda386d5

WebRTC通信は、以下の手順
- シグナリングフェーズ: 相手との接続情報を交換する。
- ICEのネゴシエーション: 最適な通信経路を確立する。
- RTCPeerConnectionの確立: コネクションが確立され、データが送受信可能に。
- メディア・データの送受信: 音声、映像、チャットのデータなどをP2Pで交換。
- 接続終了: 通話終了時にリソースを解放する。

P2Pの通信をするにあたって簡単にできるわけではなく様々な障壁と回避策によって手順と実装は複雑になる。
まず P2P の直接通信を試し、必要に応じて STUN サーバーと通信し、それでも通信が確立しない場合は TURN サーバーを利用する。

- RTCPeerConnection
WebRTC通信の中心で、P2P接続の確立、管理、メディアストリームやICE候補の処理を行う。 - RTCDataChannel
ファイル共有やチャットメッセージの送受信など、P2Pでの任意のデータ通信を提供する. - getUserMedia
ユーザーのカメラやマイクのアクセスを許可し、音声・映像ストリームを取得する。
通信開始から終了までの流れ
- メディアの取得:getUserMedia()を使用してカメラとマイクにアクセス。
- RTCPeerConnectionの作成:ICEサーバーを設定してRTCPeerConnectionを作成。
- SDP Offerの送信:createOffer()でSDPを生成し、相手に送信。
- ICE候補の交換:onicecandidateでICE候補を相手と共有。
- SDP Answerの受信:相手のSDP AnswerをsetRemoteDescription()で設定。
- 通信の確立:onconnectionstatechangeで接続状態を監視。
- データやメディアの交換:RTCDataChannelとMediaStreamでデータ交換。
- 接続の終了:peerConnection.close()でリソースを解放。

サンプルコード
const config = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };
const peerConnection = new RTCPeerConnection(config);
// データチャネルの作成
const dataChannel = peerConnection.createDataChannel('chat');
// メディアストリームの取得と追加
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => {
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
document.getElementById('localVideo').srcObject = stream;
});
// SDP Offerの作成と送信
peerConnection.createOffer().then(offer => peerConnection.setLocalDescription(offer));
// 相手からのAnswerとICE候補の処理
peerConnection.onicecandidate = event => {
if (event.candidate) {
// ICE候補を相手に送信
}
};
peerConnection.ontrack = event => {
document.getElementById('remoteVideo').srcObject = event.streams[0];
};
// チャットメッセージの送受信
dataChannel.onopen = () => dataChannel.send('Hello!');
dataChannel.onmessage = event => console.log('Received:', event.data);

WebRTCアーキテクチャの種類
P2P
- 特徴: クライアント間で直接接続し、メディアストリームやデータをやり取りする。
- 利点:
- 中継サーバーが不要で、低遅延・高速な通信が可能。
- コストがかからない。
- 欠点:
- クライアントが増えると、各端末のネットワーク負荷が増加。
- NATやファイアウォールを超える必要があり、通信が不安定になることがある。
- ユースケース:
- 1対1のビデオ通話(例: WhatsApp、Facebook Messengerのビデオ通話)。
- 小規模なファイル共有。
SFU
- 特徴: クライアントから受信したメディアストリームを**中継サーバー(SFU)**が選択的に他のクライアントに転送。
- 利点:
- クライアントごとの送信負荷が軽減され、スケーラビリティが向上。
- 選択的なストリーム転送により、帯域幅の無駄を削減。
- 欠点:
- SFUサーバーの管理・運用が必要。
- P2Pよりわずかに遅延が増える可能性がある。
- ユースケース:
- 多人数のビデオ会議(例: Zoom、Google Meet)。
- 視聴者数が多いライブストリーミング。
MCU
- 特徴: 各クライアントから送信されたストリームを、MCUサーバーで合成し、1つのストリームとして各クライアントに送信。
- 利点:
- クライアント側の負荷が最小化される。
- ネットワーク帯域が限られている場合に有効。
- 欠点:
- MCUサーバーに高い処理負荷がかかる。
- 高コストで、遅延が発生しやすい。
- ユースケース:
- リモート会議室システム。
- 高品質な映像・音声が必要なシーン。
ref: https://rtcweb.in/scaling-your-webrtc-application-in-2021/

P2Pはリアルタイム性高いものの、NATやファイヤーウォールのことを考えるとあまり現実的ではないのかもしれない。
1対1であってもSFUサーバーなどを介したほうが現実的。
同じLAN内であればP2Pは実現しやすそう。