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 仕様の Identifiers for WebRTC's 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 に追加されていますが、対応する以前のタイプはありません。
<ph type="x-smartling-placeholder">
    </ph>
  • codec: RTP ストリームでエンコードまたはデコードに現在使用されているコーデック。これは、SDP でネゴシエートされたコーデックのサブセットです。
  • remote-inbound-rtp: このエンドポイントが送信するアウトバウンド RTP ストリームに対応するリモート エンドポイントの受信 RTP ストリーム(outbound-rtp)。リモート・エンドポイントで測定され、RTCP Receiver Report(RR)または RTCP Extended Report(XR)で報告されます。
  • remote-outbound-rtp: このエンドポイントが受信している受信 RTP ストリームに対応するリモート エンドポイントの送信 RTP ストリーム(inbound-rtp)。リモート・エンドポイントで測定され、RTCP Sender Report(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.protocol および remote-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.mimeTypeinbound-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.totalAudioEnergy および media-source.totalAudioEnergy
ssrc.totalSamplesDuration inbound-rtp.totalSamplesDuration および media-source.totalSamplesDuration
.ssrc inbound-rtp.ssrc および outbound-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.decoderImplementation および outbound-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
残りの goog-metric は 1 つだけです。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 は同時キャスト対応

サイマルキャストを使用している場合、以前の API では、サイマルキャストを使用して(たとえば 3 つの別々の SSRC に)3 つの RTP ストリームを送信している場合でも、1 つの SSRC しか報告されないことにお気づきかもしれません。

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

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

移行に時間が必要な場合

Chrome 117 で以前の API が削除されると、この API を使用すると例外が発生します。コードを時間内に移行できない場合は、RTCPeerConnection コールバック ベースの getStats() API のオリジン トライアルを利用して、登録されているウェブサイトを移行する時間を確保してください。オリジン トライアル トークンを使用する場合、Chrome 121 までは以前の getStats() API を引き続き使用できます。