הממשק הקודם של getStats()
WebRTC API יוסר ב-Chrome בגרסה 117, ולכן אפליקציות שמשתמשות בו יצטרכו לעבור ל-API הסטנדרטי. במאמר הזה נסביר איך להעביר את הקוד ומה עושים אם נדרש לכם עוד זמן לביצוע השינוי הזה.
בעבר היו שתי גרסאות מתחרות של WebRTC getStats()
API. ה-API מהדור הקודם getStats() , קודם של תהליך הסטנדרטיזציה ופונקציית קריאה חוזרת (callback), וה-API הסטנדרטי והנתמך באופן נרחב שמחזיר הבטחה.
ה-API הסטנדרטי כולל מגוון רחב יותר של תכונות, ויש בו מדדים מוגדרים היטב המתועדים באופן ציבורי במפרט W3C מזהים עבור ממשק ה-API של סטטיסטיקות WebRTC. המפרט כולל תיאורים של כל מדד שמפורט במדריך הזה ושל מדדים רבים נוספים.
החל מגרסה 117 של Chrome, ה-API getStats()
הקודם ישיג חריגה בערוץ ההפצה היציבה (השלכת החריגה תושק בהדרגה). כדי להקל על המעבר ל-API הרגיל, מומלץ לעיין במדריך הזה.
סוגים קודמים של נתונים סטטיסטיים לעומת סוגים רגילים
הרשימה המלאה של סוגי הנתונים הסטטיסטיים הסטנדרטיים מופיעה במפרט של מספרי RTCStatsType במפרט. זה כולל הגדרה של מילון נתונים סטטיסטיים שמתארת את המדדים שנאספו עבור כל סוג.
לאובייקטים של הנתונים הסטטיסטיים יש מאפיין מזהה שמזהה באופן ייחודי את האובייקט הבסיסי בקריאות מרובות של getStats()
. לאותו אובייקט יהיה אותו מזהה בכל פעם שמפעילים את השיטה. אפשרות זו שימושית לחישוב שיעור השינוי של מדדים (ראו דוגמה בקטע הבא). המזהים גם יוצרים קשרים של קובצי עזר. לדוגמה, אובייקט הנתונים הסטטיסטיים outbound-rtp
מפנה לאובייקט הנתונים הסטטיסטיים המשויך של media-source
באמצעות המאפיין outbound-rtp.mediaSourceId
. אם משרטטים את כל קשרי הגומלין ...Id
, מתקבל תרשים.
ה-API מהדור הקודם כולל את סוגי הנתונים הסטטיסטיים הבאים, התואמים את הסוגים הסטנדרטיים באופן הבא:
סוג מדור קודם |
סוג סטנדרטי |
---|---|
ssrc
|
מייצג זרם RTP ומדדים לגבי MediaStreamTrack המשויך.הסוגים המקובלים של השיטה הזו הם inbound-rtp (לקבלת שידורים מסוג RTP והשלט הרחוק המשויך אליהם MediaStreamTrack ), outbound-rtp (לשליחת שידורי RTP) ו-media-source (למדדי MediaStreamTrack מקומיים המשויכים לשידור RTP). מדדי שידור RTP מכילים גם מידע על המקודד או המפענח שבו נעשה שימוש בשידור ה-RTP. |
VideoBwe
|
מדדים להערכת רוחב הפס, קצב העברת הנתונים של היעד, קצב העברת הנתונים של המקודד וקצב העברת הנתונים בפועל. סוגי המדדים האלה הם חלק ממדדי RTP ( outbound-rtp ו-inbound-rtp ) ומדדי צמדי מועמדי ICE (candidate-pair ). |
googComponent
|
מייצג את התעבורה (ICE ו-DTLS). הגרסה הרגילה היא transport . |
localcandidate and remotecandidate
|
מייצג/ת מועמד/ת ל-ICE. הגרסה הרגילה היא local-candidate ו-remote-candidate . |
googCandidatePair
|
ייצוג צמד של מועמד ICE, שהוא שילוב בין מועמד מקומי למועמד מרוחק. הגרסה הרגילה היא candidate-pair . |
googCertificate
|
מייצג אישור שמשמש את תעבורת ה-DTLS. הגרסה הרגילה היא certificate . |
googLibjingleSession
|
מייצג את RTCPeerConnection . התוכן שלו לא ממופה לאף כלל בתקן, אבל התקן משויך לסוג RTCPeerConnection : peer-connection . |
חסר ב-API הקודם |
סוגי הנתונים הסטטיסטיים האלה נוספו ל-API הרגיל שאין להם אף סוג קודם תואם:
|
מיפוי מדדים קודמים למדדים רגילים
המיפוי הזה נועד לעזור למפתחים למצוא איזה מדד מדור קודם תואם לכל מדד סטנדרטי. עם זאת, חשוב לזכור שהמדד המתאים עשוי להשתמש ביחידות שונות או להתבטא כמונה כולל במקום כערך מיידי. ההגדרות של המדדים מפורטות במפרט.
ב-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 דרך 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
|
מדד מדור קודם
remotecandidate |
תכתובת רגילה
remote-candidate |
---|---|
זהה ל-localcandidate שלמעלה. |
זהה ל-local-candidate שלמעלה. |
מדד מדור קודם
googCandidatePair |
תכתובת רגילה
candidate-pair |
---|---|
.responsesSent
|
candidate-pair.responsesSent
|
.requestsReceived
|
candidate-pair.requestsReceived
|
.googRemoteCandidateType
|
remote-candidate.candidateType (חיפוש remote-candidate דרך candidate-pair.remoteCandidateId ) |
.googReadable
|
googReadable הוא בוליאני שמשקף אם הוספנו או לא הגדלנו לאחרונה את candidate-pair.requestsReceived או candidate-pair.responsesReceived
|
.googLocalAddress
|
local-candidate.address (חיפוש local-candidate דרך candidate-pair.localCandidateId ) |
.consentRequestsSent
|
candidate-pair.consentRequestsSent
|
.googTransportType
|
בדיוק כמו local-candidate.protocol ו-remote-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
|
media-source.trackIdentifier ל-MediaStreamTrack מקומיים ו-inbound-rtp.trackIdentifier ל-MediaStreamTrack מרחוק |
.googRtt
|
remote-inbound-rtp.roundTripTime (מידע נוסף זמין בכתובת outbound-rtp.remoteId ) |
.googEchoCancellationReturnLossEnhancement
|
inbound-rtp.echoReturnLossEnhancement
|
.googCodecName
|
שם הקודק הוא סוג המשנה של סוג ה-mime 'סוג/סוג משנה' codec.mimeType (פרטים נוספים זמינים ב-inbound-rtp.codecId וב-outbound-rtp.codecId ) |
.transportId
|
inbound-rtp.transportId וגם outbound-rtp.transportId |
.mediaType
|
inbound-rtp.kind , גם outbound-rtp.kind או media-source.kind
|
.googEchoCancellationReturnLoss
|
inbound-rtp.echoReturnLoss
|
.totalAudioEnergy
|
inbound-rtp.totalAudioEnergy וגם media-source.totalAudioEnergy
|
ssrc.totalSamplesDuration
|
inbound-rtp.totalSamplesDuration וגם media-source.totalSamplesDuration
|
.ssrc
|
inbound-rtp.ssrc וגם outbound-rtp.ssrc
|
.googJitterReceived
|
inbound-rtp.jitter
|
.packetsSent
|
outbound-rtp.packetsSent
|
.bytesSent
|
outbound-rtp.bytesSent
|
.googContentType
|
inbound-rtp.contentType וגם outbound-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 , אבל בפועל הוא מיושם בתור outbound-rtp.framesPerSecond , כלומר הקידוד של FPS. |
.googFrameWidthReceived
|
inbound-rtp.frameWidth
|
.googFrameHeightReceived
|
inbound-rtp.frameHeight
|
.googFrameRateDecoded
|
שיעור השינוי של inbound-rtp.framesDecoded |
.googFrameRateOutput
|
שיעור השינוי של inbound-rtp.framesDecoded – inbound-rtp.framesDropped |
.hugeFramesSent
|
outbound-rtp.hugeFramesSent
|
.qpSum
|
|
.framesEncoded
|
outbound-rtp.framesEncoded
|
.googAvgEncodeMs
|
|
.codecImplementationName
|
|
.googCpuLimitedResolution
|
True אם outbound-rtp.qualityLimitationReason == "cpu" |
.googBandwidthLimitedResolution
|
True אם outbound-rtp.qualityLimitationReason == "bandwidth" |
.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. inbound-rtp.googTimingFrameInfo |
.framesDecoded
|
inbound-rtp.framesDecoded
|
מדד מדור קודם
VideoBwe |
תכתובת סטנדרטית
outbound-rtp ו-candidate-pair |
---|---|
.googTargetEncBitrate
|
outbound-rtp.targetBitrate כערך מיידי או outbound-rtp.totalEncodedBytesTarget / outbound-rtp.framesEncoded בממוצע |
.googActualEncBitrate
|
הבייטים שהמקודד מפיק הם הבייטים של המטען הייעודי (payload), לא כולל העברות חוזרות: קצב השינוי של outbound-rtp.bytesSent - outbound-rtp.retransmittedBytesSent |
.googBucketDelay
|
outbound-rtp.totalPacketSendDelay / outbound-rtp.packetsSent
|
.googTransmitBitrate
|
קצב השינוי של outbound-rtp.headerBytesSent + outbound-rtp.bytesSent עבור קצב העברת הנתונים של שידור RTP, candidate-pair.bytesSent עבור קצב העברת הנתונים של מועמד ל-ICE, או transport.bytesSent עבור קצב העברת הנתונים לכל העברה |
.googRetransmitBitrate
|
טווח השינוי של outbound-rtp.retransmittedBytesSent |
.googAvailableSendBandwidth
|
candidate-pair.availableOutgoingBitrate
|
.googAvailableReceiveBandwidth
|
candidate-pair.availableIncomingBitrate
|
ה-API הסטנדרטי מבוסס-Simulcast
אם אתם משתמשים בסימולציה, ייתכן שהבחנתם שה-API מהדור הקודם מדווח רק על SSRC אחד, גם אם אתם משתמשים בסימולציה כדי לשלוח (לדוגמה) שלושה שידורי RTP בשלושה קודי SSRC נפרדים.
ה-API הסטנדרטי לא משתף את המגבלה הזו ויחזיר שלושה אובייקטים של נתונים סטטיסטיים מסוג outbound-rtp
, אחד לכל אחד מקודי ה-SSRC. המשמעות היא שאפשר לנתח כל שידור RTP בנפרד, אבל המשמעות היא גם שכדי להשיג את קצב העברת הנתונים הכולל של כל שידורי ה-RTP, תצטרכו לצבור אותם בעצמכם.
מצד שני, שידורי SVC או שידורי RTP עם שכבות מרחביות מרובות שהוגדרו באמצעות ה-API scalabilityMode
עדיין מופיעים כ-outbound-rtp
יחיד כי הם נשלחים באמצעות SSRC אחד.
אם נדרש לכם עוד זמן להעברה
כשמסירים את ה-API מהדור הקודם מ-Chrome 117, השימוש בו יוצר חריג. אם אתם לא מצליחים להעביר את הקוד בזמן, גרסת המקור לניסיון של RTCPeerConnection API מבוסס קריאה חוזרת (callback) שמבוססת על getStats() תיתן לאתרים רשומים יותר זמן להעברה. עם אסימון מקור לניסיון, ניתן להמשיך להשתמש ב-getStats() API מהדור הקודם עד Chrome 121.