WebRTC: 従来の getStats() 移行ガイド

Henrik Boström
Henrik Boström

従来の getStats() WebRTC API は Chrome 117 で削除されるため、この API を使用しているアプリは標準 API に移行する必要があります。この記事では、コードを移行する方法と、この変更に時間が必要な場合の対処方法について説明します。

これまで、WebRTC getStats() API には 2 つのバージョンが競合していました。標準化プロセスより前から存在し、コールバック引数を受け取る以前の getStats() API と、Promise を返す標準化された広くサポートされている API。

標準 API は機能が豊富で、W3C 仕様の WebRTC の Statistics API の識別子に明確に定義された指標が公開されています。この仕様には、このガイドに記載されている各指標の説明など、多数の説明が含まれています。

Chrome 117 以降、以前の getStats() API は Stable リリース チャンネルで例外をスローします(例外のスローは段階的に展開される予定です)。標準 API に簡単に移行するには、このガイドを参考にしてください。

従来版と標準の統計情報タイプ

標準的な統計情報タイプの完全なリストについては、仕様の RTCStatsType 列挙型をご覧ください。これには、各タイプで収集された指標を記述する統計情報ディクショナリの定義が含まれます。

すべての統計情報オブジェクトには、複数の getStats() 呼び出しで基になるオブジェクトを一意に識別する id 属性があります。メソッドが呼び出されるたびに、同じオブジェクトは同じ ID を持ちます。これは、指標の変化率を計算するのに役立ちます(次のセクションで例を示します)。ID は参照の関係も形成します。たとえば、outbound-rtp 統計情報オブジェクトは、outbound-rtp.mediaSourceId 属性を介して関連する media-source 統計情報オブジェクトを参照します。すべての ...Id 関係を描画すると、グラフになります。

レガシー API には次の統計タイプがあり、標準タイプに対応しています。


以前の型

標準タイプ
ssrc
RTP ストリームと、関連する MediaStreamTrack に関する指標を表します。


標準のタイプは inbound-rtp(受信 RTP ストリームとそれに関連付けられたリモート MediaStreamTrack)、outbound-rtp(送信 RTP ストリーム)、media-source(送信 RTP ストリームに関連付けられたローカル MediaStreamTrack 指標の場合)です。RTP ストリームの指標には、RTP ストリームで使用されるエンコーダまたはデコーダに関する情報も含まれます。
VideoBwe
帯域幅推定の指標、ターゲット ビットレート、エンコーダのビットレート、実際のビットレート。このタイプの指標は、RTP 指標(outbound-rtpinbound-rtp)と ICE 候補ペアの指標(candidate-pair)の一部です。
googComponent
トランスポート(ICE と DTLS)を表します。標準バージョンは transport です。
localcandidate and remotecandidate
ICE の候補を表します。標準バージョンは local-candidateremote-candidate です。
googCandidatePair
ICE 候補ペア(ローカル候補とリモート候補のペア)を表します。標準バージョンは candidate-pair です。
googCertificate
DTLS トランスポートで使用される証明書を表します。標準バージョンは certificate です。
googLibjingleSession
RTCPeerConnection を表します。その内容は標準のどのものにもマッピングされませんが、標準には RTCPeerConnection: peer-connection に関連付けられた型があります。

以前の API にありません

以下の統計情報タイプは標準 API に追加され、対応するレガシー タイプはありません。
  • codec: RTP ストリームでエンコードまたはデコードに現在使用されているコーデック。これは、SDP でネゴシエートされたコーデックのサブセットです。
  • remote-inbound-rtp: このエンドポイントが送信しているアウトバウンド RTP ストリーム(outbound-rtp)に対応するリモート エンドポイントのインバウンド RTP ストリーム。リモート エンドポイントで測定され、RTCP Receiver Report(RR)または RTCP Extended Report(XR)で報告されます。
  • remote-outbound-rtp: このエンドポイントが受信しているインバウンド RTP ストリーム(inbound-rtp)に対応するリモート エンドポイントのアウトバウンド RTP ストリーム。リモート エンドポイントで測定され、RTCP 送信者レポート(SR)で報告されます。
  • media-playout: 受信 RTP ストリーム(inbound-rtp)に関連付けられたリモート MediaStreamTrack の再生に関する指標。
  • data-channel: RTCDataChannel を表します。

