🧊

“Unified Plan” Transition Guide (JavaScript) の日本語訳

“Unified Plan” Transition Guide (JavaScript) - Google ドキュメント

なんかそのうち仕事で見返しそうな感じがあったので訳してみた。

背景

WebRTCの仕様はここ数年で大きく変化してきた。`addStream()`などのStream系のAPIから、`addTrack()`などのTrack系のAPIへの移行がその一つ。これによって、再ネゴシエーションなしに設定変更が可能になった。

ただWebRTC 1.0へ向けてはまだ大きな変更が残ってて、それが今から話すSDPのフォーマット変更。

仕様の上で「Unified Plan」と呼んでるSDPのフォーマットがある。これは今のChromeが利用している「Plan B」というフォーマットとは別のもの。このフォーマットの移行は、たくさんのアプリケーションに破壊的な変更をもたらす可能性がある。

そのほか、この「Unified Plan」に沿って追加される新しいAPIもある。(`Transceiver`関連)

この記事は、そんなフォーマット移行の助けとなるべく書かれている。

Firefoxは既に「Unified Plan」をサポートしていて、他のブラウザも追ってそれに追従するだろう。

  • 複数のaudio/videoトラックを扱っている
  • ローカル・リモート問わず、トラックのIDが変わらないと仮定している
  • SDPを手動で修正している

あなたのアプリケーションがこれらに当てはまる場合は、注意が必要。

どちらのフォーマットを使うか

アプリケーションで`sdpSemantics`を指定する

`RTCPeerConnection`のコンストラクタに`sdpSemantics`オプションを指定することで、どちらのSDPフォーマットを使うか選ぶことができる。

new RTCPeerConnection({ sdpSemantics: 'unified-plan' });
new RTCPeerConnection({ sdpSemantics: 'plan-b' });

ただしこれはChromeでのみ有効で、他のブラウザでは無視される。

実装が適切に両方のフォーマットに対応していないのであれば、Chromeの仕様変更に備える意味でも、どちらかを指定しておくことを推奨する。

`chrome://flags`によるデフォルト設定

ChromeのM71から`chrome://flags`にて、「WebRTC: Use Unified Plan SDP Semantics by default」というフラグが指定できるようになる。

このフラグを有効にするか、`--enable-features=RTCUnified Plan ByDefault`つきでChromeを起動することでも有効にできる。

これらの指定がない場合も、デフォルトで「Unified Plan」が使われる。

ちなみに、M71未満のChromeの場合は、`--enable-blink-features=RTCUnified Plan ByDefault`というフラグを指定することでも有効にできる。

これは、`sdpSemantics`をコード内で指定してない場合に、その対応をしないとどうなるのかを調べたい場合に使える。

フォーマットの判別

ChromeのM69から`Transceiver`関連のAPIが追加されたが、これらは「Unified Plan」の時のみサポートされる。

「とりあえず`addTransceiver()`を呼んでみて、例外を投げないかどうか」をチェックするのが、「Unified Plan」かどうかをチェックする方法のひとつ。

M70だと、`getConfiguration()`を呼ぶことで正式に`sdpSemantics`の値を知ることができる。(`chrome://webrtc-internals`と同じように)

このあたりのコードスニペットはこちら。

Feature Detection

他のやり方としては、SDPをパースして`m=`行を調べることでもできる。

Unified PlanとPlan Bの違い

SDP上の違い

「Plan B」では、audio/videoごとに、1つのSDPの`m=`セクションがあり、`mid`もそれぞれ割り当てられていた。
なので複数のトラックがオファーに含まれていた場合、複数の`a=ssrc`行がそれぞれの`m=`セクションに含まれることになる。

「Unified Plan」では、1つの`m=`セクションが1つのトラックの送(受)信に割り当てられる。
なので、複数のトラックが存在する場合はその分だけ`m=`セクションが作られる。

これがSDPのフォーマットに互換性がない原因で、「Unified Plan」のピアは「Plan B」のフォーマットのオファーが来た場合、「Failed to set remote answer sdp: Media section has more than one track specified with a=ssrc lines which is not supported with Unified Plan.」といって拒否する必要がある。

また「Plan B」側のピアは、「Unified Plan」のオファーに含まれる最初の`m=`セクションだけを解釈して受け入れてもよい。

以下は2つのaudioトラックを送る場合の「Plan B」と「Unified Plan」それぞれのSDPのサンプル。

説明に必要な部分のみ抜粋してあり、`mid`や`ssrc`は簡略化してある。

Plan B
...
a=group:BUNDLE audio
a=msid-semantic: WMS stream-id-2 stream-id-1
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
...
a=mid:audio
...
a=rtpmap:103 ISAC/16000
...
a=ssrc:10 cname:cname
a=ssrc:10 msid:stream-id-1 track-id-1
a=ssrc:10 mslabel:stream-id-1
a=ssrc:10 label:track-id-1
a=ssrc:11 cname:cname
a=ssrc:11 msid:stream-id-2 track-id-2
a=ssrc:11 mslabel:stream-id-2
a=ssrc:11 label:track-id-2

`a=mid:audio`が使われ、トラックは同じ`m=audio`セクションに含まれる。

Unified Plan
...
a=group:BUNDLE 0 1
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
...
a=mid:0
...
a=sendrecv
a=msid:- <track-id-1>
...
a=rtpmap:103 ISAC/16000
...
a=ssrc:10 cname:cname
a=ssrc:10 msid: track-id-1
a=ssrc:10 mslabel