従来の 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-rtp と inbound-rtp )と ICE 候補ペア指標(candidate-pair )の一部です。 |
googComponent
|
トランスポート(ICE と DTLS)を表します。標準バージョンは transport です。 |
localcandidate and remotecandidate
|
ICE 候補を表します。標準バージョンは local-candidate と remote-candidate です。 |
googCandidatePair
|
ローカル候補とリモート候補のペアである ICE 候補ペアを表します。標準バージョンは candidate-pair です。 |
googCertificate
|
DTLS トランスポートで使用される証明書を表します。標準バージョンは certificate です。 |
googLibjingleSession
|
RTCPeerConnection を表します。内容は標準のどの項目にもマッピングされていませんが、標準には RTCPeerConnection に関連付けられた型(peer-connection )があります。 |
従来の API にはありません |
以下の統計情報の種類は、対応する以前のタイプがない標準 API に追加されました。
|
従来指標と標準指標のマッピング
このマッピングは、どのレガシー指標がどの標準指標に対応しているかをデベロッパーが把握できるようにすることを目的としています。ただし、対応する指標で異なる単位が使用されている場合や、瞬間値ではなく合計カウンタとして表されている場合があります。指標の定義については、仕様をご覧ください。
標準 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.requestsSent (candidate-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.remoteCandidateId を介して remote-candidate を検索) |
.googReadable
|
googReadable は、最近 candidate-pair.requestsReceived または candidate-pair.responsesReceived がインクリメントされたかどうかを示すブール値です。 |
.googLocalAddress
|
local-candidate.address ( candidate-pair.localCandidateId を介して local-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-rtp 、outbound-rtp 、media-source |
---|---|
.audioInputLevel
|
media-source.audioLevel 。従来の指標の範囲は [0..32768] ですが、標準指標の範囲は [0..1] です。 |
.audioOutputLevel
|
inbound-rtp.audioLevel 。従来の指標の範囲は [0..32768] ですが、標準指標の範囲は [0..1] です。 |
.packetsLost
|
inbound-rtp.packetsLost
|
.googTrackId
|
ローカル MediaStreamTrack の場合は media-source.trackIdentifier 、リモート MediaStreamTrack の場合は inbound-rtp.trackIdentifier |
.googRtt
|
remote-inbound-rtp.roundTripTime (outbound-rtp.remoteId を参照) |
.googEchoCancellationReturnLossEnhancement
|
inbound-rtp.echoReturnLossEnhancement
|
.googCodecName
|
コーデック名は、「type/subtype」MIME タイプ codec.mimeType のサブタイプです(inbound-rtp.codecId と outbound-rtp.codecId を参照)。 |
.transportId
|
inbound-rtp.transportId 、outbound-rtp.transportId |
.mediaType
|
inbound-rtp.kind と outbound-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.contentType 、outbound-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
|
|
.framesEncoded
|
outbound-rtp.framesEncoded
|
.googAvgEncodeMs
|
|
.codecImplementationName
|
|
.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。 inbound-rtp.googTimingFrameInfo |
.framesDecoded
|
inbound-rtp.framesDecoded
|
従来の指標
VideoBwe |
標準の対応outbound-rtp と candidate-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 つの個別の SSRC を介して 3 つの RTP ストリームを送信している場合でも、以前の API では 1 つの SSRC しか報告されないことに気づいたかもしれません。
標準 API にはこの制限はなく、SSRC ごとに 1 つずつ、3 つの outbound-rtp
統計情報オブジェクトが返されます。つまり、各 RTP ストリームを個別に分析できますが、すべての RTP 送信ストリームの合計ビットレートを取得するには、それらを自分で集計する必要があります。
一方、scalabilityMode
API で複数の空間レイヤが構成された SVC ストリームまたは RTP ストリームは、単一の SSRC 経由で送信されるため、引き続き単一の outbound-rtp
として表示されます。
移行にさらに時間が必要な場合
Chrome 117 で以前の API が削除されると、その API を使用すると例外が発生します。コードを期限までに移行できない場合は、RTCPeerConnection コールバック ベースの getStats() API のオリジン トライアルを利用すると、登録済みのウェブサイトは移行期間を延長できます。オリジン トライアル トークンを使用すると、従来の getStats() API は Chrome 121 まで引き続き使用できます。