クライアントの観測可能性:ウェブ

Vonage Video SDKは、ほとんどのユースケースで推奨される高レベルの統計APIを通じて、詳細なストリーム品質メトリクスを公開します。このAPIは、音声、ビデオ、ネットワーク、および送信者側の統計を、ピア接続の遷移をまたいで安定したまま、統一されたセッション認識形式で提供します。高度なデバッグのために、SDKは未処理のピア接続データを反映する生のWebRTC統計レポートへのアクセスも提供します。

音声・ビデオ統計API

Vonage Video Web SDKは、パブリッシャーとサブスクライバーの両方に対して、オーディオとビデオのネットワーク統計を定期的に送信します。これらには、パケット数、ビットレート、フレームレートデータ、一時停止/フリーズメトリクス、コーデック情報、およびオプションの送信側ネットワーク推定が含まれます。

出版社の統計を取る

について Publisher.getStats() メソッドは オブジェクトの配列を提供します。 ルーティングされたセッション( オープントーク メディア・ルーター)、この配列には1つのオブジェクトが含まれ、Vonage Video Media Routerに送信される単一のオーディオ・ビデオ・ストリームの統計情報を定義します。 この配列には、Vonage Video Media Router に送信される単一のオーディオ・ビデオ・ストリームの統計情報を定義する 1 つのオブジェクトが含まれます。中継セッションの場合、 には、公開ストリームの加入者ごとのオブジェクトが含まれます。

以下のコードでは、パブリッシャーのストリームのメトリクスを毎秒ログしています:

window.setInterval(() => {
  publisher.getStats((error, statsArray) => {
    if (error) {
      console.error(error);
      return;
    }

    statsArray.forEach(statsContainer => {
      const stats = statsContainer.stats;
      const connectionId = stats.connectionId || 'routed';

      console.log(`\nStats for ${connectionId}`);
      if (stats.video) {
        const video = stats.video;

        if (video.layers && video.layers.length > 0) {
          console.log(`Video layers: ${video.layers.length}`);

          video.layers.forEach((layer, index) => {
            console.log(` Layer ${index}: ${layer.width}x${layer.height}`);
            console.log(`   encodedFrameRate: ${layer.encodedFrameRate} fps`);
            console.log(`   bitrate: ${layer.bitrate} bps`);
            console.log(`   totalBitrate: ${layer.totalBitrate} bps`);
            console.log(`   codec: ${layer.codec}`);
            console.log(`   scalabilityMode: ${layer.scalabilityMode}`);
            if (layer.qualityLimitationReason) {
              console.log(`   qualityLimitationReason: ${layer.qualityLimitationReason}`);
            }
          });
        }

        if (stats.transportStats) {
          console.log(
            'transport estimated bandwidth:',
            stats.transportStats.connectionEstimatedBandwidth,
            'bps'
          );
        }
      }
    });
  });
}, 1000);

パブリッシャーでのビデオ品質イベントの受信

との統計ポーリングに加え Publisher.getStats()を購読することで、パブリッシャーがビデオの品質に意味のある変化を検出したときに、リアルタイムで通知を聞くことができます。 videoQualityChanged イベントを開催する:

publisher.on('videoQualityChanged', ({ reason, statsContainer }) => {
  console.log('Video quality change reason:', reason);

  const { stats } = statsContainer;

  if (stats.video && stats.video.layers) {
    stats.video.layers.forEach((layer) => {
      console.log(
        `Resolution: ${layer.width}x${layer.height}, FPS: ${layer.frameRate}`
      );
    });
  }
});

購読者の統計情報の取得

について getStats() メソッドは、サブスクライバのストリームに関する情報を提供します。 サブスクライバのストリームに関する情報を提供します。

以下のコードは、加入者のストリームについて、1秒ごとにいくつかのメトリクスを記録する:

