Chrome 117 即將移除舊版 getStats()
WebRTC API,因此必須使用這個 API 的應用程式必須遷移至標準 API。本文將說明如何遷移程式碼,以及需要更多時間進行這項變更。
WebRTC getStats()
API 以往有兩種彼此競爭的版本。舊版 getStats() API 會預先標準化程序並採用回呼引數,以及經過標準化且廣為支援的 API,會傳回 promise。
標準 API 的功能更加豐富,並有公開定義的指標,詳情請參閱 W3C 規格的 WebRTC 統計資料 API 規格。規格包含本指南中每個指標的說明以及許多其他內容。
自 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-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 偏好顯示總數,而非費率。這表示如要取得舊版 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-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
|
media-source.trackIdentifier 代表本機 MediaStreamTrack ,inbound-rtp.trackIdentifier 代表遠端 MediaStreamTrack |
.googRtt
|
remote-inbound-rtp.roundTripTime (請參閱 outbound-rtp.remoteId ) |
.googEchoCancellationReturnLossEnhancement
|
inbound-rtp.echoReturnLossEnhancement
|
.googCodecName
|
轉碼器名稱是「類型/子類型」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
|
雖然傳送每秒影格數是 outbound-rtp.framesSent 的變化率,但實際上是以 outbound-rtp.framesPerSecond 的形式實作,用於編碼 FPS。 |
.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 變更速率,candidate-pair.bytesSent 代表個別 ICE 候選位元率,或 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 的來源試用可為已註冊的網站提供更多遷移時間。透過來源試用權杖,在 Chrome 121 版之前,您可以繼續使用舊版 getStats() API。