A API getStats()
WebRTC legada será removida no Chrome 117. Portanto, os apps que a usam vão precisar migrar para a API padrão. Neste artigo, explicamos como migrar seu código e o que fazer se você precisar de mais tempo para fazer essa mudança.
Historicamente, houve duas versões concorrentes da API getStats()
do WebRTC. A API legada getStats(), que antecede o processo de padronização e recebe um argumento de callback, e a API padronizada e amplamente compatível que retorna uma promessa.
A API padrão tem mais recursos e métricas bem definidas, documentadas publicamente na especificação do W3C Identifiers for WebRTC's Statistics API (em inglês). A especificação inclui descrições de cada métrica listada neste guia e muito mais.
No Chrome 117 e versões mais recentes, a API getStats()
legada vai gerar uma exceção no canal de lançamento estável. A exceção será lançada gradualmente. Siga este guia para facilitar a transição para a API padrão.
Tipos de estatísticas legados e padrão
A lista completa de tipos de estatísticas padrão pode ser encontrada na enumeração RTCStatsType na especificação. Isso inclui a definição do dicionário de estatísticas que descreve as métricas coletadas para cada tipo.
Todos os objetos de estatísticas têm um atributo id que identifica exclusivamente o objeto em várias chamadas getStats()
. O mesmo objeto terá o mesmo ID sempre que o método for chamado. Isso é útil para calcular a taxa de mudança das métricas. Confira um exemplo na próxima seção. Os IDs também formam relações de referências. Por exemplo, o objeto de estatísticas outbound-rtp
faz referência ao objeto de estatísticas media-source
associado pelo atributo outbound-rtp.mediaSourceId
. Se você desenhar todas as relações ...Id
, vai receber um gráfico.
A API legada tem os seguintes tipos de estatísticas, correspondentes aos tipos padrão:
Tipo legado |
Padrão |
---|---|
ssrc
|
Representa um fluxo RTP e métricas sobre o MediaStreamTrack associado.Os tipos padrão para isso são inbound-rtp (para receber streams RTP e o MediaStreamTrack remoto associado), outbound-rtp (para enviar streams RTP) e media-source (para métricas locais de MediaStreamTrack associadas a um stream RTP de envio). As métricas do fluxo RTP também contêm informações sobre o codificador ou decodificador usado pelo fluxo RTP. |
VideoBwe
|
Métricas de estimativa de largura de banda, taxa de bits desejada, taxa de bits do codificador e taxa de bits real. Esses tipos de métricas fazem parte das métricas de RTP ( outbound-rtp e inbound-rtp ) e das métricas de par de candidato ICE (candidate-pair ). |
googComponent
|
Representa o transporte (ICE e DTLS). A versão padrão é transport . |
localcandidate and remotecandidate
|
Representa um candidato ICE. A versão padrão é local-candidate e remote-candidate . |
googCandidatePair
|
Representa um par de candidato ICE, que é um par de candidato local e remoto. A versão padrão é candidate-pair . |
googCertificate
|
Representa um certificado usado pelo transporte DTLS. A versão padrão é certificate . |
googLibjingleSession
|
Representa o RTCPeerConnection . Embora o conteúdo não seja mapeado para nada no padrão, o padrão tem um tipo associado ao RTCPeerConnection : peer-connection . |
Ausente na API legada |
Esses tipos de estatísticas foram adicionados à API padrão que não tem um tipo legados correspondente:
|
Mapeamento de métricas legadas para métricas padrão
O objetivo desse mapeamento é ajudar os desenvolvedores a encontrar qual métrica legada corresponde a qual métrica padrão, mas a métrica correspondente pode usar unidades diferentes ou ser expressa como um contador total em vez de um valor instantâneo. Consulte a especificação para definições de métricas.
A API padrão prefere mostrar contadores totais em vez de taxas. Isso significa que, para receber a taxa correspondente (por exemplo, taxa de bits), como na API legada, o app precisa calcular a taxa média usando o delta entre duas chamadas getStats()
. Exemplo:
// 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;
Ter que calcular taxas e médias dessa forma pode parecer uma etapa adicional complicada, mas tem a vantagem de permitir que você obtenha médias em qualquer intervalo de tempo desejado. Chamar a API padrão com menos frequência do que você precisaria fazer com a API legada tem alguns benefícios de desempenho.
Métrica legada
googCertificate |
Correspondência padrão
certificate |
---|---|
.googFingerprint
|
.fingerprint
|
.googFingerprintAlgorithm
|
.fingerprintAlgorithm
|
.googDerBase64
|
.base64Certificate
|
Métrica legada
googComponent |
Correspondência padrão
transport |
---|---|
.localCertificateId
|
.localCertificateId
|
.remoteCertificateId
|
.remoteCertificateId
|
.selectedCandidatePairId
|
.selectedCandidatePairId
|
.dtlsCipher
|
.dtlsCipher
|
.srtpCipher
|
.srtpCipher
|
Métrica legada
localcandidate |
Correspondência padrão
local-candidate ou candidate-pair |
---|---|
.stunKeepaliveRequestsSent
|
candidate-pair.requestsSent (pesquisa reversa candidate-pair via 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 legada
remotecandidate |
Correspondência padrão
remote-candidate |
---|---|
Igual a localcandidate acima. |
Igual a local-candidate acima. |
Métrica legada
googCandidatePair |
Correspondência padrão
candidate-pair |
---|---|
.responsesSent
|
candidate-pair.responsesSent
|
.requestsReceived
|
candidate-pair.requestsReceived
|
.googRemoteCandidateType
|
remote-candidate.candidateType (procurar remote-candidate usando candidate-pair.remoteCandidateId ) |
.googReadable
|
googReadable é um booleano que reflete se incrementamos recentemente candidate-pair.requestsReceived ou candidate-pair.responsesReceived
|
.googLocalAddress
|
local-candidate.address (procurar local-candidate usando candidate-pair.localCandidateId ) |
.consentRequestsSent
|
candidate-pair.consentRequestsSent
|
.googTransportType
|
Igual a local-candidate.protocol e remote-candidate.protocol . |
.googChannelId
|
candidate-pair.transportId
|
.googLocalCandidateType
|
local-candidate.candidateType
|
.googWritable
|
googWritable é um booleano que reflete se incrementamos candidate-pair.responsesReceived recentemente
|
.googRemoteAddress
|
remote-candidate.address
|
.googRtt
|
candidate-pair.currentRoundTripTime
|
.googActiveConnection
|
A conexão ativa se refere ao par candidato que está selecionado pelo transporte, como onde 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 legada
ssrc |
Correspondência padrão
inbound-rtp , outbound-rtp , media-source |
---|---|
.audioInputLevel
|
media-source.audioLevel . A métrica legada está no intervalo [0..32768], mas a métrica padrão está no intervalo [0..1]. |
.audioOutputLevel
|
inbound-rtp.audioLevel . A métrica legada está no intervalo [0..32768], mas a métrica padrão está no intervalo [0..1]. |
.packetsLost
|
inbound-rtp.packetsLost
|
.googTrackId
|
media-source.trackIdentifier para MediaStreamTrack s locais e inbound-rtp.trackIdentifier para MediaStreamTrack s remotos |
.googRtt
|
remote-inbound-rtp.roundTripTime (consulte outbound-rtp.remoteId ) |
.googEchoCancellationReturnLossEnhancement
|
inbound-rtp.echoReturnLossEnhancement
|
.googCodecName
|
O nome do codec é o subtipo do tipo MIME "type/subtype", codec.mimeType (consulte inbound-rtp.codecId e outbound-rtp.codecId ). |
.transportId
|
inbound-rtp.transportId e outbound-rtp.transportId |
.mediaType
|
inbound-rtp.kind e outbound-rtp.kind ou media-source.kind
|
.googEchoCancellationReturnLoss
|
inbound-rtp.echoReturnLoss
|
.totalAudioEnergy
|
inbound-rtp.totalAudioEnergy e media-source.totalAudioEnergy
|
ssrc.totalSamplesDuration
|
inbound-rtp.totalSamplesDuration e media-source.totalSamplesDuration
|
.ssrc
|
inbound-rtp.ssrc e outbound-rtp.ssrc
|
.googJitterReceived
|
inbound-rtp.jitter
|
.packetsSent
|
outbound-rtp.packetsSent
|
.bytesSent
|
outbound-rtp.bytesSent
|
.googContentType
|
inbound-rtp.contentType e outbound-rtp.contentType |
.googFrameWidthInput
|
media-source.width
|
.googFrameHeightInput
|
media-source.height
|
.googFrameRateInput
|
media-source.framesPerSecond
|
.googFrameWidthSent
|
outbound-rtp.frameWidth
|
.googFrameHeightSent
|
outbound-rtp.frameHeight
|
.googFrameRateSent
|
Embora o FPS de envio seja a taxa de mudança de outbound-rtp.framesSent , ele é implementado como outbound-rtp.framesPerSecond , que codifica o FPS. |
.googFrameWidthReceived
|
inbound-rtp.frameWidth
|
.googFrameHeightReceived
|
inbound-rtp.frameHeight
|
.googFrameRateDecoded
|
A taxa de mudança de inbound-rtp.framesDecoded |
.googFrameRateOutput
|
A taxa de mudança de inbound-rtp.framesDecoded - inbound-rtp.framesDropped |
.hugeFramesSent
|
outbound-rtp.hugeFramesSent
|
.qpSum
|
|
.framesEncoded
|
outbound-rtp.framesEncoded
|
.googAvgEncodeMs
|
|
.codecImplementationName
|
|
.googCpuLimitedResolution
|
Verdadeiro se outbound-rtp.qualityLimitationReason == "cpu" |
.googBandwidthLimitedResolution
|
Verdadeiro se outbound-rtp.qualityLimitationReason == "bandwidth" |
.googAdaptationChanges
|
A métrica legada conta o número de vezes que a resolução ou a taxa de frames mudou por motivos relacionados a qualityLimitationReason . Isso pode ser deduzido de outras métricas (por exemplo, a resolução ou a taxa de frames do envio ser diferente da resolução ou da taxa de frames da origem), mas a duração do limite, outbound-rtp.qualityLimitationDurations , pode ser mais útil do que a frequência com que a resolução ou a taxa de frames foi reconfigurada. |
.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
|
A proporção recente de pacotes com correção de erros: inbound-rtp.fecPacketsReceived - inbound-rtp.fecPacketsDiscarded |
.packetsReceived
|
inbound-rtp.packetsReceived
|
.googJitterBufferMs
|
inbound-rtp.jitterBufferDelay / inbound-rtp.jitterBufferEmittedCount
|
.googTargetDelayMs (vídeo) |
inbound-rtp.jitterBufferTargetDelay / inbound-rtp.jitterBufferEmittedCount
|
.googPreferredJitterBufferMs (áudio) |
inbound-rtp.jitterBufferTargetDelay / inbound-rtp.jitterBufferEmittedCount
|
.googExpandRate
|
A proporção recente de amostras ocultas: inbound-rtp.concealedSamples / inbound-rtp.totalSamplesReceived |
.googSpeechExpandRate
|
A proporção recente de amostras ocultas enquanto a transmissão não estava em silêncio: (inbound-rtp.concealedSamples - inbound-rtp.silentConcealedSamples ) / inbound-rtp.concealedSamples |
.googAccelerateRate
|
A proporção recente de amostras descartadas para acelerar a velocidade de reprodução: inbound-rtp.removedSamplesForAcceleration / inbound-rtp.totalSamplesReceived |
.googPreemptiveExpandRate
|
A proporção recente de amostras sintetizadas para desacelerar a velocidade de reprodução: 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
|
A única goog-metric restante. inbound-rtp.googTimingFrameInfo |
.framesDecoded
|
inbound-rtp.framesDecoded
|
Métrica legada
VideoBwe |
Correspondência padrão
outbound-rtp e candidate-pair |
---|---|
.googTargetEncBitrate
|
outbound-rtp.targetBitrate como um valor instantâneo ou outbound-rtp.totalEncodedBytesTarget / outbound-rtp.framesEncoded como uma média |
.googActualEncBitrate
|
Os bytes produzidos pelo codificador são os bytes de payload, excluindo as retransmissões: a taxa de mudança de outbound-rtp.bytesSent - outbound-rtp.retransmittedBytesSent |
.googBucketDelay
|
outbound-rtp.totalPacketSendDelay / outbound-rtp.packetsSent
|
.googTransmitBitrate
|
A taxa de mudança de outbound-rtp.headerBytesSent + outbound-rtp.bytesSent para a taxa de bits por fluxo RTP, candidate-pair.bytesSent para a taxa de bits por candidato ICE ou transport.bytesSent para a taxa de bits por transporte |
.googRetransmitBitrate
|
O intervalo de mudança de outbound-rtp.retransmittedBytesSent |
.googAvailableSendBandwidth
|
candidate-pair.availableOutgoingBitrate
|
.googAvailableReceiveBandwidth
|
candidate-pair.availableIncomingBitrate
|
A API padrão é compatível com simulcast
Se você usa a transmissão simultânea, talvez tenha notado que a API legada só informa um único SSRC, mesmo quando você usa a transmissão simultânea para enviar (por exemplo) três streams RTP em três SSRCs separados.
A API padrão não compartilha essa limitação e retorna três objetos de estatísticas outbound-rtp
, um para cada SSRC. Isso significa que você pode analisar cada stream RTP individualmente, mas também significa que, para conseguir o bitrate total de todos os streams de envio RTP, você precisa agregá-los.
Os streams SVC ou RTP com várias camadas espaciais configuradas pela API scalabilityMode
, por outro lado, ainda aparecem como um único outbound-rtp
porque são enviados por um único SSRC.
Se você precisar de mais tempo para a migração
Quando a API legada for removida no Chrome 117, o uso dela vai gerar uma exceção. Se não for possível migrar o código a tempo, o teste de origem para a API getStats() com base em callback da RTCPeerConnection dá mais tempo para a migração dos sites registrados. Com um token de teste de origem, a API legada getStats() pode continuar sendo usada até o Chrome 121.