WebRTCのSDP typeにおけるpranswerとは
はじめに
WebRTCではSDPを示すオブジェクトとして、RTCSessionDescriptionが利用される。RTCSessionDescriptionにはいくつかのタイプがあり、通常利用するのが”offer”と”answer”だ。実はあまり知られていないが、UXを向上させるための手段として”pranswer”というタイプもある。
私の知る限り、日本語で言及されている情報は見つからなかったので、本記事にて”pranswer”について解説する。
本記事の概要、読むと得られるもの
- “pranswer”とは?なぜ必要なのか?
- JavaScriptからどうやったら使えるのか?
対象読者
- WebRTCのクライアントサイドを開発しているエンジニア
- SDPについて多少なりとも知識がある人
では本題。
pranswerとは?
まず、pranswerとはProvisional Answerの略だ。Provisionalとは”暫定的な”と捉えると良い。最終的に確定したAnswerの前に用いるAnswerのことを、Provisional Answerと呼ぶ。別にChrome限定の裏メニューでもなんでもなくて、W3Cの仕様にも、IETFの仕様にも規定されている。たとえば、IETF側の仕様であるJSEPから一部の図を抜粋すると以下になる。
setRemote(OFFER) setLocal(PRANSWER)
/-----\ /-----\
| | | |
v | v |
+---------------+ | +---------------+ |
| |----/ | |----/
| | setLocal(PRANSWER) | |
| Remote-Offer |------------------- >| Local-Pranswer|
| | | |
| | | |
+---------------+ +---------------+
^ | |
| | setLocal(ANSWER) |
setRemote(OFFER) | |
| V setLocal(ANSWER) |
+---------------+ |
| | |
| |<---------------------------+
| Stable |
| |<---------------------------+
| | |
+---------------+ setRemote(ANSWER) |
^ | |
| | setLocal(OFFER) |
setRemote(ANSWER) | |
| V |
+---------------+ +---------------+
| | | |
| | setRemote(PRANSWER) | |
| Local-Offer |------------------- >|Remote-Pranswer|
| | | |
| |----\ | |----\
+---------------+ | +---------------+ |
^ | ^ |
| | | |
\-----/ \-----/
setLocal(OFFER) setRemote(PRANSWER)
PRANSWERの文字がいくつかの箇所で見えると思う。注目すべきは状態遷移で、LocalにしろRemoteにしろPRAnswerを設定した後は、PRAnswerを保持した状態になり、その後PR無しのAnswerをsetするとStableになる点だ。
これを使うと何が嬉しいのか?(なぜ必要なのか?)
かなりニッチなユースケースだが、こんなアプリを作りこむときに役立つ。
- 前提:1:1のビデオチャットをする
- 処理の流れ
- 通信は自動的に応答するのではなくて、受信側に「応答可否」を確認するダイアログが出る
- OKであれば「応答」ボタンを押して接続を開始する
このとき、pranswerを使うと[1]の段階で、音声映像のトラフィックは送受信しないものの、DTLSの確立・ICEによるP2P/TURN経由の接続確立を裏で済ませることができる。そして[2]で、実際にユーザが「応答」ボタンを押したときにトラフィックの送受信を開始する。(DTLSおよびICEの処理は完了しているので、接続までの時間が非常に早いのがポイント)
個人的な意見の補足:ここまで頑張って接続時間を早くしようというアプリケーションは少ない気がするが、1つの手として知っておくのには役立つと思われる
やりかた
createAnswer()
を読んでSDPのオブジェク卜を取得できたら、中身をちょっとだけ変えてあげるだけで良い。具体的にはこんな感じ:
peerConnection.createAnswer( (description) => {
description.sdp = description.sdp.replace(/a=sendrecv/g, 'a=inactive');
description.type = 'pranswer';
}, (error) => {});
短いコードだがポイントは2点:
a=sendrecv
のように記載される方向属性をa=inactive
に書き換えてあげること。これによってメディアのトラフィックは送受信されなくなる。- typeに
pranswer
を設定してあげること
これでpranswerを利用できる。
まとめ
本記事では、WebRTCにおけるpranswerの必要性、その利用方法について解説を行った。