📊

WebRTCのstatsについて入門した

2022/05/22に公開

WebRTC とは

Web Real-Time-Communication の略称で、HTML5 から策定された API 規格であり、プロトコルでもある。
WebRTC プロトコルは、2 つの WebRTC エージェントが双方向の安全なリアルタイム通信をネゴシエートするための一連のルールである。WebRTC API は、開発者が WebRTC プロトコルを使うためのもので、JavaScript のみで規定されている。
HTTP と fetch API の関係に似ていて、プロトコルとしての WebRTC が HTTP で、API としての WebRTC が fetch API のようなもの。

WebRTC は、リアルタイムにビデオ/オーディオ/データのやり取りを実現し、プラグインなしでボイスチャットやビデオチャットをブラウザ上で実現可能。

通信方法には P2P、MCU、SFU がある。
P2P 通信はコンピューター間で直接通信を行うアーキテクチャで、複数人がつながると端末の通信量と負荷がかかる。
一方、MCU や SFU ではサーバーを経由する。MCU はサーバーでデータを加工して他のクライアントに送るが、SFU はサーバーでデータを加工せずそのまま他のクライアントに送る。

WebRTC の P2P 通信の流れ

1. シグナリング

  • SDP(Session Description Protocol)を通信することで通信の種類を決まる
    • SDP: 通信セッションを記述するプロトコル。通信に必要な各ブラウザの情報(セッションの属性、メディアの形式、IP アドレス、ポート番号、通信帯域など)を記述する
  • 片方の PC が他方 PC に対し SDP を Offer し、それに対して Answer SDP を返すという Offer/Answer モデルで通信する

シグナリングの流れ

  1. 接続を開始する PC A で SDP を作成し、自身の SDP に登録する
  2. 登録後、シグナリングサーバを通じて PC B に SDP を送信する
  3. PC B は受け取り後、PC A の SDP を登録する
  4. PC B で SDP を作成し、自身の SDP に登録する
  5. 登録後、シグナリングサーバを通じて PC A に SDP を送る
  6. PC A は受け取り後、PC B の SDP を登録する

2. 接続

  • STUN/TURN サーバーを使って ICE(Interactive Connectivity Establishment)を通信することで通信経路が決まる
    • ICE: 相手ブラウザに到達する可能性のある通信経路の情報。
    • STUN サーバー: NAT 配下にある場合、自分のグローバル IP/Port を教えるためのサーバー
    • TURN サーバ: Firewall など P2P 通信が出来ない場合に使うデータを中継して送信するためのサーバー

接続の流れ

  1. NAT 配下にある場合、STUN サーバを通じて PC A 自身のグローバル IP/Port を取得する
  2. これまでの情報をもとに ICE を生成し、シグナリングサーバーを通じて ICE を PC B に送る
  3. PC B は受け取った PC A の ICE を登録する
  4. STUN サーバを通じて PC B 自身のグローバル IP/Port を取得する
  5. これまでの情報をもとに ICE を生成し、シグナリングサーバーを通じて ICE を PC A に送る
  6. PC A は受け取った PC B の ICE を登録する

上記によりP2Pで通信するための情報が揃い、通信が開始できる状態となった

  • P2P 通信が確立できた場合、シグナリングサーバー経由でデータをやり取りする
  • Firewall など P2P 通信が出来ない場合、TURN サーバがデータを中継してやり取りする

3. セキュリティの確保

  • DTLS (Datagram Transport Layer Security)と SRTP (Secure Real-time Transport Protocol)によるトランスポート層のセキュリティ確保することで双方向の安全な通信が確立する
    • DTLS: TLS の特徴を UDP 上で利用できるようにしたプロトコル (HTTPS などのセキュアな Web 通信をライブストリーミングなどのリアルタイムアプリケーションで使われる UDP で利用できる)
      • UDPである理由はNATトラバーサルに必要だから。NATトラバーサルがなければP2P接続の確立をすることはできない
    • SRTP: WebRTC で利用されている音声や映像の暗号化に使うプロトコル
  • WebRTC は ICE で確立された接続の上で DTLS ハンドシェイクを行って接続する
    • WebRTC は証明書に中央機関を使用しないため、DTLS を通じて交換された証明書が、シグナリングによって共有されたフィンガープリントと一致することを表明する
  • WebRTC は、RTP というオーディオ/ビデオ伝送用の別のプロトコルを使用するが、RTP パケットのセキュリティには SRTP を使用する

4. 通信

  • RTP および SCTP によるピアとの通信
    • RTP: SRTP で暗号化されたメディアのやり取りに使う。音声と映像をリアルタイムでやりとりに使われる
    • SCTP: DTLS で暗号化されたメッセージの送受信に使う。任意のデータ(テキスト、ファイルなど)の転送などに使われる

WebRTC stats とは

WebRTCアプリケーションのパフォーマンスと品質を監視および分析するための統計情報を提供するAPI。
開発者はリアルタイムの音声、ビデオ、データ通信の品質を評価し、問題を特定してトラブルシューティングに役立てる。
最新の仕様は https://www.w3.org/TR/webrtc-stats/ を確認する。

