Se quitará la API heredada de getStats()
de WebRTC en Chrome 117, por lo que las apps que la usen deberán migrar a la API estándar. En este artículo, se explica cómo migrar tu código y qué hacer si necesitas más tiempo para realizar este cambio.
Históricamente, ha habido dos versiones que compiten de la API de getStats()
de WebRTC. La API heredada de getStats(), que es anterior al proceso de estandarización y toma un argumento de devolución de llamada, y la API estandarizada y ampliamente admitida que muestra una promesa.
La API estándar cuenta con más funciones y tiene métricas bien definidas que se documentan públicamente en la especificación de W3C Identifiers for WebRTC's Statistics API. La especificación incluye descripciones de cada métrica que aparece en esta guía y muchas más.
A partir de Chrome 117, la API de getStats()
heredada arrojará una excepción en el canal de versiones estable (la excepción se lanzará de forma gradual). Sigue esta guía para facilitar tu transición a la API estándar.
Tipos de estadísticas heredados frente a los estándar
Puedes encontrar la lista completa de los tipos de estadísticas estándar en la enum RTCStatsType de la especificación. Esto incluye qué definición del diccionario de estadísticas describe las métricas recopiladas para cada tipo.
Todos los objetos de estadísticas tienen un atributo de ID que identifica de forma única el objeto subyacente en varias llamadas a getStats()
. El mismo objeto tendrá el mismo ID cada vez que se llame al método. Esto es útil para calcular la tasa de cambio de las métricas (encontrarás un ejemplo en la siguiente sección). Los ID también forman relaciones de referencias. Por ejemplo, el objeto de estadísticas outbound-rtp
hace referencia al objeto de estadísticas media-source
asociado a través del atributo outbound-rtp.mediaSourceId
. Si dibujas todas las relaciones ...Id
, obtienes un gráfico.
La API heredada tiene los siguientes tipos de estadísticas, correspondientes a los tipos estándar:
Tipo heredado |
Tipo estándar |
---|---|
ssrc
|
Representa una transmisión de RTP y métricas acerca del MediaStreamTrack asociado.Los tipos estándar para esto son inbound-rtp (para recibir transmisiones RTP y su MediaStreamTrack remota asociada), outbound-rtp (para transmisiones RTP de envío) y media-source (para métricas locales MediaStreamTrack asociadas con una transmisión de RTP de envío). Las métricas de la transmisión RTP también contienen información sobre el codificador o el decodificador utilizado por la transmisión RTP. |
VideoBwe
|
Métricas de estimación del ancho de banda, tasa de bits objetivo, tasa de bits del codificador y tasa de bits real. Estos tipos de métricas forman parte de las métricas de RTP ( outbound-rtp y inbound-rtp ) y de las métricas del par de candidatos de ICE (candidate-pair ). |
googComponent
|
Representa el transporte (ICE y DTLS). La versión estándar es transport . |
localcandidate and remotecandidate
|
Representa a un candidato de ICE. La versión estándar es local-candidate y remote-candidate . |
googCandidatePair
|
Representa un par de candidatos de ICE, que es una combinación de un candidato local y uno remoto. La versión estándar es candidate-pair . |
googCertificate
|
Representa un certificado que usa el transporte DTLS. La versión estándar es certificate . |
googLibjingleSession
|
Representa el RTCPeerConnection . Si bien su contenido no se asigna a ningún elemento del estándar, este tiene un tipo asociado con RTCPeerConnection : peer-connection . |
Falta en la API heredada |
Se agregaron estos tipos de estadísticas a la API estándar y no tienen ningún tipo heredado correspondiente:
|
Asignación de métricas heredadas a estándar
El objetivo de esta asignación es ayudar a los desarrolladores a encontrar qué métrica heredada corresponde a qué métrica estándar, pero ten en cuenta que la métrica correspondiente puede usar diferentes unidades o se puede expresar como un contador total en lugar de un valor instantáneo. Consulta las especificaciones para las definiciones de métricas.
La API estándar prefiere exponer los contadores totales en lugar de las tarifas. Esto significa que, para obtener la tarifa correspondiente (por ejemplo, la tasa de bits) como en la API heredada, la app debe calcular la tarifa promedio tomando el valor delta entre dos llamadas getStats()
. Por ejemplo:
// 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;
Tener que calcular las tasas y los promedios por tu cuenta puede parecer un paso adicional engorroso, pero tiene la ventaja de permitirte obtener promedios durante cualquier intervalo de tiempo deseado. Llamar a la API estándar con menos frecuencia de la que tendrías que ver con la API heredada tiene algunos beneficios de rendimiento.
Métrica heredada
de googCertificate |
Correspondencia estándar
de certificate |
---|---|
.googFingerprint
|
.fingerprint
|
.googFingerprintAlgorithm
|
.fingerprintAlgorithm
|
.googDerBase64
|
.base64Certificate
|
Métrica heredada
de googComponent |
Correspondencia estándar
de transport |
---|---|
.localCertificateId
|
.localCertificateId
|
.remoteCertificateId
|
.remoteCertificateId
|
.selectedCandidatePairId
|
.selectedCandidatePairId
|
.dtlsCipher
|
.dtlsCipher
|
.srtpCipher
|
.srtpCipher
|
Métrica heredada
de localcandidate |
Correspondencia estándar
local-candidate o candidate-pair |
---|---|
.stunKeepaliveRequestsSent
|
candidate-pair.requestsSent (búsqueda inversa de candidate-pair a través de candidate-pair.localCandidateId ) |
.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
|
Métrica heredada
de remotecandidate |
Correspondencia estándar
de remote-candidate |
---|---|
Igual que el localcandidate anterior. |
Igual que el local-candidate anterior. |
Métrica heredada
de googCandidatePair |
Correspondencia estándar
de candidate-pair |
---|---|
.responsesSent
|
candidate-pair.responsesSent
|
.requestsReceived
|
candidate-pair.requestsReceived
|
.googRemoteCandidateType
|
remote-candidate.candidateType (busca remote-candidate mediante candidate-pair.remoteCandidateId ) |
.googReadable
|
googReadable es un valor booleano que refleja si recientemente aumentamos candidate-pair.requestsReceived o candidate-pair.responsesReceived .
|
.googLocalAddress
|
local-candidate.address (busca local-candidate mediante candidate-pair.localCandidateId ) |
.consentRequestsSent
|
candidate-pair.consentRequestsSent
|
.googTransportType
|
Igual que local-candidate.protocol y remote-candidate.protocol . |
.googChannelId
|
candidate-pair.transportId
|
.googLocalCandidateType
|
local-candidate.candidateType
|
.googWritable
|
googWritable es un valor booleano que refleja si aumentamos o no recientemente el candidate-pair.responsesReceived .
|
.googRemoteAddress
|
remote-candidate.address
|
.googRtt
|
candidate-pair.currentRoundTripTime
|
.googActiveConnection
|
La conexión activa hace referencia al par de candidatos que el transporte selecciona actualmente, como cuando 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
|
Métrica heredada
de ssrc |
Correspondencia estándar
inbound-rtp , outbound-rtp y media-source |
---|---|
.audioInputLevel
|
media-source.audioLevel . La métrica heredada está dentro del rango [0..32768], pero la métrica estándar está dentro del rango [0..1]. |
.audioOutputLevel
|
inbound-rtp.audioLevel La métrica heredada está dentro del rango [0..32768], pero la métrica estándar está dentro del rango [0..1]. |
.packetsLost
|
inbound-rtp.packetsLost
|
.googTrackId
|
media-source.trackIdentifier para MediaStreamTrack locales y inbound-rtp.trackIdentifier para MediaStreamTrack remotos |
.googRtt
|
remote-inbound-rtp.roundTripTime (consulta outbound-rtp.remoteId ) |
.googEchoCancellationReturnLossEnhancement
|
inbound-rtp.echoReturnLossEnhancement
|
.googCodecName
|
El nombre del códec es el subtipo del "tipo/subtipo" tipo de MIME, codec.mimeType (consulta inbound-rtp.codecId y outbound-rtp.codecId ) |
.transportId
|
inbound-rtp.transportId y outbound-rtp.transportId |
.mediaType
|
inbound-rtp.kind y outbound-rtp.kind o media-source.kind
|
.googEchoCancellationReturnLoss
|
inbound-rtp.echoReturnLoss
|
.totalAudioEnergy
|
inbound-rtp.totalAudioEnergy y media-source.totalAudioEnergy
|
ssrc.totalSamplesDuration
|
inbound-rtp.totalSamplesDuration y media-source.totalSamplesDuration
|
.ssrc
|
inbound-rtp.ssrc y outbound-rtp.ssrc
|
.googJitterReceived
|
inbound-rtp.jitter
|
.packetsSent
|
outbound-rtp.packetsSent
|
.bytesSent
|
outbound-rtp.bytesSent
|
.googContentType
|
inbound-rtp.contentType y outbound-rtp.contentType |
.googFrameWidthInput
|
media-source.width
|
.googFrameHeightInput
|
media-source.height
|
.googFrameRateInput
|
media-source.framesPerSecond
|
.googFrameWidthSent
|
outbound-rtp.frameWidth
|
.googFrameHeightSent
|
outbound-rtp.frameHeight
|
.googFrameRateSent
|
Si bien el valor de FPS de envío es la tasa de cambio de outbound-rtp.framesSent , en realidad se implementa como outbound-rtp.framesPerSecond , que codifica los FPS. |
.googFrameWidthReceived
|
inbound-rtp.frameWidth
|
.googFrameHeightReceived
|
inbound-rtp.frameHeight
|
.googFrameRateDecoded
|
La tasa de cambio de inbound-rtp.framesDecoded |
.googFrameRateOutput
|
La tasa de cambio de inbound-rtp.framesDecoded - inbound-rtp.framesDropped |
.hugeFramesSent
|
outbound-rtp.hugeFramesSent
|
.qpSum
|
|
.framesEncoded
|
outbound-rtp.framesEncoded
|
.googAvgEncodeMs
|
|
.codecImplementationName
|
|
.googCpuLimitedResolution
|
Verdadero si outbound-rtp.qualityLimitationReason == "cpu" |
.googBandwidthLimitedResolution
|
Verdadero si outbound-rtp.qualityLimitationReason == "bandwidth" |
.googAdaptationChanges
|
La métrica heredada cuenta la cantidad de veces que cambió la resolución o la velocidad de fotogramas por motivos relacionados con qualityLimitationReason . Esto se podría deducir a partir de otras métricas (p.ej., la resolución de envío o la velocidad de fotogramas difiere de la resolución de origen o la velocidad de fotogramas), pero la duración limitada, outbound-rtp.qualityLimitationDurations , puede ser más útil que la frecuencia con la que se reconfiguró la resolución o la velocidad de fotogramas. |
.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
|
La proporción reciente de paquetes que contienen corrección de errores: inbound-rtp.fecPacketsReceived - inbound-rtp.fecPacketsDiscarded |
.packetsReceived
|
inbound-rtp.packetsReceived
|
.googJitterBufferMs
|
inbound-rtp.jitterBufferDelay /inbound-rtp.jitterBufferEmittedCount
|
.googTargetDelayMs (video) |
inbound-rtp.jitterBufferTargetDelay /inbound-rtp.jitterBufferEmittedCount
|
.googPreferredJitterBufferMs (audio) |
inbound-rtp.jitterBufferTargetDelay /inbound-rtp.jitterBufferEmittedCount
|
.googExpandRate
|
La proporción reciente de muestras ocultas: inbound-rtp.concealedSamples / inbound-rtp.totalSamplesReceived |
.googSpeechExpandRate
|
La proporción reciente de muestras ocultas mientras la transmisión no estaba en silencio: de (inbound-rtp.concealedSamples - inbound-rtp.silentConcealedSamples ) / inbound-rtp.concealedSamples |
.googAccelerateRate
|
Proporción reciente de muestras que se descartaron para acelerar la velocidad de reproducción: inbound-rtp.removedSamplesForAcceleration / inbound-rtp.totalSamplesReceived |
.googPreemptiveExpandRate
|
Proporción reciente de muestras que se sintetizaron para desacelerar la velocidad de reproducción: 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
|
La única métrica de goog restante. inbound-rtp.googTimingFrameInfo |
.framesDecoded
|
inbound-rtp.framesDecoded
|
Métrica heredada
de VideoBwe |
Correspondencia estándar
outbound-rtp y candidate-pair |
---|---|
.googTargetEncBitrate
|
outbound-rtp.targetBitrate como valor instantáneo o outbound-rtp.totalEncodedBytesTarget / outbound-rtp.framesEncoded como promedio |
.googActualEncBitrate
|
Los bytes que produce el codificador son los bytes de carga útil, sin incluir las retransmisiones: la tasa de cambio de outbound-rtp.bytesSent a outbound-rtp.retransmittedBytesSent . |
.googBucketDelay
|
outbound-rtp.totalPacketSendDelay /outbound-rtp.packetsSent
|
.googTransmitBitrate
|
La tasa de cambio de outbound-rtp.headerBytesSent + outbound-rtp.bytesSent para la tasa de bits de transmisión por RTP, candidate-pair.bytesSent para la tasa de bits candidata por ICE o transport.bytesSent para la tasa de bits por transporte |
.googRetransmitBitrate
|
El rango de cambio de outbound-rtp.retransmittedBytesSent |
.googAvailableSendBandwidth
|
candidate-pair.availableOutgoingBitrate
|
.googAvailableReceiveBandwidth
|
candidate-pair.availableIncomingBitrate
|
La API estándar es compatible con la transmisión simultánea
Si usas la transmisión simultánea, es posible que hayas notado que la API heredada solo informa un solo SSRC, incluso cuando usas la transmisión simultánea para enviar (por ejemplo) tres transmisiones de RTP a través de tres SSRC diferentes.
La API estándar no comparte esta limitación y mostrará tres objetos de estadísticas outbound-rtp
, uno para cada uno de los SSRC. Esto significa que puedes analizar cada transmisión RTP individualmente, pero también significa que para obtener la tasa de bits total de todas las transmisiones de envío RTP, deberás agregarlas tú mismo.
Las transmisiones SVC o RTP con múltiples capas espaciales configuradas a través de la API de scalabilityMode
, por otro lado, siguen apareciendo como un único outbound-rtp
porque se envían a través de un solo SSRC.
Si necesitas más tiempo para la migración
Cuando se quite la API heredada en Chrome 117, usarla generará una excepción. Si no puedes migrar tu código a tiempo, la prueba de origen para la API getStats() basada en devoluciones de llamada de RTCPeerConnection, con más tiempo para migrar a los sitios web registrados. Con un token de prueba de origen, se puede seguir usando la API de getStats() heredada hasta Chrome 121.