window.setInterval(() => {
  subscriber.getStats((error, stats) => {
    if (error) {
      console.error('Error getting subscriber stats: ', error.message);
      return;
    }

    const video = stats.video;

    if (video) {
      console.log('video bitrate:', video.bitrate, 'bps');
      console.log('video totalBitrate:', video.totalBitrate, 'bps');
      console.log('decoded frame rate:', video.decodedFrameRate, 'fps');
      console.log('codec:', video.codec);
      console.log('res:', `${video.width}x${video.height}`);

      console.log('freezeCount:', video.freezeCount);
      console.log('totalFreezesDuration:', video.totalFreezesDuration, 'ms');
      console.log('pauseCount:', video.pauseCount);
      console.log('totalPausesDuration:', video.totalPausesDuration, 'ms');
    }
  });
}, 1000);

加入者のビデオ品質イベントの受信

を聴くことができる。 videoQualityChanged イベントで、ビデオ画質の著しい中断や変化が検出されたときに通知されます。

subscriber.on('videoQualityChanged', ({ reason, stats }) => {
  if (reason === 'videoInterruption') {
    console.warn('Video playback was interrupted');

    if (stats.video.freezeCount > 0) {
      console.log(`Freeze count: ${stats.video.freezeCount}`);
    }

    if (stats.video.pauseCount > 0) {
      console.log(`Pause count: ${stats.video.pauseCount}`);
    }
  }
});

既知の問題

品質制限のトリガーとなる実際の値や条件は実装に固有であり、ブラウザやプラットフォームによって異なる場合があります。例えば

  • 画面共有のビデオストリームは videoQualityChanged イベントを開催する。
  • Firefoxは以下をサポートしていません。 qualityLimitationReasonそのため、このプロパティはパブリッシャーの統計には存在しない。また videoQualityChanged 理由のある出来事 bandwidth, cpu そして other はこのブラウザではサポートされていません。
  • ハードウェアアクセラレーションによるビデオエンコーディングと専用ビデオエンコーダーが、macOSのトリガーを防ぐ cpu 制限がある。

統計データ構造

このセクションでは、Video API が提供する構造体とプロパティの概要を説明します。すべての Video SDK プラットフォームが同じ統計情報セットを公開していますが、各プラットフォームで個々のフィールドの構造や名前の付け方に若干の違いがある場合があります。これらの違いは、基本的なメトリクスの違いではなく、プラットフォーム固有の SDK 設計規約を反映しています。

出版社統計 (stats)

出版社に関する統計情報を提供します。

  • connectionId - のidプロパティと一致する、クライアント接続の一意なID。 connection プロパティの connectionCreated セッションオブジェクトがリモートクライアントにディスパッチしたイベント(リレーされたセッションでのみ使用可能)。
  • subscriberId - のidプロパティと一致する、購読者の一意なID。 Subscriber オブジェクトをサブスクライブしているクライアントのアプリで使用することができます(リレーセッションでのみ使用可能)。

出版社オーディオ統計 (stats.audio)

パブリッシャーのオーディオトラックに関する統計を提供します。

  • bytesSent - 送信されたオーディオ・バイトの合計。
  • packetsLost - 加入者またはメディア・ルーターに到達しなかったオーディオ・パケットの合計。
  • packetsSent - 送信されたオーディオパケットの合計。
  • timestamp - 統計情報が収集されたUnixタイムスタンプ(ms)。

出版社ビデオ統計 (stats.video)

これらのフィールドは、パブリッシャーの現在のビデオパフォーマンスを表しています:

  • bytesSent - 送信されたビデオ・バイトの合計。
  • packetsLost - 加入者またはメディアルーターに到達しなかったビデオパケットの合計。
  • packetsSent - 送信されたビデオパケットの合計。
  • layers - アクティブなビデオエンコーディングレイヤーを高解像度から低解像度の順に並べたリスト。

パブリッシャービデオレイヤー統計 (stats.video.layers)

