WebRTC: 기존 getStats() 이전 가이드

Henrik Boström
Henrik Boström

기존 getStats() WebRTC API는 Chrome 117에서 삭제되므로 이를 사용하는 앱은 표준 API로 이전해야 합니다. 이 도움말에서는 코드를 이전하는 방법과 변경하는 데 시간이 더 필요한 경우 취해야 할 조치를 설명합니다.

지금까지 WebRTC getStats() API에는 두 가지 경쟁 버전이 있었습니다. 기존의 getStats() API는 표준화 프로세스를 더 일찍 만들고 콜백 인수를 사용하며 표준화되어 널리 지원되는 API로, 프로미스를 반환합니다.

표준 API는 기능이 더욱 풍부하며 W3C 사양 WebRTC Statistics API의 식별자에 공개적으로 문서화되어 있는 잘 정의된 측정항목이 있습니다. 사양에는 이 가이드에 나열된 각 측정항목에 대한 설명 및 기타 많은 항목이 포함되어 있습니다.

Chrome 117부터 기존 getStats() API가 안정화 버전 출시 채널에서 예외를 발생시킵니다 (예외 발생은 점진적으로 적용될 예정). 이 가이드를 따라 표준 API로 쉽게 전환하세요.

기존 통계 유형과 표준 통계 유형 비교

표준 통계 유형의 전체 목록은 사양의 RTCStatsType enum에서 확인할 수 있습니다. 여기에는 각 유형에 대해 수집된 측정항목을 설명하는 통계 사전 정의가 포함됩니다.

통계 객체에는 모두 여러 getStats() 호출에서 기본 객체를 고유하게 식별하는 id 속성이 있습니다. 동일한 객체는 메서드가 호출될 때마다 같은 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에 추가되었지만 해당하는 기존 유형이 없습니다.
  • codec: 현재 RTP 스트림에서 인코딩 또는 디코딩에 사용 중인 코덱입니다. SDP에서 협상된 코덱의 하위 집합입니다.
  • remote-inbound-rtp: 이 엔드포인트에서 전송하는 아웃바운드 RTP 스트림 (outbound-rtp)에 해당하는 원격 엔드포인트의 인바운드 RTP 스트림입니다. 원격 엔드포인트에서 측정되며 RTCP 수신자 보고서 (RR) 또는 RTCP 확장 보고서 (XR)로 보고됩니다.
  • remote-outbound-rtp: 이 엔드포인트가 수신하는 인바운드 RTP 스트림 (inbound-rtp)에 해당하는 원격 엔드포인트의 아웃바운드 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-candidate 또는 candidate-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.requestsReceived 또는 candidate-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-rtp, outbound-rtp, media-source
.audioInputLevel media-source.audioLevel. 기존 측정항목의 범위는 [0..32768] 이지만 표준 측정항목은 [0..1] 범위 내에 있습니다.
.audioOutputLevel
inbound-rtp.audioLevel 기존 측정항목의 범위는 [0..32768] 이지만 표준 측정항목은 [0..1] 범위 내에 있습니다.
.packetsLost inbound-rtp.packetsLost
.googTrackId 로컬 MediaStreamTrack의 경우 media-source.trackIdentifier, 원격 MediaStreamTrack의 경우 inbound-rtp.trackIdentifier
.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.kind 또는 media-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의 변화 속도이지만 실제로는 FPS를 인코딩하는 outbound-rtp.framesPerSecond로 구현됩니다.
.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는 동시캐스트를 인식합니다.

simulcast를 사용하는 경우, simulcast를 사용하여 3개의 별도 SSRC를 통해 세 개의 RTP 스트림을 전송하는 경우에도 기존 API는 단일 SSRC만 보고한다는 사실을 알 수 있습니다.

표준 API는 이 제한을 공유하지 않으며 각 SSRC마다 하나씩 총 3개의 outbound-rtp 통계 객체를 반환합니다. 즉, 각 RTP 스트림을 개별적으로 분석할 수 있지만 모든 RTP 전송 스트림의 전체 비트 전송률을 얻으려면 직접 집계해야 합니다.

반면에 scalabilityMode API를 통해 구성된 여러 공간 레이어가 있는 SVC 스트림 또는 RTP 스트림은 단일 SSRC를 통해 전송되므로 여전히 단일 outbound-rtp로 표시됩니다.

이전하는 데 시간이 더 필요한 경우

기존 API가 Chrome 117에서 삭제될 때 이를 사용하면 예외가 발생합니다. 코드를 제때 이전할 수 없는 경우 RTCPeerConnection 콜백 기반 getStats() API의 오리진 트라이얼을 사용하면 등록된 웹사이트에 더 오래 이전할 수 있습니다. 오리진 트라이얼 토큰을 사용하면 Chrome 121까지 기존 getStats() API를 계속 사용할 수 있습니다.