WebRTC: guida alla migrazione con getStats() precedente

Henrik Boström
Henrik Boström

L'API WebRTC getStats() precedente verrà rimossa in Chrome 117, pertanto le app che la utilizzano dovranno eseguire la migrazione all'API standard. Questo articolo spiega come eseguire la migrazione del codice e cosa fare se hai bisogno di più tempo per apportare questa modifica.

Storicamente esistono due versioni concorrenti dell'API WebRTC getStats(). L'API legacy getStats(), che precede il processo di standardizzazione e utilizza un argomento di callback, e l'API standardizzata e ampiamente supportata che restituisce una promessa.

L'API standard è più ricca di funzionalità e presenta metriche ben definite documentate pubblicamente nella specifica W3C Identifiers for WebRTC's Statistics API. La specifica include le descrizioni di ogni metrica elencata in questa guida e molte altre.

A partire da Chrome 117, l'API getStats() precedente genererà un'eccezione nel canale di rilascio stabile (la generazione delle eccezioni verrà implementata gradualmente). Segui questa guida per semplificare la transizione all'API standard.

Tipi di statistiche precedenti e standard

L'elenco completo dei tipi di statistiche standard è disponibile nell'enumerazione RTCStatsType nella specifica. Include la definizione del dizionario delle statistiche che descrive le metriche raccolte per ogni tipo.

Tutti gli oggetti statistica hanno un attributo ID che identifica in modo univoco l'oggetto sottostante in più chiamate getStats(). Lo stesso oggetto avrà lo stesso ID ogni volta che viene chiamato il metodo. Questo è utile per calcolare il tasso di variazione delle metriche (c'è un esempio nella sezione successiva). Gli ID formano anche relazioni di riferimenti. Ad esempio, l'oggetto statistiche outbound-rtp fa riferimento all'oggetto statistiche media-source associato tramite l'attributo outbound-rtp.mediaSourceId. Se tracci tutte le relazioni di ...Id, viene visualizzato un grafico.

L'API legacy dispone dei seguenti tipi di statistiche, corrispondenti ai tipi standard come segue:


Tipo precedente

Tipo standard
ssrc
Rappresenta uno stream RTP e le metriche relative al MediaStreamTrack associato.


