WebRTC Chrome で映像ビットレートが音声に食われる件
m-yoshimo
Posted on March 26, 2020
(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 で映像ビットレートは異なるので注意 (全体のビットレートは同じはず)。
Posted on March 26, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024
November 23, 2024
November 14, 2024