1つのサイマルキャスト・レイヤーまたはSVCレイヤーを表す。

  • width - エンコードされた幅(ピクセル)。
  • height - エンコードされた高さをピクセルで表す。
  • encodedFrameRate- このレイヤーの実際のエンコードフレームレート。
  • bitrate - ペイロードのビットレート(bps)。
  • totalBitrate - RTPヘッダーとパディングを含むビットレート(bps)。
  • scalabilityMode- スケーラビリティ設定(例:SVCの場合は「L1T3」、サイマルキャストの場合は「L3T3」)。
  • codec - このレイヤーに使用されるコーデック。
  • qualityLimitationReason - エンコーダーが品質を調整した理由 (「帯域幅」、「CPU」、「その他」)。

出版社輸送統計 (stats.transport)

transportStatsオブジェクトは、個々のトラックやレイヤーではなく、オーディオビデオトランスポート全体に適用されるピアコネクションレベルのネットワーク推定メトリクスを提供する。

  • connectionEstimatedBandwidth - 接続で利用可能なアップリンク帯域幅の推定値(bps)。

加入者オーディオ統計 (stats.audio)

加入者のオーディオトラックに関する統計情報を提供します。

  • bytesReceived - 受信したオーディオ・バイトの合計。
  • packetsLost - 加入者に届かなかったオーディオパケットの合計。
  • packetsReceived - 正常に受信されたオーディオ・パケットの合計。
  • timestamp - これらの統計情報が収集されたUnixタイムスタンプ(ms)。

加入者ビデオ統計 (stats.video)

これらのフィールドは、加入者のリアルタイムのビデオ受信およびデコード性能を示す:

  • bytesReceived - 受信したビデオ・バイトの合計。
  • packetsLost - 加入者に届かなかったビデオパケットの合計。
  • packetsReceived - 受信したビデオパケットの合計。
  • timestamp - 統計情報が収集されたUnixタイムスタンプ(ms)。
  • decodedFrameRate - デコーダーが生成する実際のフレームレート(fps)。
  • bitrate - ペイロードのビットレート(ビット/秒)。
  • totalBitrate - RTPヘッダーとパディングを含むビットレート(bps)。
  • codec - この加入者に使用されているコーデック。
  • pauseCount - 5秒以上フレームがレンダリングされなかったポーズの数。
  • totalPausesDuration - 全休止の累積時間(ms)。
  • freezeCount - 短いフリーズの数(WebRTC統計の定義より)。
  • totalFreezesDuration - すべてのフリーズの累積時間(ms)。

加入者送信側推定(stats.senderStats)

これらのメトリクスは、送信者の送信接続について報告される帯域幅の推定値を提供する:

  • connectionMaxAllocatedBitrate - 送信側に割り当てられた最大ビットレート(bps)。
  • connectionEstimatedBandwidth - 送信側の現在の推定アップリンク帯域幅(bps)。

通話品質モニタリング

コア統計APIに加え、OpenTok.jsは通話品質の変化を監視し、対応するための追加機能を提供します。これらの機能は、アプリケーションがデバイスの制約やネットワーク状況に適応してパフォーマンスを最適化するのに役立ちます。

CPUパフォーマンス監視

アプリケーションは、プラットフォームの異なる様々なモバイルデバイスやデスクトップデバイス上で実行される可能性がある。さらに、デバイスのハードウェア仕様は均一ではない。例えば、あるモバイル・デバイスは多くのデスクトップ・デバイスよりもCPU性能が優れているかもしれないし、その逆かもしれない。

CPU、GPU、RAM、ハードウェア・エンコーダ/デコーダなど、多数のハードウェア構成が可能なため、チューニングが必要になる場合があります。性能の低いデバイスは、CPUに負荷のかかる機能を無効にするように設定でき、性能の高いデバイスは、より没入感のある体験をデフォルトにすることができます。

CPUパフォーマンスの変化の検出