I tipi standard sono inbound-rtp (per la ricezione di stream RTP e il relativo MediaStreamTrack remoto associato), outbound-rtp (per l'invio di stream RTP) e media-source (per le metriche MediaStreamTrack locali associate a uno stream RTP di invio). Le metriche di flusso RTP contengono anche informazioni sull'encoder o sul decoder utilizzato dal flusso RTP.
VideoBwe
Metriche per la stima della larghezza di banda, velocità in bit target, velocità in bit del codificatore e velocità in bit effettiva. Questi tipi di metriche fanno parte delle metriche RTP (outbound-rtp e inbound-rtp) e delle metriche delle coppie di candidati ICE (candidate-pair).
googComponent
Rappresenta il trasporto (ICE e DTLS). La versione standard è transport.
localcandidate and remotecandidate
Rappresenta un candidato dell'ICE. La versione standard è local-candidate e remote-candidate.
googCandidatePair
Rappresenta una coppia di candidati dell'ICE, ovvero l'abbinamento di un candidato locale e di un candidato da remoto. La versione standard è candidate-pair.
googCertificate
Rappresenta un certificato utilizzato dal trasporto DTLS. La versione standard è certificate.
googLibjingleSession
Rappresenta il RTCPeerConnection. Anche se i suoi contenuti non sono associati a nessun elemento nello standard, lo standard ha un tipo associato a RTCPeerConnection: peer-connection.

Non presente nell'API precedente

Questi tipi di statistiche sono stati aggiunti all'API standard che non dispone di alcun tipo precedente corrispondente:
  • codec: un codec attualmente utilizzato da uno stream RTP, per la codifica o la decodifica. Si tratta di un sottoinsieme dei codec che sono stati negoziati in SDP.
  • remote-inbound-rtp: stream RTP in entrata di un endpoint remoto corrispondente a uno stream RTP in uscita che questo endpoint sta inviando (outbound-rtp). Viene misurato nell'endpoint remoto e segnalato in un report RTCP ricevitore (RR) o RTCP Extended Report (XR).
  • remote-outbound-rtp: stream RTP in uscita di un endpoint remoto corrispondente a uno stream RTP in entrata che questo endpoint riceve (inbound-rtp). Viene misurato nell'endpoint remoto e segnalato in un report RTCP Sender Report (SR).
  • media-playout: metriche sulla riproduzione di un MediaStreamTrack remoto associato a uno stream RTP in entrata (inbound-rtp).
  • data-channel: rappresenta un RTCDataChannel.

Mappatura delle metriche da legacy a standard

Questa mappatura è pensata per aiutare gli sviluppatori a capire quale metrica precedente corrisponde a una metrica standard, ma tieni presente che la metrica corrispondente potrebbe utilizzare unità diverse o essere espressa come contatore totale anziché come valore istantaneo. Fai riferimento alle specifiche per le definizioni delle metriche.
L'API standard preferisce esporre i contatori totali piuttosto che le tariffe. Ciò significa che per ottenere la velocità corrispondente (ad esempio, la velocità in bit) come nell'API precedente, l'app deve calcolare la velocità media facendo il delta tra due chiamate getStats(). Ad esempio:

// 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;

Dover calcolare personalmente tariffe e medie in questo modo può sembrare un passaggio aggiuntivo gravoso, ma ha l'aspetto positivo di consentirti di ottenere le medie sull'intervallo di tempo desiderato. Chiamare l'API standard meno spesso di quanto avresti dovuto fare con l'API legacy offre alcuni vantaggi in termini di prestazioni.

Metrica precedente
googCertificate
Corrispondenza standard
certificate
.googFingerprint .fingerprint
.googFingerprintAlgorithm .fingerprintAlgorithm
.googDerBase64 .base64Certificate
Metrica precedente
googComponent
Corrispondenza standard
transport
.localCertificateId .localCertificateId
.remoteCertificateId .remoteCertificateId
.selectedCandidatePairId .selectedCandidatePairId
.dtlsCipher .dtlsCipher
.srtpCipher .srtpCipher
Metrica precedente
localcandidate
Corrispondenza standard
local-candidate o candidate-pair
.stunKeepaliveRequestsSent candidate-pair.requestsSent (ricerca inversa di candidate-pair tramite 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
Metrica precedente
remotecandidate
Corrispondenza standard
remote-candidate
Come localcandidate sopra. Come local-candidate sopra.
Metrica precedente
googCandidatePair
Corrispondenza standard
candidate-pair
.responsesSent candidate-pair.responsesSent
.requestsReceived candidate-pair.requestsReceived
.googRemoteCandidateType remote-candidate.candidateType
(ricerca remote-candidate tramite
candidate-pair.remoteCandidateId)
.googReadable googReadable è un valore booleano che riflette se di recente abbiamo incrementato o meno candidate-pair.requestsReceived o candidate-pair.responsesReceived
.googLocalAddress local-candidate.address
(ricerca local-candidate tramite
candidate-pair.localCandidateId)
.consentRequestsSent candidate-pair.consentRequestsSent
.googTransportType Uguale a local-candidate.protocol e remote-candidate.protocol.
.googChannelId candidate-pair.transportId
.googLocalCandidateType local-candidate.candidateType
.googWritable googWritable è un valore booleano che riflette se di recente abbiamo incrementato o meno candidate-pair.responsesReceived
.googRemoteAddress remote-candidate.address
.googRtt candidate-pair.currentRoundTripTime
.googActiveConnection La connessione attiva si riferisce alla coppia di candidati attualmente selezionata dal trasporto, ad esempio dove 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
Metrica precedente
ssrc
Corrispondenza standard
inbound-rtp, outbound-rtp, media-source
.audioInputLevel media-source.audioLevel. La metrica precedente è compresa nell'intervallo [0..32768], ma il metodo di misurazione standard è compreso nell'intervallo [0..1].
.audioOutputLevel
inbound-rtp.audioLevel. La metrica precedente è compresa nell'intervallo [0..32768], ma il metodo di misurazione standard è compreso nell'intervallo [0..1].
.packetsLost inbound-rtp.packetsLost
.googTrackId media-source.trackIdentifier per MediaStreamTrack locali e inbound-rtp.trackIdentifier per MediaStreamTrack remoti
.googRtt remote-inbound-rtp.roundTripTime (vedi outbound-rtp.remoteId)
.googEchoCancellationReturnLossEnhancement inbound-rtp.echoReturnLossEnhancement
.googCodecName Il nome del codec è il sottotipo del tipo MIME "type/subtype", codec.mimeType (vedi inbound-rtp.codecId e outbound-rtp.codecId).
.transportId inbound-rtp.transportId e outbound-rtp.transportId
.mediaType inbound-rtp.kind e outbound-rtp.kind o 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
Mentre l'FPS di invio è la frequenza di modifica di outbound-rtp.framesSent, in realtà viene implementato come outbound-rtp.framesPerSecond, che corrisponde alla codifica FPS.
.googFrameWidthReceived inbound-rtp.frameWidth
.googFrameHeightReceived inbound-rtp.frameHeight
.googFrameRateDecoded
Il tasso di variazione della metrica inbound-rtp.framesDecoded
.googFrameRateOutput
Tasso di variazione della metrica inbound-rtp.framesDecoded-inbound-rtp.framesDropped
.hugeFramesSent outbound-rtp.hugeFramesSent
.qpSum

inbound-rtp.qpSum e outbound-rtp.qpSum

.framesEncoded outbound-rtp.framesEncoded
.googAvgEncodeMs

outbound-rtp.totalEncodeTime/outbound-rtp.framesEncoded

.codecImplementationName

inbound-rtp.decoderImplementation e outbound-rtp.encoderImplementation

.googCpuLimitedResolution
Vero se outbound-rtp.qualityLimitationReason == "cpu"
.googBandwidthLimitedResolution
Vero se outbound-rtp.qualityLimitationReason == "bandwidth"
.googAdaptationChanges
La metrica precedente conteggia il numero di volte in cui la risoluzione o la frequenza fotogrammi sono cambiate per motivi correlati a qualityLimitationReason. Questo risultato potrebbe essere dedotto da altre metriche (ad es. la risoluzione di invio o la frequenza fotogrammi sono diverse dalla risoluzione di origine o dalla frequenza fotogrammi), ma la durata che abbiamo limitato, outbound-rtp.qualityLimitationDurations, potrebbe essere più utile rispetto alla frequenza con cui la risoluzione o la frequenza fotogrammi sono state modificate è stata riconfigurata.
.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
Il rapporto recente di pacchetti contenenti la correzione degli errori: 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
Il rapporto recente dei campioni nascosti: inbound-rtp.concealedSamples / inbound-rtp.totalSamplesReceived
.googSpeechExpandRate Il rapporto recente dei campioni nascosti mentre lo stream non era silenzioso: di (inbound-rtp.concealedSamples-inbound-rtp.silentConcealedSamples) / inbound-rtp.concealedSamples
.googAccelerateRate Il rapporto recente di campioni eliminati per accelerare la velocità dei playout: inbound-rtp.removedSamplesForAcceleration / inbound-rtp.totalSamplesReceived
.googPreemptiveExpandRate
Il rapporto recente di campioni sintetizzati per decelerare la velocità di playout: 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
L'unica metrica goog-metrica rimanente. inbound-rtp.googTimingFrameInfo
.framesDecoded inbound-rtp.framesDecoded
Metrica precedente
VideoBwe
Corrispondenza standard
outbound-rtp e candidate-pair
.googTargetEncBitrate
outbound-rtp.targetBitrate come valore istantaneo o outbound-rtp.totalEncodedBytesTarget / outbound-rtp.framesEncoded come media
.googActualEncBitrate I byte prodotti dall'encoder sono i byte del payload, escluse le ritrasmissioni: la velocità di variazione compresa tra outbound-rtp.bytesSent e outbound-rtp.retransmittedBytesSent.
.googBucketDelay outbound-rtp.totalPacketSendDelay/outbound-rtp.packetsSent
.googTransmitBitrate Il tasso di modifica di outbound-rtp.headerBytesSent + outbound-rtp.bytesSent per la velocità in bit dello stream per RTP, di candidate-pair.bytesSent per la velocità in bit del candidato per-ICE o di transport.bytesSent per la velocità in bit per trasporto
.googRetransmitBitrate L'intervallo di variazione di outbound-rtp.retransmittedBytesSent
.googAvailableSendBandwidth candidate-pair.availableOutgoingBitrate
.googAvailableReceiveBandwidth candidate-pair.availableIncomingBitrate

L'API standard è sensibile alla simulcast

Se utilizzi simulcast, potresti aver notato che l'API legacy segnala solo un singolo SSRC anche quando utilizzi questa modalità per inviare (ad esempio) tre stream RTP su tre SSRC separati.

L'API standard non condivide questa limitazione e restituisce tre oggetti statistiche outbound-rtp, uno per ciascuno degli SSRC. Ciò significa che puoi analizzare ogni singolo stream RTP, ma significa anche che per ottenere la velocità in bit totale di tutti gli stream di invio RTP dovrai aggregarli personalmente.

Gli stream SVC o RTP con più livelli spaziali configurati tramite l'API scalabilityMode vengono invece visualizzati come un singolo outbound-rtp perché vengono inviati tramite un singolo SSRC.

Se hai bisogno di più tempo per la migrazione

Quando l'API precedente viene rimossa in Chrome 117, il suo utilizzo genera un'eccezione. Se non riesci a eseguire la migrazione del codice in tempo, la prova dell'origine per l'API getStats() basata su callback RTCPeerConnection offre più tempo ai siti web registrati per eseguire la migrazione. Con un token di prova dell'origine, l'API getStats() precedente potrebbe continuare a essere utilizzata fino a Chrome 121.