従来の指標と標準指標のマッピング

このマッピングは、どの以前の指標がどの標準指標に対応しているかを簡単に特定できるようにすることを目的としていますが、対応する指標では異なる単位が使用されていたり、瞬間値ではなく合計カウンタとして表されたりする場合があります。指標の定義については、仕様をご覧ください。
標準 API では、レートではなく合計カウンタを公開します。つまり、以前の API の場合と同様に、対応するレート(ビットレートなど)を取得するには、アプリで 2 つの getStats() 呼び出し間の差分を取って平均レートを計算する必要があります。次に例を示します。

// Periodically (e.g. every second or every 10 seconds)...
const currReport = await pc.getStats();
// Calculate bitrate since the last getStats() call.
// Handling of undefined is omitted for clarity.
const currOutboundRtp = currReport.values().find(s => s.type == 'outbound-rtp');
const prevOutboundRtp = prevReport.get(currOutboundRtp.id);
const deltaBits = (currOutboundRtp.bytesSent - prevOutboundRtp.bytesSent) * 8;
const deltaSeconds = (currOutboundRtp.timestamp - prevOutboundRtp.timestamp) / 1000;
logBitrateMeasurement(deltaBits / deltaSeconds);
// Remember the report for next time.
prevReport = currReport;

このようにレートと平均を計算しなければならないのは面倒な追加ステップのように思えるかもしれませんが、希望する時間間隔で平均を取得できるという利点があります。標準 API の呼び出し頻度を従来の API よりも少なくすると、パフォーマンス上のメリットがあります。

以前の指標
googCertificate
標準的な対応
certificate
.googFingerprint .fingerprint
.googFingerprintAlgorithm .fingerprintAlgorithm
.googDerBase64 .base64Certificate
以前の指標
googComponent
標準的な対応
transport
.localCertificateId .localCertificateId
.remoteCertificateId .remoteCertificateId
.selectedCandidatePairId .selectedCandidatePairId
.dtlsCipher .dtlsCipher
.srtpCipher .srtpCipher
以前の指標
localcandidate
標準的な対応
local-candidate または candidate-pair
.stunKeepaliveRequestsSent candidate-pair.requestsSentcandidate-pair.localCandidateId による candidate-pair の逆引き参照)
.portNumber local-candidate.port
.networkType local-candidate.networkType
.ipAddress local-candidate.address
.stunKeepaliveResponsesReceived candidate-pair.responsesReceived
.stunKeepaliveRttTotal candidate-pair.totalRoundTripTime
.transport local-candidate.protocol
.candidateType local-candidate.candidateType
.priority local-candidate.priority
以前の指標
remotecandidate
標準的な対応
remote-candidate
上記の localcandidate と同じです。 上記の local-candidate と同じです。
以前の指標
googCandidatePair
標準的な対応
candidate-pair
.responsesSent candidate-pair.responsesSent
.requestsReceived candidate-pair.requestsReceived
.googRemoteCandidateType remote-candidate.candidateType

candidate-pair.remoteCandidateIdremote-candidate を検索)
.googReadable googReadable は、candidate-pair.requestsReceived または candidate-pair.responsesReceived を最近増やしたかどうかを示すブール値です。
.googLocalAddress local-candidate.address

