WebRTC:舊版 getStats() 遷移指南

Henrik Boström
Henrik Boström

舊版 getStats() WebRTC API 將在 Chrome 117 版中移除,因此使用這組 API 的應用程式需遷移至標準 API。本文將說明如何遷移程式碼,以及需要更多時間變更這項設定時應採取的行動。

在過去,WebRTC getStats() API 有兩個競爭版本。舊版 getStats() API 會預先處理標準化程序並使用回呼引數,以及傳回承諾且廣泛支援的 API。

標準 API 提供更豐富的功能,且已在 W3C 規格 WebRTC 的 Statistics API 的 ID 中公開定義明確指標。規格包括本指南中列出的各項指標說明,以及其他其他資訊。

自 Chrome 117 起,舊版 getStats() API 會在穩定版中擲回例外狀況 (系統將逐步推出擲回例外狀況)。請按照這份指南操作,輕鬆轉換至標準 API。

舊版與標準的統計資料類型

如需標準統計資料類型的完整清單,請查看規格中的 RTCStatsType 列舉。其中包括哪些統計資料字典定義,用來說明針對每種類型所收集的指標。

所有統計資料物件都具有 ID 屬性,可在多個 getStats() 呼叫中識別其基礎物件。每次呼叫方法時,相同的物件都會有相同的 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 串流,與這個端點傳送的輸出 RTP 串流對應 (outbound-rtp)。系統會在遠端端點測量,並回報在 RTCP 接收者報告 (RR) 或 RTCP 延伸報告 (XR) 中。
  • remote-outbound-rtp:遠端端點的傳出 RTP 串流,與這個端點所接收的傳入 RTP 串流對應 (inbound-rtp)。系統會在遠端端點測量,並回報在 RTCP 傳送者報告 (SR) 中。
  • media-playout:與傳入 RTP 串流 (inbound-rtp) 相關聯的遠端 MediaStreamTrack 播放指標。
  • data-channel:代表 RTCDataChannel

從舊版指標對應

這份對應旨在協助開發人員找出與哪個標準指標對應的舊版指標,但請注意,對應指標可能會使用不同的單位或以總計數器表示,而非即時值。請參閱指標定義的規格。
標準 API 偏好顯示計數器總數,而非顯示費率。也就是說,如要取得舊版 API 的對應費率 (例如位元率),應用程式必須計算兩次 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-candidatecandidate-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.requestsReceivedcandidate-pair.responsesReceived
.googLocalAddress local-candidate.address
(透過
candidate-pair.localCandidateId 查詢 local-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] 之間,但標準符合曲線在 [0..1] 範圍內。
.audioOutputLevel
inbound-rtp.audioLevel。舊版指標的範圍介於 [0..32768] 之間,但標準符合曲線在 [0..1] 範圍內。
.packetsLost inbound-rtp.packetsLost
.googTrackId 本機 MediaStreamTrackmedia-source.trackIdentifier,遠端 MediaStreamTrackinbound-rtp.trackIdentifier
.googRtt remote-inbound-rtp.roundTripTime (請參閱「outbound-rtp.remoteId」)
.googEchoCancellationReturnLossEnhancement inbound-rtp.echoReturnLossEnhancement
.googCodecName 轉碼器名稱是「type/subtype」的子類型MIME 類型:codec.mimeType (請參閱 inbound-rtp.codecIdoutbound-rtp.codecId)
.transportId inbound-rtp.transportIdoutbound-rtp.transportId
.mediaType inbound-rtp.kindoutbound-rtp.kindmedia-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
雖然傳送每秒影格數是 outbound-rtp.framesSent 的變更速率,但實際上是實作為 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。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 只會回報一個 SSRC,即使您使用模擬功能傳送三個不同的 SSRC 來傳送三個 RTP 串流 (例如),

標準 API 並未分享這項限制,並會傳回三個 outbound-rtp 統計資料物件 (每個 SSRC 各一個)。也就是說,您可以個別分析每個 RTP 串流,但也代表您必須自行匯總所有 RTP 傳送串流的總位元率。

另一方面,具有多個空間層透過 scalabilityMode API 設定的 SVC 串流或 RTP 串流,仍會顯示為單一 outbound-rtp,因為這些內容是透過單一 SSRC 傳送。

需要更多時間遷移

在 Chrome 117 中移除舊版 API 後,使用該 API 將產生例外狀況。如果您無法及時遷移程式碼,可以參考 RTCPeerConnection 回呼式 getStats() API 的來源試用,讓已註冊的網站有更多時間遷移。如為來源試用權杖,則可繼續使用舊版 getStats() API,直到 Chrome 121 版為止。