WebRTC備忘録

# WebRTCって何
リアルタイム通信に特化したプロトコルで、主にブラウザ上で使われる。Google MeetやZoomなどのビデオ会議システムの内部ではWebRTCが使われている。

もともと映像/音声通信のために生まれたプロトコルだが、データ通信のためのDataChannelという機能もあり、その用途はビデオ通話に限らない。

リアルタイム通信のためのプロトコルはWebSocketがあるが、WebSocketはTCPが使われているので、2024年現在、Web上でUDPを使うことができる唯一の手段になっている。

# WebRTCの歴史
1992年、Ron FrederickはIPマルチキャストを使ってビデオカンファレンスの送受信をする実験をしていた。

この実験では、ビデオカンファレンスの受信者が、単純にマルチキャストグループにフィードされたパケットを取得するだけという簡素な仕組みであった。

Ron Frederickは、当時のISDNの回線で十分に映像が再生できるために映像を圧縮することを考え、おおよそ128 kbpsの帯域で映像を送受信できるようにした。

このプロトコルは`nv`というツールとして組み込まれ、IETFの会議に使われた。のちにこのプロトコルがRTPとして標準化されることになった。

90年代にこの`nv`が普及していったが、使い方が難しく誰もが簡単に使えるようなものではなかかった。

現在GoogleのプロダクトマネージャーであるSerge Lachapelleはブラウザからビデオ通話ができるようにしたいと考え、Marratechという会社を設立し、この`nv`の技術をもとにしたソフトウェアを開発した。

Maratechは2007年にGoogleに買収され、Googleではこの技術を使ってGmailのビデオ通話機能を開発した。

2010年、RTPをもっと使いやすくするという目的のもと、Google, Cisco, Ericsson, Skype, Mozillaなどの企業が協力して、WebRTCが標準化されることになった。


# WebRTCのメリット/デメリット

## メリット
1. ブラウザでUDPが使える
2. P2Pで通信ができるため、サーバー維持費がかからない。サーバーを経由しないあため、遅延が少ない。またE2Eの暗号化使われるため、第三者に盗聴される心配がない。一方で、SFUやMCUを使うことで一対多の通信もできる。
3. パケットの到達保証性と速度を調節できる（DataChannel）

## デメリット

1. シグナリングという経路情報を交換するための仕組みが必要。このためにWHIPやWHEPというプロトコルが近年提案されている。
2. リアルタイム通信に特化しているため、シークなど、過去のデータを取得するような昨日は組み込まれていない。

# WebRTCの構成

