WebRTC: دليل نقل بيانات getStats() القديم

Henrik Boström
Henrik Boström

ستتم إزالة واجهة برمجة التطبيقات getStats() WebRTC API القديمة في الإصدار 117 من Chrome، لذا على التطبيقات التي تستخدمها نقل بياناتها إلى واجهة برمجة التطبيقات العادية. توضّح هذه المقالة كيفية نقل الرمز البرمجي، وما يجب فعله إذا كنت بحاجة إلى مزيد من الوقت لإجراء هذا التغيير.

في السابق، كان هناك إصداران متنافسان من واجهة برمجة التطبيقات WebRTC getStats(). واجهة برمجة التطبيقات القديمة getStats()‎ التي تعود إلى ما قبل عملية وضع المعايير وتستخدِم مَعلمة لإجراء معاودة الاتصال، وواجهة برمجة التطبيقات المتوافقة على نطاق واسع والمتوافقة مع المعايير والتي تعرض وعدًا

توفّر واجهة برمجة التطبيقات العادية ميزات أكثر، كما تتضمّن مقاييس محدّدة جيدًا وموثّقة بشكل علني في مواصفات W3C المعرّفات لواجهة برمجة تطبيقات إحصاءات WebRTC. تتضمّن المواصفة أوصافًا لكل مقياس مُدرَج في هذا الدليل وغيرها الكثير.

اعتبارًا من الإصدار 117 من Chrome، ستُعرِض واجهة برمجة التطبيقات getStats() القديمة استثناءً في قناة الإصدار الثابت (سيتم طرح الاستثناء تدريجيًا). اتّبِع هذا الدليل لتسهيل عملية الانتقال إلى واجهة برمجة التطبيقات العادية.

أنواع الإحصاءات القديمة مقابل أنواع الإحصاءات العادية

يمكن العثور على القائمة الكاملة بأنواع الإحصاءات العادية من خلال الاطّلاع على التعداد RTCStatsType في المواصفات. ويشمل ذلك تعريف قاموس الإحصاءات الذي يصف المقاييس التي يتم جمعها لكل نوع.

تحتوي جميع عناصر الإحصاءات على سمة id التي تحدّد العنصر الأساسي بشكل فريد في طلبات getStats() المتعددة. سيحتوي العنصر نفسه على المعرّف نفسه في كل مرة يتم فيها استدعاء الطريقة. وهذا مفيد لاحتساب معدّل تغيُّر المقاييس (يتوفر مثال في القسم التالي). تشكل الأرقام التعريفية أيضًا علاقات بين المراجع. على سبيل المثال، يشير عنصر الإحصاءات outbound-rtp إلى عنصر الإحصاءات media-source المرتبط به من خلال السمة outbound-rtp.mediaSourceId. إذا رسمت جميع علاقات ...Id، ستحصل على رسم بياني.

تتضمّن واجهة برمجة التطبيقات القديمة أنواع الإحصاءات التالية، والتي تتوافق مع الأنواع العادية على النحو التالي:


النوع القديم

النوع العادي
ssrc
يمثّل بثًا عبر بروتوكول RTP ومقاييس عن MediaStreamTrack المرتبط به.


