さらっと触れるWebRTCの基礎知識


# はじめに
[iRidge Advent Calendar 2020](https://qiita.com/advent-calendar/2020/iridge) 10日目の記事です。

コロナの影響でリモート○○が一般的になりつつあるからか最近WebRTCのご相談を受ける機会が増えており、過去の記憶を掘り起こしながら対応している日々の@ya8612tecです。
せっかく思い出したので、また忘れる前に後々思い出すとっかかりになるよう、WebRTCについてさわりの部分を記載しておくことにしました。
自身の備忘録として書いていますが、初めてWebRTCに触れる人のとっかかりにもなるように雰囲気がなんとなく伝わる言い回しにしているので、厳密な表現は[公式](https://webrtc.org/)や途中にリンクしているドキュメントを読んでください！

# WebRTCって？
**主に**Webブラウザを利用して映像・音声・データを**P2Pで**やりとりする技術です。
（iOS, Androidのネイティブアプリでも実装すれば可能です）
大きく分けて、映像・音声を扱う[MediaStream](https://www.w3.org/TR/mediacapture-streams/)と対向機器との通信を行う[PeerConnection](https://www.w3.org/TR/webrtc/#peer-to-peer-connections)の2つが基礎になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96952/5842b99c-348e-e622-c73d-a4b81f536d3c.png)

## MediaStream
カメラ・マイク・画面といった映像・音声をキャプチャし、ストリームデータとしてvideoタグやPeerConnectionへ流します。
映像・音声はそれぞれTrackという単位で扱われます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96952/8cb57d08-35df-541a-f2da-ef388740cd0f.png)
> 出典：https://dev.w3.org/2011/webrtc/editor/archives/20130320/getusermedia.html

APIの[Webブラウザ対応状況](https://caniuse.com/stream)はこちらで確認できます。

## PeerConnection
メディアチャネル(RTCPeerConnection)とデータチャネル(DataChannel)の2つのチャネルがあり、プロトコルスタックはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96952/159570f1-8ab5-aa02-b10f-59b4612dfa06.png)
> 出典：https://www.researchgate.net/figure/Web-Real-Time-Communications-WebRTC-protocol-stack_fig1_339838518

### RTCPeerConnection
SRTP(Secure Real-time Transport Protocol)を使用してMediaStreamをやりとりします。
APIの[Webブラウザ対応状況](https://caniuse.com/rtcpeerconnection)はこちらで確認できます。

### DataChannel
SCTP(Stream Control Transport Protocol) over DTLS(Datagram Transport Layer Security) over UDPを使用してバイナリデータをやりとりします。([RFC8261](https://tools.ietf.org/html/rfc8261))
APIの[Webブラウザ対応状況](https://caniuse.com/mdn-api_rtcdatachannel)はこちらで確認できます。

ICE(Interactive Connectivity Establishment)

# WebRTCの接続方式
この3方式があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96952/00972c8c-b2e9-c4a1-dad6-ab63b77acb8a.png)

|方式|接続数|CPU|帯域|
|:-:|:--|:--|:--|
|P2P|送信：n-1<br>受信：n-1|クライアント：高<br>メディアサーバ：ー|クライアント：高<br>メディアサーバ：ー|
|SFU|送信：1<br>受信：n-1|クライアント：中<br>メディアサーバ：中|クライアント：中<br>メディアサーバ：中|
|MCU|送信：1<br>受信：1|クライアント：低<br>メディアサーバ：高|クライアント：低<br>メディアサーバ：低|
※　**n=ユーザ数**。高中低はユーザー数の増加時に各方式を比較した場合の相対的な評価としてます。

### P2P
- メディアサーバを経由せず、クライアント間で送受信します
- クライアント側でレイアウトを自由に組むことが可能です<br>(それぞれのMediaStreamを紐付けたvideoタグを配置する）
- ユーザ数に比例して通信量とクライアント負荷が上がります
- TURNサーバをクラウドサービスで構築した場合、通信料要注意

### SFU
- メディアサーバ経由で送受信します
- 配送するのみなので、クライアント側でレイアウトを自由に組むことが可能です<br>(それぞれのMediaStreamを紐付けたvideoタグを配置する）
- ユーザ数に比例して通信量とクライアント負荷が上がります
- SFUサーバをクラウドサービスで構築した場合、通信料要注意

### MCU
- メディアサーバ経由で送受信します
- サーバで映像・音声を合成するのでレイアウトは予めサーバ側で用意されたものになります
- ユーザ数が増えてもクライアント負荷や通信量は一定になります
- ただし、合成するためサーバ負荷は上がるため、要求スペックは高くなります

# まとめてるうちに蘇った記憶
まとめてるうちに思い出したかつての苦しみをここでいくつか共有しておきたいと思います。
- Webブラウザ(たしかFirefoxだった)がバージョンアップしたら、あるOSSで埋め込まれていた画面共有ボタンが反応しなくなった<br>→セキュリティ強化された結果、そのOSSの実装で使ってたJavaScriptが動作しなくなってた
- なんかカメラが使えないんだけど<br>→あるメーカのノートPCは内臓カメラをON/OFFできて、それでOFFになってた
- なんか画面共有できないんだけど<br>→Macのセキュリティとプライバシーで画面収録がOFFになってた
- 映像送ってるはずなのにvideoタグが真っ黒<br>→タグにautoplayを指定してなかった

# おわりに
OSSに甘えて中の仕組みをちゃんと追ってないので、時間見つけてドヤ顔で説明できるくらいまでは頑張ってキャッチアップしたいと思いました。。。
皆様も、なんとなく動かすだけなら大丈夫ですが運用やデバッグするとなると幅広い知識（ネットワーク、Webブラウザ、インフラなどなど）が必須なので、興味がある人は覚悟して手を出すことをオススメします〜

# 学習資料
（本記事を書く上でも）よくお世話になっているページ
- [公式](https://webrtc.org/)
- [時雨堂さんのサイト](https://webrtc.shiguredo.jp/)
- [HTML5experts](https://html5experts.jp/series/webrtc2016/)

# おまけ
- [ソースコード](https://webrtc.googlesource.com/src)
- [TestRTC](https://testrtc.com/)