セッションをモニターすることで、デバイスのCPU負荷の変化を検出することができます。 cpuPerformanceChanged イベントを含む。このイベントには cpuPerformanceState プロパティに設定される:

  • 'nominal' - この装置は追加の仕事を引き受けることができる。
  • 'fair' - さらに、ファンを搭載したデバイスの場合、ファンが作動し、音が聞こえるようになることがある。
  • 'serious' - デバイスはストレスを受けているため、リソース(CPUなど)のスロットルが発生する可能性がある。
  • 'critical' - デバイスには非常に大きなストレスがかかっており、これを軽減しないと問題が発生する可能性がある。

詳しくは このW3C仕様.

CPUパフォーマンスの変化に基づくアプリケーションの最適化

このイベントに応答して、アプリケーションはユーザーにリソースの消費を通知したり などの計算量の多いプロセスを無効にすることができる。 ビデオトランス. セッションを見る cpuPerformanceChanged.

以下のコードは、CPUが 'critical' パフォーマンス状態と に戻ったら、再び有効にします。 'fair' またはそれ以上:

let isVideoDisabledByCPU = false;

session.on('cpuPerformanceChanged', (event) => {
  if (event.cpuPerformanceState === 'critical') {
    // The application should alert the user why their video is being disabled
    publisher.publishVideo(false);
    isVideoDisabledByCPU = true;
  } else if (event.cpuPerformanceState === 'nominal' || event.cpuPerformanceState === 'fair') {
    if (isVideoDisabledByCPU) {
      publisher.publishVideo(true);
      isVideoDisabledByCPU = false;
    }
  }
})

平均意見スコア(MOS)

ユーザーがサービスから感じる経験の質は、以下の方法で評価することができる。 平均意見スコア (MOS)。

格付けシステム

MOSは正の数で表される。スコアは1(最も品質が悪い)から5(最も品質が良い)の間である:

  • 5(Excellent) - ユーザーが体験できる最高の品質に対する仮想的な上限。
  • 4 (Good) - より達成可能な評価。Vonageユーザーはこのレベルの品質を期待できます。
  • 3 (Fair) - 品質は問題ない。
  • 2 (Poor) - 品質が受け入れがたい。
  • 1(悪い) - 品質は最悪。

アルゴリズム

MOSレーティングは、ユーザーエクスペリエンスに影響を与える(そして低下させうる)いくつかの要素を考慮に入れています。これらの要因には以下のものが含まれます(ただし、これらに限定されるものではありません):

  • パケットロス - パケットロスがメディアの品質を劣化させる
  • ビットレート - ビットレートが高いほど、メディアの忠実度は高くなる。
  • ネットワーク遅延 - 到着が遅すぎるパケットはドロップされる可能性があり、音声の欠落や映像の乱れにつながります。

通話品質の変化に基づくアプリケーションの最適化

サブスクライバーを使う クオリティスコア変更 イベントで、オーディオとビデオの品質の変化を監視する。しかし、メディア品質の変化を監視するだけでは不十分です。通話アプリケーションのリアルタイムの性質を考えると、最高のユーザー体験を継続的に提供するためにアプリケーションをチューニングすることによって、観察された変化に対応することも必要です。

単純なヒューリスティックを以下に示す。アプリケーションはリソース制約に基づいて動的に最適化される。

// We want to know if the CPU is overloaded. If it is, then we
// can disable certain features so that the best call possible
// can still take place.
let isCpuOverloaded = false;

session.on('cpuPerformanceChanged', (event) => {
  isCpuOverloaded = event.cpuPerformanceState === 'critical';
});

// We monitor for changes in call quality. This allows us to
// tune our application, taking into account multiple factors
// (inlined below)
subscriber.on('qualityScoreChanged', (event) => {
  const { qualityScore } = event;
  const isVideoQualityBad = qualityScore.video < 2;

  if (!isVideoQualityBad && !isCpuOverloaded) {
    // Subscribe to the highest quality video since the CPU isn't taxed
    // and the quality received is good
    subscriber.setPreferredResolution('1280x720');
    subscriber.setPreferredFrameRate(30);
  }
  else if (isVideoQualityBad && !isCpuOverloaded) {
    // Even though the CPU isn't taxed, the video quality received is
    // bad. This might be due to (hopefully) intermittent network issues, so
    // we subscribe to lower quality video.
    subscriber.setPreferredResolution('320x180');
    subscriber.setPreferredFrameRate(7);
  }
  else if (isVideoQualityBad && isCpuOverloaded) {
    // The video quality received is bad and the CPU not being overloaded.
    // Let's disable video for now.
    // We can enable video once conditions improve. See statement below.
    subscriber.subscribeToVideo(false);
  }
  else {
    // Enable video
    subscriber.subscribeToVideo(true);
  }
});