WebRTC stats を確認してみる

Chrome 内部ツール chrome://webrtc-internals/ で簡単に WebRTC stats を確認できる。

  1. chrome://webrtc-internals/ にアクセスし GoogleMeet などビデオ通話を開始する
  2. タブの中から会議に参加したタイミングで作成されたタブを選択する
    1. GoogleMeetだとタブが https://meet.google.com/ で始まる

WebRTC のサンプルアプリが https://github.com/webrtc/samples にたくさんあり、参考になる。
その中に stats に関するサンプルアプリもあり、Chrome 内部ツールを使わずに簡単に確認できる。
WebRTC で実装した内容が動かない時の原因の切り分けにサンプルアプリを動かすのもお勧め。

WebRTC stats で確認する値

まず用語として出てくる Transport、MediaStream、Trackの関係を押さえておく

  • Transport、MediaStream、Trackの関係
    • Track: WebRTC におけるメディアの最小の単位
    • Stream: アプリケーションは Track を束ねた Stream の単位で扱う
    • Transport: WebRTC のデータを送受信するための通信経路を管理

RTCStatsType の type のなかで基本的なものを紹介する

主な type

  • type: candidate-pair
    • RTCIceCandidatePairStats
    • 2 つの WebRTC エンドポイント間の実行可能な接続を構成する ICE 候補のペア
    • Chrome 内部ツールでは太字が現在使われている有効な Transport/輸送路
      • 太字以外は通信で使われていないためbytesSentが 0 になっていたりする
  • type: outbound-rtp
    • 送信の RTP Stream に関する統計情報
    • kind: audio/video でどの Track か判断できる。以降の inbound-rtp なども同様
  • type: inbound-rtp
    • 受信の RTP Stream に関する統計情報
  • type: remote-outbound-rtp
    • ローカル側から見た相手側の送信 RTP Stream の統計情報
    • つまり、ローカルから見ると受信に影響する値となる
  • type: remote-inbound-rtp
    • ローカル側から見た相手側の受信 RTP Stream の統計情報
    • つまり、ローカルから見ると送信に影響する値となる

確認する値の例

音声関連

  • audioLevel (type: media-source, kind: audio)
    • オーディオトラックの音量レベルの確認
    • 範囲が 0.0 (無音) から 1.0 (最大音量) である
    • 0であれば音が出ていないことがわかる

映像関連

  • frameWidth (type: inbound-rtp/outbound-rtp, kind: video)
  • frameHeight (type: inbound-rtp/outbound-rtp, kind: video)
    • ビデオフレームの幅・高さの確認
    • 値が定期的に変わっていれば映像の解像度が揺らいでいたことがわかる

ネットワーク関連

  • bytesSent (type: outbound-rtp, kind: video/audio)
  • availableOutgoingBitrate (type: candidate-pair)
    • 送信ビットレートと利用可能な送信ビットレート
    • 想定より低い場合、映像や音声の品質の低下が生じる可能性がある
  • bytesReceived (type: inbound-rtp, kind: video/audio)
  • availableIncomingBitrate (type: candidate-pair)
    • 受信ビットレートと利用可能な受信ビットレート
    • 想定より低い場合、映像や音声の品質の低下が生じる可能性がある
      • Note: availableIncomingBitrate は、現在はブラウザ互換性データがなく取得できるブラウザが不明(Chromeで確認できたりできなかったりする)
        • GitHub Issueでも互換性データがないことが言及されている
        • 2023年1月時点ではSafariのみで取得可能だった
  • packetsLost (type: inbound-rtp, kind: video/audio)
    • パケットロス数
    • 値が高い場合、ネットワーク輻輳が発生し映像や音声の品質が低下している可能性がある
  • nackCount (type: outbound-rtp/inbound-rtp, kind: video/audio)
    • 特定のパケットが失われ、再送要求したリクエストの回数
    • 値が高い場合、ネットワークの問題やパケットロスが原因で映像や音声の品質が低下している可能性がある
  • firCount (type: outbound-rtp, kind: video)
    • 完全なフレームを再送するよう要求した回数
    • 値が高い場合、ネットワークの問題や送信側の端末スペックやエンコードの問題が原因で映像品質が低下している可能性がある
  • pliCount (type: outbound-rtp/inbound-rtp, kind: video)
    • 特定のフレームの一部が失われたことを通知したリクエストの回数
    • 値が高い場合、ネットワークの問題や送信側の端末スペックやエンコードの問題が原因で映像品質が低下している可能性がある
  • jitter (type: inbound-rtp, kind: video/audio)
    • パケット間の遅延変動
    • 値が高い場合、パケット到着時間の変動が原因で音声や映像が途切れたり遅延が発生する可能性がある
  • currentRoundTripTime (type: candidate-pair)
    • ラウンドトリップタイム(RTT)応答が返ってくるまでの経過時間
    • 値が大きい場合、ネットワークの遅延が大きく通信の応答時間が遅くなる

参考

Discussion