الأنواع العادية لهذا النوع هي inbound-rtp (لتلقّي أحداث بث بروتوكول RTP والمقاييس البعيدة المرتبطة بها MediaStreamTrack)، وoutbound-rtp (لإرسال أحداث بث بروتوكول RTP) وmedia-source (لمقاييس MediaStreamTrack المحلية المرتبطة ببث بروتوكول RTP). تحتوي مقاييس مصادر بيانات RTP أيضًا على معلومات عن برنامج الترميز أو فك الترميز المستخدَمَين في مصدر بيانات RTP.
VideoBwe
مقاييس تقدير معدل نقل البيانات ومعدل نقل البيانات المستهدَف ومعدل نقل البيانات في برنامج الترميز ومعدل نقل البيانات الفعلي تشكّل هذه الأنواع من المقاييس جزءًا من مقاييس بروتوكول النقل في الوقت الفعلي (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.

غير متوفّر في واجهة برمجة التطبيقات القديمة

تمّت إضافة أنواع الإحصاءات هذه إلى واجهة برمجة التطبيقات العادية التي لا تتضمّن أيّ نوع قديم مناظر:
  • codec: برنامج ترميز يتم استخدامه حاليًا من خلال بث RTP، إما للترميز أو فك التشفير. هذه مجموعة فرعية من برامج الترميز التي تم التفاوض عليها في ملف وصف الجلسة.
  • remote-inbound-rtp: بثّ RTP وارد من نقطة نهاية عن بُعد يتوافق مع بثّ RTP صادر ترسله نقطة النهاية هذه (outbound-rtp). ويتم قياسه في نقطة النهاية البعيدة ويتم الإبلاغ عنه في تقرير مستلِم RTCP (RR) أو تقرير RTCP الموسّع (XR).
  • remote-outbound-rtp: بث RTP ناتج من نقطة نهاية عن بُعد يتوافق مع بث RTP وارد تتلقّاه نقطة النهاية هذه (inbound-rtp). ويتم قياسه في نقطة النهاية البعيدة ويتم تسجيله في تقرير مُرسِل RTCP (SR).
  • media-playout: مقاييس حول تشغيل MediaStreamTrack عن بُعد مرتبط ببث RTP وارد (inbound-rtp).
  • data-channel: يمثّل RTCDataChannel.

ربط المقاييس القديمة بالمقاييس العادية

يهدف هذا الربط إلى مساعدة المطوّرين في العثور على المقياس القديم الذي يتوافق مع المقياس العادي، ولكن يُرجى العِلم أنّ المقياس المقابل قد يستخدم وحدات مختلفة أو يتم التعبير عنه كعداد إجمالي بدلاً من قيمة فورية. يُرجى الرجوع إلى المواصفات لمعرفة تعريفات المقاييس.
تفضّل واجهة برمجة التطبيقات العادية عرض إجمالي العدّادات بدلاً من المعدّلات. وهذا يعني أنّه للحصول على معدّل البث المقابل (مثل معدل نقل البيانات) كما هو الحال في واجهة برمجة التطبيقات القديمة، على التطبيق احتساب متوسّط معدّل البث من خلال احتساب الفرق بين طلبَي 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;

قد يبدو لك أنّ احتساب الأسعار والمتوسّطات بنفسك بهذه الطريقة هو خطوة إضافية مزعجة، ولكنّ لها ميزة تتيح لك الحصول على متوسّطات خلال أيّ فاصل زمني مطلوب. إنّ استدعاء واجهة برمجة التطبيقات العادية بمعدّل أقلّ من معدّل استدعاء واجهة برمجة التطبيقات القديمة قد يحقّق بعض المزايا في الأداء.

المقياس القديم
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 "type/subtype"، 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
على الرغم من أنّ عدد اللقطات في الثانية المُرسَلة هو معدّل تغيير outbound-rtp.framesSent، يتم تنفيذ ذلك في الواقع على أنّه 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.qpSum وoutbound-rtp.qpSum

.framesEncoded outbound-rtp.framesEncoded
.googAvgEncodeMs

outbound-rtp.totalEncodeTime / outbound-rtp.framesEncoded

.codecImplementationName

inbound-rtp.decoderImplementation وoutbound-rtp.encoderImplementation

.googCpuLimitedResolution
صحيح إذا outbound-rtp.qualityLimitationReason == "cpu"
.googBandwidthLimitedResolution
صحيح إذا 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
مقياس Google الوحيد المتبقّي. inbound-rtp.googTimingFrameInfo
.framesDecoded inbound-rtp.framesDecoded
المقياس القديم
VideoBwe
المراسلات العادية
outbound-rtp وcandidate-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 معدّل تغيير 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

واجهة برمجة التطبيقات العادية متوافقة مع البث المباشر المتزامن

في حال استخدام البث المتزامن، قد تلاحظ أنّ واجهة برمجة التطبيقات القديمة لا تسجِّل سوى مصدر مسؤولية بث واحد حتى في حال استخدام البث المتزامن لإرسال (على سبيل المثال) ثلاثة أحداث بث RTP عبر ثلاثة مصادر مسؤولية بث منفصلة.

لا تفرض واجهة برمجة التطبيقات العادية هذا القيد، وستُرجع ثلاثة عناصر إحصاءات outbound-rtp، واحد لكلّ من معرّفات SSRC. وهذا يعني أنّه يمكنك تحليل كلّ بثّ RTP بشكلٍ فردي، ولكنّه يعني أيضًا أنّه للحصول على إجمالي معدّل نقل البيانات لجميع أحداث إرسال RTP، عليك تجميعها بنفسك.

من ناحية أخرى، لا تزال أحداث بث SVC أو أحداث بث RTP التي تتضمّن عدة طبقات مكانية تم ضبطها من خلال واجهة برمجة التطبيقات scalabilityMode تظهر كحدث بث outbound-rtp واحد لأنّه يتم إرسالها عبر مصدر مسؤولية بث واحد.

إذا كنت بحاجة إلى مزيد من الوقت لنقل البيانات

عند إزالة واجهة برمجة التطبيقات القديمة في الإصدار 117 من Chrome، سيؤدي استخدامها إلى حدوث استثناء. إذا لم تتمكّن من نقل الرمز في الوقت المناسب، تمنحك فترة تجريبية لمصدر واجهة برمجة التطبيقات getStats()‎ المستندة إلى طلب إعادة الاتصال RTCPeerConnection المزيد من الوقت لنقل البيانات إلى الإصدار الجديد. باستخدام رمز مميّز لمرحلة التجربة والتقييم، يمكن مواصلة استخدام واجهة برمجة التطبيقات القديمة getStats()‎ حتى الإصدار 121 من Chrome.