WebRTCはプロトコルの寄せ集めで、それ自体に機能はない。WebRTCのRFCは薄い(そもそもユースケース）

使われているプロトコルは次のようなものがある。

- ネットワーク層
    - IPv4/IPv6
- トランスポート層
    - UDP
- アプリケーション層
    - SDP
    - ICE
    - RTP/RTCP
    - SCTP

RFC7478としてWebRTCのユースケースがまとめられている。

[Web Real-Time Communication Use Cases and Requirements](https://datatracker.ietf.org/doc/html/rfc7478)

## RTP

RTPパケットは次のような構造になっている。

```code
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|  CC   |M|     PT      |       Sequence Number         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           Timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Synchronization Source (SSRC) identifier            |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|            Contributing Source (CSRC) identifiers             |
|                             ....                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Payload                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```

## RTCP
WebRTCの映像と音声はRTPで送られている。`RTP`はパケット送信の制御をするプロトコルである、`RTCP`とセットになっており、その送受信の統計情報を送りあっている。

この統計情報に基づいて、RTCPははRTPの解像度を変えたり、バッファサイズを変えたり柔軟に調節するため遅延を小さくできる。

```code
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|    RC   |       PT      |             length            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Payload                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```


### Sender Report

```code
     0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P|    RC   |   PT=SR=200   |             length            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         SSRC of sender                        |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
sender |              NTP timestamp, most significant word             |
info   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |             NTP timestamp, least significant word             |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         RTP timestamp                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     sender's packet count                     |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      sender's octet count                     |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_1 (SSRC of first source)                 |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
```

### Receiver Report

```code
        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
header |V=2|P|    RC   |   PT=RR=201   |             length            |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                     SSRC of packet sender                     |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_1 (SSRC of first source)                 |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  1    | fraction lost |       cumulative number of packets lost       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           extended highest sequence number received           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      interarrival jitter                      |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                         last SR (LSR)                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                   delay since last SR (DLSR)                  |
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
report |                 SSRC_2 (SSRC of second source)                |
block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2    :                               ...                             :
       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
       |                  profile-specific extensions                  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```

### Full INTRA-frame Request (FIR)
映像はフレーム間圧縮をしているので受信者はキーフレームが来るまで再生できないため、`FIR`というパケットを使って要求する機能がある。

## シグナリング

WebRTCではP2Pの通信をするために、シグナリングという仕組みが必要になる。まず送受信する映像や音声の情報を交換するために`SDP(Session Description Protocol)`というプロトコルを使う。

加えて、通信をするための経路情報を交換するために`ICE(Interactive Connectivity Establishment)`という経路情報を交換するためのプロトコルがある。

この二つの情報を交換する仕組みをシグナリングという。

なお、どちらもWebRTCのために生まれたわけではなく、WebRTCが生まれる前から別のRFCとして公開されている。

### [SDP(Session Description Protocol)](https://datatracker.ietf.org/doc/html/rfc8866)

メディアの情報を交換するためのプロトコルで、次のような情報が含まれる。

- 音声
    - コーデック
    - サンプリングレート
    - チャンネル数

- 映像
    - コーデック
    - フレーム数

#### SDPの意味
```tex:sdp例
v=0
o=- 0 0 IN IP6 ::1
s=柔道トップ選手のトレーニングが過激すぎた - YouTube - Google Chrome
c=IN IP6 ::1
t=0 0
a=tool:libavformat 58.51.101
m=video 3001 RTP/AVP 96
b=AS:200
a=rtpmap:96 MP4V-ES/90000
a=fmtp:96 profile-level-id=1
```

**v=0**

SDPのバージョンは0を使う

**a=tool:libavformat 58.51.101**

ffmpegのlibavformatのver58.51.101を使っているという意味。

libavformatとは、mp4やmkvなどのコンテナから、H264やAACなどの映像や音声ストリームを取り出したり（demux）、逆に映像・音声ストリームをコンテナに入れたり（mux）するライブラリのこと。

**m=video 3001 RTP/AVP 96**

映像をポート3001宛に送る。RTPプロトコルを使って、ペイロードタイプ96を使う。AVP=Audio/Video Profile

**a=rtpmap:96 MP4V-ES/90000**

ペイロードタイプ96はMP4V-ESを使って90000Hzのサンプリングレートで送るという意味。

**b=AS:200**

200kbpsの帯域を使う

**a=fmtp:96 profile-level-id=1**

追加のペイロードタイプのパラメータを指定する。ここではペイロードタイプに96を使って、h264のprofile-idに1(Baselineかな？）を使うという意味。

### [ICE(Interactive Connectivity Establishment)](https://datatracker.ietf.org/doc/html/rfc8445)

端末がグローバルIPアドレスを持っていない場合、NAT(Network Address Translation)という仕組みを使ってグローバルIPアドレスを持っているサーバーを経由して通信をする。

この場合、NATの持つグローバルIPアドレスや、自分の端末と結び付けられたポート番号を相手に伝える必要がある。

`ICE`はこの経路情報を交換するためのプロトコルで、STUN(Session Traversal Utilities for NAT)というサーバーを使って自分のIPアドレスやポート番号を取得する。

`ICE`には`Tricke Ice`と`Vanilla Ice`の2種類あり、コネクションの手順が若干変わる。

#### ICE type

ICEプロトコルで取得する経路情報を`ICE candidate`という。

`ICE candidate`の種類は経路で分類され、`host`,`srflx`,`pfux`,`relay`の4種類がある。
- host
    - ローカルIPアドレスを使うもの
- srflx/pfux
    - STUNサーバから得られるNATのアドレスが入る。NATのタイプによって変わる
- relay
    - TURNサーバを使うもの

[WebRTC connectivity](https://developer.mozilla.org/ja/docs/Web/API/WebRTC_API/Connectivity)

#### Trickle/Vanilla

ICEの交換方法は二種類あり、情報がすべて集まってから相手に送るのがVanilla、随時送信するものをTrickleという。

Trickleの方が接続完了までの時間がかなり早くなる。一方で、Vanillaの場合はICEはSDP内に含まれているため、実装としてはシンプルになる。

Vanillaの場合はSDPのcandidate行にiceが含まれているので、これでつながる場合ICEの交換は不要になる。

```tex:sdp内に含まれるICE
a=candidate:1 1 UDP 2130706431 10.0.1.1 8998 typ host
a=candidate:2 1 UDP 1694498815 192.0.2.3 45664 typ srflx raddr
```

https://tools.ietf.org/id/draft-ietf-mmusic-ice-sip-sdp-14.html#rfc.section.3

## DataChannel
Webのスタックの一つに、映像とは別に任意のデータ形式の通信方法としてDataChannelがある。
SCTPプロトコルが使われていてTCPとUDPのいいとこどりができる。信頼性と速度を必要に応じて調節できる。

## SFUとMCU
1-Nの通信をする点で共通のトポロジーだが、SFUはデータを中継するだけだが、MCUはデコード/エンコードをして画像加工などをすることができる。


## SFUのRTCP送受信
実装依存と思いますがJanusに限って言えば、RTCPパケットはSFUとエッジ間ではやり取りせずにSFUはRTCPパケットの中継だけ行う。


## サイマルキャスト
複数の解像度をSFUに送る方法で、エッジデバイスは自身の処理速度に合わせて解像度を選択できるメリットがある

# 誤解されやすいWebRTCの仕組み

## SRTPとDTLS

WebRTCの映像と音声はSRTP(Secure Real-time Transport Protocol)で暗号化されており、AESで暗号化されている。その鍵交換にはDTLS(Datagram Transport Layer Security)が使われているが、鍵交換が終了した後はSRTPの仕組み、つまりアプリケーション層で暗号化されている。