WebRTC:旧版 getStats() 迁移指南

Henrik Boström
Henrik Boström

旧版 getStats() WebRTC API 将从 Chrome 117 中移除,因此使用该 API 的应用需要迁移到标准 API。本文介绍了如何迁移代码,以及如果您需要更多时间来完成此更改,应该怎么做。

WebRTC getStats() API 过去有两个竞争版本。旧版 getStats() API(早于标准化流程日期并采用回调参数)和广泛支持的标准化 API(会返回 promise)。

标准 API 功能更丰富,并且在 W3C 规范 WebRTC Statistics 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-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 接收器报告 (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] 范围内,但标准 Merc 在 [0..1] 范围内。
.audioOutputLevel
inbound-rtp.audioLevel。旧版指标在 [0..32768] 范围内,但标准 Merc 在 [0..1] 范围内。
.packetsLost inbound-rtp.packetsLost
.googTrackId media-source.trackIdentifier 用于本地 MediaStreamTrackinbound-rtp.trackIdentifier 用于远程 MediaStreamTrack
.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.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 的变化率,但这实际上是以 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

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
仅剩的 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 可感知同步播放

如果您使用同时直播,可能会注意到,即使您使用同步直播通过三个单独的 SSRC 发送(举例而言)三个 RTP 流,旧版 API 也只会报告一个 SSRC。

标准 API 没有此限制,将返回三个 outbound-rtp 统计信息对象,每个 SSRC 对应一个。也就是说,您可以单独分析每个 RTP 流,但要获得所有 RTP 发送流的总比特率,您需要自行聚合它们。

另一方面,通过 scalabilityMode API 配置多个空间层的 SVC 视频流或 RTP 视频流仍会显示为单个 outbound-rtp,因为它们是通过单个 SSRC 发送的。

如果您需要更多时间进行迁移

在 Chrome 117 中移除旧版 API 后,使用该 API 会引发异常。如果您无法及时迁移代码,基于 RTCPeerConnection 回调的 getStats() API 源试用会为已注册的网站提供更多迁移时间。借助源试用令牌,旧版 getStats() API 可继续使用到 Chrome 121。