candidate-pair.localCandidateIdlocal-candidate を検索)
.consentRequestsSent candidate-pair.consentRequestsSent
.googTransportType local-candidate.protocolremote-candidate.protocol と同じです。
.googChannelId candidate-pair.transportId
.googLocalCandidateType local-candidate.candidateType
.googWritable googWritable は、candidate-pair.responsesReceived が最近増加したかどうかを表すブール値です。
.googRemoteAddress remote-candidate.address
.googRtt candidate-pair.currentRoundTripTime
.googActiveConnection アクティブな接続は、トランスポートによって現在選択されている候補ペアを指します。例: candidate-pair.id == transport.selectedCandidatePairId
.packetsDiscardedOnSend candidate-pair.packetsDiscardedOnSend
.bytesReceived candidate-pair.bytesReceived
.responsesReceived candidate-pair.responsesReceived
.remoteCandidateId candidate-pair.remoteCandidateId
.localCandidateId candidate-pair.localCandidateId
.bytesSent candidate-pair.bytesSent
.packetsSent candidate-pair.packetsSent
.bytesReceived candidate-pair.bytesReceived
.bytesReceived candidate-pair.bytesReceived
以前の指標
ssrc
標準的な対応
inbound-rtpoutbound-rtpmedia-source
.audioInputLevel media-source.audioLevel。以前の指標は [0..32768] の範囲ですが、標準の metrc は [0..1] の範囲にあります。
.audioOutputLevel
inbound-rtp.audioLevel。以前の指標は [0..32768] の範囲ですが、標準の metrc は [0..1] の範囲にあります。
.packetsLost inbound-rtp.packetsLost
.googTrackId ローカル MediaStreamTrack の場合は media-source.trackIdentifier、リモート MediaStreamTrack の場合は inbound-rtp.trackIdentifier
.googRtt remote-inbound-rtp.roundTripTimeoutbound-rtp.remoteId を参照)
.googEchoCancellationReturnLossEnhancement inbound-rtp.echoReturnLossEnhancement
.googCodecName コーデック名は「タイプ/サブタイプ」の MIME タイプのサブタイプ codec.mimeType です(inbound-rtp.codecIdoutbound-rtp.codecId を参照)。
.transportId inbound-rtp.transportIdoutbound-rtp.transportId
.mediaType inbound-rtp.kindoutbound-rtp.kind または media-source.kind
.googEchoCancellationReturnLoss inbound-rtp.echoReturnLoss
.totalAudioEnergy inbound-rtp.totalAudioEnergymedia-source.totalAudioEnergy
ssrc.totalSamplesDuration inbound-rtp.totalSamplesDurationmedia-source.totalSamplesDuration
.ssrc inbound-rtp.ssrcoutbound-rtp.ssrc
.googJitterReceived inbound-rtp.jitter
.packetsSent outbound-rtp.packetsSent
.bytesSent outbound-rtp.bytesSent
.googContentType inbound-rtp.contentTypeoutbound-rtp.contentType
.googFrameWidthInput media-source.width
.googFrameHeightInput media-source.height
.googFrameRateInput media-source.framesPerSecond
.googFrameWidthSent outbound-rtp.frameWidth
.googFrameHeightSent outbound-rtp.frameHeight
.googFrameRateSent
送信 FPS は outbound-rtp.framesSent の変化率ですが、実際には、FPS をエンコードする outbound-rtp.framesPerSecond として実装されます。
.googFrameWidthReceived inbound-rtp.frameWidth
.googFrameHeightReceived inbound-rtp.frameHeight
.googFrameRateDecoded
inbound-rtp.framesDecoded の変化率
.googFrameRateOutput
inbound-rtp.framesDecoded の変化率 - inbound-rtp.framesDropped
.hugeFramesSent outbound-rtp.hugeFramesSent
.qpSum

inbound-rtp.qpSumoutbound-rtp.qpSum

.framesEncoded outbound-rtp.framesEncoded
.googAvgEncodeMs

outbound-rtp.totalEncodeTime / outbound-rtp.framesEncoded

.codecImplementationName

inbound-rtp.decoderImplementationoutbound-rtp.encoderImplementation

