DEV Community

m-yoshimo
m-yoshimo

Posted on

WebRTC Chrome で映像ビットレートが音声に食われる件

(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 を指定した場合

SnapCrab_NoName_2019-7-9_13-28-16_No-00.png

解像度 720p のフレームを 20fps でエンコードしており、55513 Bytes/s = 444kbps で配信していることがわかる。
配信ビットレートはフレームの大きさで変わるため、少し上下する。
少し眺めていた感じでは、52000 ~ 60000 Byts/s あたりに収まっていた。

AS:256 を指定した場合

SnapCrab_NoName_2019-7-9_13-30-39_No-00.png

解像度が 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

SnapCrab_NoName_2019-7-9_14-47-42_No-00.png
SnapCrab_NoName_2019-7-9_14-48-29_No-00.png
SnapCrab_NoName_2019-7-9_14-48-57_No-00.png

音声まわりの stats

SnapCrab_NoName_2019-7-9_14-48-1_No-00.png
SnapCrab_NoName_2019-7-9_14-48-42_No-00.png

映像:512kbps、音声:256kbps の場合

映像まわりの stats

SnapCrab_NoName_2019-7-9_14-51-18_No-00.png
SnapCrab_NoName_2019-7-9_14-51-56_No-00.png
SnapCrab_NoName_2019-7-9_14-52-13_No-00.png

音声まわりの stats

SnapCrab_NoName_2019-7-9_14-51-40_No-00.png
SnapCrab_NoName_2019-7-9_14-52-46_No-00.png

映像ビットレートが音声ビットレートに食われてる?

比較しやすいように映像の bitrate を並べてみる
左が音声 32kbps で右が 256kbps である。

SnapCrab_NoName_2019-7-9_14-48-29_No-00.png
SnapCrab_NoName_2019-7-9_14-51-56_No-00.png

画像が小さくて申し訳ないが、明らかに映像の bitrate が下がっている。
この事象は Firefox では発生しない。
スクショが取れていないが、音声ビットレートの値を 192kbps などの大きい値にしたり、マルチストリーム環境で配信者を複数に増やすと、この差が顕著に見受けられる。

考察

RFC4566RFC3890 を読む限り、RTP session 毎なので m=video の下に書いていれば映像にだけ影響すると思っているのだが、AS の略が Application Indicated bandwidth なので、映像・音声を含めた全体を示すのかもしれない。

また、Chrome でこのような事象が発生して、Firefox では発生していないが、Firefox ではそもそも音声ビットレート制御 (maxaveragebitrate の指定) が効かないようなので、Chrome の方が WebRTC の挙動として正しい可能性がある。

結論

映像のビットレートを指定することは出来ない。
SDP において、AS に指定する値は映像・音声ビットレートを足し合わせた値を指定し、音声ビットレートを maxaveragebitrate で指定することで、映像のビットレートを間接的に指定する方法が良さそう。

注意事項として、maxaveragebitrate は Firefox では効いていないため、Chrome と Firefox で映像ビットレートは異なるので注意 (全体のビットレートは同じはず)。

Top comments (0)