A API WebRTC legada getStats()
será removida no Chrome 117. Portanto, os apps que a usam precisarão migrar para a API padrão. Este artigo explica como migrar seu código e o que fazer se você precisar de mais tempo para fazer essa alteração.
Historicamente, há duas versões concorrentes da API WebRTC getStats()
. A API getStats() legada, 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 é mais rica em recursos e tem métricas bem definidas documentadas publicamente na especificação W3C Identificadores para a API Statistics's Statistics. 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 Stable (a exceção gerada será lançada gradualmente). Siga este guia para facilitar sua transição para a API padrão.
Tipos de estatísticas legadas e padrão
A lista completa dos tipos de estatísticas padrão pode ser encontrada na enumeração RTCStatsType na especificação. Isso inclui qual definição do dicionário de estatísticas descreve as métricas coletadas para cada tipo.
Todos os objetos de estatística têm um atributo id que identifica exclusivamente o objeto subjacente em várias chamadas getStats()
. O mesmo objeto terá o mesmo ID todas as vezes que o método for chamado. Isso é útil para calcular a taxa de alteração de métricas (há um exemplo na próxima seção). Os IDs também formam relacionamentos de referências. Por exemplo, o objeto de estatísticas outbound-rtp
faz referência ao objeto de estatísticas media-source
associado usando o atributo outbound-rtp.mediaSourceId
. Se você desenhar todas as relações ...Id
, um gráfico será gerado.
A API legada tem os seguintes tipos de estatísticas, que correspondem aos tipos padrão:
Tipo legado |
Tipo padrão |
---|---|
ssrc
|
Representa um fluxo de RTP e métricas sobre o MediaStreamTrack associado.Os tipos padrão para isso são inbound-rtp (para fluxos de RTP de recebimento e os MediaStreamTrack remotos associados), outbound-rtp (para streams de RTP de envio) e media-source (para métricas locais de MediaStreamTrack associadas a um fluxo de RTP de envio). As métricas de fluxo de RTP também contêm informações sobre o codificador ou decodificador usado pelo stream de RTP. |
VideoBwe
|
Métricas de estimativa de largura de banda, taxa de bits de destino, 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 do par de candidatos ICE (candidate-pair ). |
googComponent
|
Representa o transporte (ICE e DTLS). A versão padrão é transport . |
localcandidate and remotecandidate
|
Representa um candidato da ICE. A versão padrão é local-candidate e remote-candidate . |
googCandidatePair
|
Representa um par de candidatos ICE, que é um par de um candidato local e um 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 mapeie 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 têm tipos legados correspondentes:
|
Mapeamento de métricas legadas para padrão
Esse mapeamento tem como objetivo ajudar os desenvolvedores a encontrar qual métrica legada corresponde a qual métrica padrão. No entanto, 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étrica.
A API padrão prefere expor os 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 por conta própria pode parecer complicado, 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 poderia ter a ver 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 ao localcandidate acima. |
Igual ao 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 (consulta remote-candidate por candidate-pair.remoteCandidateId ) |
.googReadable
|
googReadable é um booleano que indica se o candidate-pair.requestsReceived ou candidate-pair.responsesReceived foi incrementado recentemente
|
.googLocalAddress
|
local-candidate.address (consulta local-candidate por 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 indica se o candidate-pair.responsesReceived foi ou não incrementado recentemente
|
.googRemoteAddress
|
remote-candidate.address
|
.googRtt
|
candidate-pair.currentRoundTripTime
|
.googActiveConnection
|
A conexão ativa se refere ao par candidato atualmente selecionado pelo transporte, como em que 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á dentro do intervalo [0..32768], mas a métrica padrão está dentro do intervalo [0..1]. |
.audioOutputLevel
|
inbound-rtp.audioLevel A métrica legada está dentro do intervalo [0..32768], mas a métrica padrão está dentro do intervalo [0..1]. |
.packetsLost
|
inbound-rtp.packetsLost
|
.googTrackId
|
media-source.trackIdentifier para MediaStreamTrack s locais e inbound-rtp.trackIdentifier para MediaStreamTrack s remotas |
.googRtt
|
remote-inbound-rtp.roundTripTime (consulte outbound-rtp.remoteId ) |
.googEchoCancellationReturnLossEnhancement
|
inbound-rtp.echoReturnLossEnhancement
|
.googCodecName
|
O nome do codec é o subtipo do tipo MIME "tipo/subtipo", 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 QPS de envio seja a taxa de mudança de outbound-rtp.framesSent , ele é implementado como outbound-rtp.framesPerSecond , que é a codificação de FPS. |
.googFrameWidthReceived
|
inbound-rtp.frameWidth
|
.googFrameHeightReceived
|
inbound-rtp.frameHeight
|
.googFrameRateDecoded
|
A taxa de mudança de inbound-rtp.framesDecoded |
.googFrameRateOutput
|
Taxa de mudança de inbound-rtp.framesDecoded a 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 o frame rate mudou por motivos relacionados a qualityLimitationReason . Isso pode ser deduzido de outras métricas (por exemplo, a resolução de saída ou o frame rate diferente da resolução da origem ou do frame rate). No entanto, a duração limitada, outbound-rtp.qualityLimitationDurations , pode ser mais útil do que a frequência com que a resolução ou o frame rate foram reconfigurados. |
.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 contendo a correção de erro: 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 o stream não estava em silêncio: de (inbound-rtp.concealedSamples - inbound-rtp.silentConcealedSamples ) / inbound-rtp.concealedSamples |
.googAccelerateRate
|
A proporção recente de amostras que foram descartadas para acelerar a velocidade de reprodução: inbound-rtp.removedSamplesForAcceleration / inbound-rtp.totalSamplesReceived |
.googPreemptiveExpandRate
|
A proporção recente de amostras que foram 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
|
O único "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 do payload, excluindo retransmissões: a taxa de mudança de outbound-rtp.bytesSent a 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 RTP, candidate-pair.bytesSent para taxa de bits de candidato a ICE ou transport.bytesSent para 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 reconhece a transmissão simultânea
Se você usa a transmissão simultânea, talvez a API legada informe apenas uma SSRC, mesmo quando você estiver usando a transmissão simultânea para enviar (por exemplo) três streams de 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 SSRCs. Isso significa que é possível analisar cada stream de RTP individualmente, mas isso também significa que, para obter a taxa de bits total de todos os streams de envio de RTP, você precisará agregá-los por conta própria.
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 você não conseguir migrar seu código a tempo, o teste de origem da API getStats() baseada em callback do RTCPeerConnection oferece mais tempo para os sites registrados migrarem. Com um token de teste de origem, a API getStats() legada pode continuar sendo usada até o Chrome 121.