.googCpuLimitedResolution
outbound-rtp.qualityLimitationReason == "cpu" の場合は true
.googBandwidthLimitedResolution
outbound-rtp.qualityLimitationReason == "bandwidth" の場合は true
.googAdaptationChanges
以前の指標は、qualityLimitationReason に関連する理由で解像度またはフレームレートが変更された回数をカウントしていました。これは他の指標(送信解像度やフレームレートがソース解像度やフレームレートと異なるなど)から推定できますが、解像度やフレームレートの変更頻度を再構成する頻度よりも、制限されている時間 outbound-rtp.qualityLimitationDurations の方が役に立つ可能性があります。
.googNacksReceived inbound-rtp.nackCount
.googNacksSent inbound-rtp.nackCount
.googPlisReceived inbound-rtp.pliCount
.googPlisSent inbound-rtp.pliCount
.googFirsReceived inbound-rtp.firCount
.googFirsSent inbound-rtp.firCount
.googSecondaryDecodedRate
エラー修正を含むパケットの最近の比率: inbound-rtp.fecPacketsReceived - inbound-rtp.fecPacketsDiscarded
.packetsReceived inbound-rtp.packetsReceived
.googJitterBufferMs inbound-rtp.jitterBufferDelay / inbound-rtp.jitterBufferEmittedCount
.googTargetDelayMs(動画) inbound-rtp.jitterBufferTargetDelay / inbound-rtp.jitterBufferEmittedCount
.googPreferredJitterBufferMs(音声) inbound-rtp.jitterBufferTargetDelay / inbound-rtp.jitterBufferEmittedCount
.googExpandRate
最近の隠蔽サンプルの割合: inbound-rtp.concealedSamples / inbound-rtp.totalSamplesReceived
.googSpeechExpandRate ストリーミングが無音ではなかったときの隠蔽サンプルの最近の比率: (inbound-rtp.concealedSamples - inbound-rtp.silentConcealedSamples)/ inbound-rtp.concealedSamples
.googAccelerateRate 再生速度を上げるために破棄されたサンプルの最近の比率: inbound-rtp.removedSamplesForAcceleration / inbound-rtp.totalSamplesReceived
.googPreemptiveExpandRate
プレイアウト速度を遅くするために合成されたサンプルの最近の比率: inbound-rtp.insertedSamplesForDeceleration / inbound-rtp.totalSamplesReceived
.googSecondaryDiscardedRate inbound-rtp.fecPacketsDiscarded
.bytesReceived inbound-rtp.bytesReceived
s.googCurrentDelayMs inbound-rtp.jitterBufferDelay + media-playout.totalPlayoutDelay
.googDecodeMs inbound-rtp.totalDecodeTime / inbound-rtp.framesDecoded
.googTimingFrameInfo
残りの 1 つの goog-metric。inbound-rtp.googTimingFrameInfo
.framesDecoded inbound-rtp.framesDecoded
以前の指標
VideoBwe
標準的な対応
outbound-rtpcandidate-pair
.googTargetEncBitrate
瞬間値として outbound-rtp.targetBitrate、または平均として outbound-rtp.totalEncodedBytesTarget / outbound-rtp.framesEncoded
.googActualEncBitrate エンコーダによって生成されるバイト数は、再送信を除くペイロード バイトです。変化率 outbound-rtp.bytesSent - outbound-rtp.retransmittedBytesSent
.googBucketDelay outbound-rtp.totalPacketSendDelay / outbound-rtp.packetsSent
.googTransmitBitrate RTP ごとのストリーム ビットレートは outbound-rtp.headerBytesSent + outbound-rtp.bytesSent、ICE 候補ごとのビットレートは candidate-pair.bytesSent、トランスポートごとのビットレートは transport.bytesSent の変化率
.googRetransmitBitrate outbound-rtp.retransmittedBytesSent の変化の範囲
.googAvailableSendBandwidth candidate-pair.availableOutgoingBitrate
.googAvailableReceiveBandwidth candidate-pair.availableIncomingBitrate

標準 API は同時対応モデルです。

同時配信を使用している場合、(たとえば)3 つの RTP ストリームを 3 つの異なる SSRC で送信するために従来の API が報告するのは 1 つの SSRC のみであることにお気づきかもしれません。

標準 API はこの制限を共有しておらず、SSRC ごとに 1 つずつ、3 つの outbound-rtp 統計情報オブジェクトを返します。つまり、各 RTP ストリームを個別に分析できますが、すべての RTP 送信ストリームの合計ビットレートを取得するには、自分で集計する必要があります。

一方、scalabilityMode API を介して構成された複数の空間レイヤを含む SVC ストリームまたは RTP ストリームは、単一の SSRC を介して送信されるため、引き続き単一の outbound-rtp として表示されます。

移行に時間が必要な場合

Chrome 117 で以前の API が削除された場合、それを使用すると例外が生成されます。コードを期限内に移行できない場合、RTCPeerConnection コールバック ベースの getStats() API のオリジン トライアルを利用すると、登録済みのウェブサイトの移行期間を延長できます。オリジン トライアル トークンについては、Chrome 121 まで以前の getStats() API を引き続き使用できます。