通話前テストにおける通話品質の推定

Vonageビデオ ウェブ用ネットワーク・テスト・ライブラリ を使用して、クライアントがオーディオとビデオの公開をサポートしているかどうかを確認し、クライアントの公開ストリームのオーディオとビデオの推定MOSスコアを報告します。このライブラリは Publisher.getRtcStatsReport() そして Subscriber.subscriber.getStats() の方法でMOSスコアを算出する。

送信側統計

参照 送信側統計の概要.

送信側統計の有効化

送信者側の統計情報は、購読者が受け取る。送信者側の統計情報を受け取るには、ストリームのパブリッシャーに publishSenderStats プロパティを true での OT.initPublisher コール:

const publisher = OT.initPublisher({
  publishSenderStats: true
});

もし publishSenderStats が有効でない場合、このパブリッシャーに対して送信者統計チャンネルは発行されません。デフォルト値は false.

送信側統計の購読

購読者が送信者統計を自動的に受け取るのは、パブリッシャーがそれを有効にしていて、ユーザーが Subscriber.getStats() を少なくとも一度は呼び出す。ネットワーク遅延のため、最初の getStats には送信者統計が含まれていない場合がある。その後の呼び出しでは、このデータが返される可能性が高くなる。

追加のイベントやメソッドは必要なく、送信者統計は既存の stats オブジェクトを返します。 getStats().

統計イベントの受信

送信側の統計は、オプションとして含まれる。 senderStats オブジェクトを stats オブジェクトに渡される。 Subscriber.getStats() コールバック。コールバックは senderStats オブジェクトには2つのプロパティがあります:

  • connectionMaxAllocatedBitrate - 接続時に推定される最大ビットレート(単位:ビット/秒)

  • connectionEstimatedBandwidth - 現在の推定接続帯域幅(単位:ビット/秒)

これらの2つのメトリクスは、オーディオ・ビデオ・バンドルごとに計算されるため、ビデオとオーディオの両方の統計に同じ値が表示されます。個々のトラックではなくトランスポートを反映するため、メトリクスはオーディオとビデオの両方で共有されます。

subscriber.getStats((stats) => {
  if (stats.senderStats) {
    console.log(`Connection max allocated bitrate: ${stats.senderStats.connectionMaxAllocatedBitrate} bps`);
    console.log(`Connection current estimated bandwidth: ${stats.senderStats.connectionEstimatedBandwidth} bps`);
  } else {
    console.log("Sender stats not available yet.");
  }
});

既知の問題

セッションがリレーされている場合、または参加者が2人だけの特定のルーティング・セットアップで、パブリッシャーがFirefoxを使用している場合、ブラウザの制限により送信側の統計が利用できないことがあります。

RTC統計レポート

パブリッシャーの低レベルのピア接続統計を取得するには Publisher.getRtcStatsReport() メソッドを呼び出す。このメソッドはプロミスを返す。 RtcStatsReport オブジェクトを返します:

publisher.getRtcStatsReport()
  .then((stats) => stats.forEach(console.log))
  .catch(console.log);

サブスクライバの低レベルのピア接続統計を取得するには Subscriber.getRtcStatsReport() メソッドを呼び出す。このメソッドはプロミスを返す。 RtcStatsReport オブジェクトを返します:

subscriber.getRtcStatsReport()
  .then((stats) => stats.forEach(console.log))
  .catch(console.log);