(2019/07/16:追記) 考察と結論をアップデートしました。
モバイル環境でも WebRTC を利用する場合、回線が細かったり、キャリアの通信量上限などで映像・音声の配信ビットレートは結構重要なウェイトを占めると思います。
色々とビットレート制御を調べているうちに、Chrome では指定した映像ビットレート通りに配信されないという事象を見つけました。
どうも、音声ビットレートに食われてしまっているようなので、配信ビットレートの制御について説明しつつ、どういう事象が起きるか説明したいと思います。
WebRTC の配信ビットレートの制御
WebRTC では配信側のフレームサイズ、フレームレートおよび圧縮コードによって配信ビットレートが決まる。
フレームサイズやフレームレートは getUserMedia の constraints などで指定し、圧縮コードは SDP で指定することになる。
フレームサイズやフレームレートは、カメラデバイスのスペックに依存するため、constraints の exact を使って厳密に指定することは現実的ではないため、max/min などで幅を持たせることになる。
その際、ウェブブラウザの実装に応じてフレームサイズやフレームレートが最適化されて、配信ビットレートが決まる。
SDP による映像配信ビットレート制御
WebRTC では SDP の m=video 内で TIAS および AS を指定することでビットレートを制御できるで配信ビットレートを指定することができる。
映像の場合、下記のようにすることで 512 kbps に制限することを伝えている。
m=video 9 UDP/TLS/RTP/SAVPF 120 116 117 96 97
b=TIAS:512000
b=AS:512
...
SDP で配信ビットレートを指定すると、ブラウザが上記のビットレートに収まるように、フレームサイズやフレームレートを上手く調整してくれる。
例えば、getUserMedia の constraints で下記を指定して、配信ビットレートの変えてみよう。
const constraints = {
video: {
enable: true,
width: { min: 640, ideal: 1280, max: 1920 },
height: { min: 480, ideal: 720, max: 1080 },
facingMode: 'user'
},
audio: { enabled: false }
};
navigator.mediaDevices.getUserMedia(constraints).then(stream => {
...
}.catch(...);
AS:512 を指定した場合
解像度 720p のフレームを 20fps でエンコードしており、55513 Bytes/s = 444kbps で配信していることがわかる。
配信ビットレートはフレームの大きさで変わるため、少し上下する。
少し眺めていた感じでは、52000 ~ 60000 Byts/s あたりに収まっていた。
AS:256 を指定した場合
解像度が 960x540 に変わり、配信ビットレートが 28225 Bytes/s = 225kbps になっている。
フレームレートは変わっていないので、フレームサイズを変更して指定された配信ビットレートに合わせようとしていることがわかる。
音声配信ビットレートの指定
音声も同様に SDP で maxaveragebitrate を指定することで音声配信ビットレートを制御できる。
m=audio 9 UDP/TLS/RTP/SAVPF 109
a=fmtp:109 maxplaybackrate=48000;maxaveragebitrate=256000;stereo=1;sprop-stereo=1;minptime=10;useinbandfec=1
...
Chrome の場合、6000 ~ 510000 bps の範囲でサポートされているようだ。
https://chromium.googlesource.com/external/webrtc/+/HEAD/api/audio_codecs/opus/audio_encoder_opus_config.h#28
Chrome の映像配信ビットレートの指定がうまく行かない件
前述のとおり、配信ビットレートを指定することで、フレームサイズやフレームレートはブラウザが調整してくれる。
上記は Chrome の例だったが、Firefox でも同様である (Safari や Edge は知らない)。
さて、本題。
上記の例では audio を disable にしていた。
ここで audio を true にして、映像・音声の配信ビットレートをそれぞれ指定して chrome://webrtc-internals を見てみる。
映像:512kbps、音声:32kbps の場合
映像まわりの stats
音声まわりの stats
映像:512kbps、音声:256kbps の場合
映像まわりの stats
音声まわりの stats
映像ビットレートが音声ビットレートに食われてる?
比較しやすいように映像の bitrate を並べてみる
左が音声 32kbps で右が 256kbps である。
画像が小さくて申し訳ないが、明らかに映像の bitrate が下がっている。
この事象は Firefox では発生しない。
スクショが取れていないが、音声ビットレートの値を 192kbps などの大きい値にしたり、マルチストリーム環境で配信者を複数に増やすと、この差が顕著に見受けられる。
考察
RFC4566 や RFC3890 を読む限り、RTP session 毎なので m=video の下に書いていれば映像にだけ影響すると思っているのだが、AS の略が Application Indicated bandwidth なので、映像・音声を含めた全体を示すのかもしれない。
また、Chrome でこのような事象が発生して、Firefox では発生していないが、Firefox ではそもそも音声ビットレート制御 (maxaveragebitrate の指定) が効かないようなので、Chrome の方が WebRTC の挙動として正しい可能性がある。
結論
映像のビットレートを指定することは出来ない。
SDP において、AS に指定する値は映像・音声ビットレートを足し合わせた値を指定し、音声ビットレートを maxaveragebitrate で指定することで、映像のビットレートを間接的に指定する方法が良さそう。
注意事項として、maxaveragebitrate は Firefox では効いていないため、Chrome と Firefox で映像ビットレートは異なるので注意 (全体のビットレートは同じはず)。
Top comments (0)