From b25e9cf466e3b30a92bd610b8f1ace5c61f53184 Mon Sep 17 00:00:00 2001 From: "Eswar Prasad Clinton. A" <64120992+eswarclynn@users.noreply.github.com> Date: Tue, 12 Mar 2024 18:08:24 +0530 Subject: [PATCH] fix: calcuating difference average, av sync and remove unnecessary fields for subscriber stats sample --- .../src/analytics/stats/BaseStatsAnalytics.ts | 4 ++- .../stats/SubscribeStatsAnalytics.ts | 25 +++++++++++++------ .../src/interfaces/webrtc-stats.ts | 1 + 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/hms-video-store/src/analytics/stats/BaseStatsAnalytics.ts b/packages/hms-video-store/src/analytics/stats/BaseStatsAnalytics.ts index 179815a397..b0d16adb0c 100644 --- a/packages/hms-video-store/src/analytics/stats/BaseStatsAnalytics.ts +++ b/packages/hms-video-store/src/analytics/stats/BaseStatsAnalytics.ts @@ -85,6 +85,7 @@ export abstract class RunningTrackAnalytics { protected samples: (LocalBaseSample | LocalVideoSample | RemoteAudioSample | RemoteVideoSample)[] = []; protected tempStats: TempPublishStats[] = []; + protected prevLatestStat?: TempPublishStats; constructor({ track, @@ -118,6 +119,7 @@ export abstract class RunningTrackAnalytics { } this.samples.push(this.collateSample()); + this.prevLatestStat = this.getLatestStat(); this.tempStats.length = 0; } @@ -160,7 +162,7 @@ export abstract class RunningTrackAnalytics { } protected calculateDifferenceForSample(key: keyof TempPublishStats) { - const firstValue = Number(this.tempStats[0][key]) || 0; + const firstValue = Number(this.prevLatestStat?.[key]) || 0; const latestValue = Number(this.getLatestStat()[key]) || 0; return latestValue - firstValue; diff --git a/packages/hms-video-store/src/analytics/stats/SubscribeStatsAnalytics.ts b/packages/hms-video-store/src/analytics/stats/SubscribeStatsAnalytics.ts index 5c44720388..1ca7567d5f 100644 --- a/packages/hms-video-store/src/analytics/stats/SubscribeStatsAnalytics.ts +++ b/packages/hms-video-store/src/analytics/stats/SubscribeStatsAnalytics.ts @@ -92,12 +92,16 @@ export class SubscribeStatsAnalytics extends BaseStatsAnalytics { // eslint-disable-next-line complexity private calculateAvSyncForStat(trackStats: HMSTrackStats, hmsStats: HMSWebrtcStats) { - if (!trackStats.peerID || !(trackStats.kind === 'video')) { + if (!trackStats.peerID || !trackStats.estimatedPlayoutTimestamp || trackStats.kind !== 'video') { return; } const peer = this.store.getPeerById(trackStats.peerID); const audioTrack = peer?.audioTrack; const videoTrack = peer?.videoTrack; + /** + * 1. Send value as MAX_SAFE_INTEGER when either audio or value track is muted for the entire window + * 2. When both audio and video are unmuted for a part of window , then divide the difference by those many number of samples only + */ const areBothTracksEnabled = audioTrack && videoTrack && audioTrack.enabled && videoTrack.enabled; if (!areBothTracksEnabled) { return MAX_SAFE_INTEGER; @@ -106,7 +110,12 @@ export class SubscribeStatsAnalytics extends BaseStatsAnalytics { if (!audioStats) { return MAX_SAFE_INTEGER; } - return audioStats.timestamp - trackStats.timestamp; + if (!audioStats.estimatedPlayoutTimestamp) { + return; + } + + // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-estimatedplayouttimestamp + return audioStats.estimatedPlayoutTimestamp - trackStats.estimatedPlayoutTimestamp; } } @@ -119,14 +128,9 @@ class RunningRemoteTrackAnalytics extends RunningTrackAnalytics { const baseSample = { timestamp: Date.now(), - fec_packets_discarded: this.calculateDifferenceForSample('fecPacketsDiscarded'), - fec_packets_received: this.calculateDifferenceForSample('fecPacketsReceived'), - total_samples_duration: this.calculateDifferenceForSample('totalSamplesDuration'), - total_packets_received: this.calculateDifferenceForSample('packetsReceived'), - total_packets_lost: this.calculateDifferenceForSample('packetsLost'), total_pli_count: this.calculateDifferenceForSample('pliCount'), total_nack_count: this.calculateDifferenceForSample('nackCount'), - avg_jitter_buffer_delay: this.calculateAverage('calculatedJitterBufferDelay'), + avg_jitter_buffer_delay: this.calculateAverage('calculatedJitterBufferDelay', false), }; if (latestStat.kind === 'video') { @@ -155,6 +159,11 @@ class RunningRemoteTrackAnalytics extends RunningTrackAnalytics { audio_concealed_samples, audio_total_samples_received: this.calculateDifferenceForSample('totalSamplesReceived'), audio_concealment_events: this.calculateDifferenceForSample('concealmentEvents'), + fec_packets_discarded: this.calculateDifferenceForSample('fecPacketsDiscarded'), + fec_packets_received: this.calculateDifferenceForSample('fecPacketsReceived'), + total_samples_duration: this.calculateDifferenceForSample('totalSamplesDuration'), + total_packets_received: this.calculateDifferenceForSample('packetsReceived'), + total_packets_lost: this.calculateDifferenceForSample('packetsLost'), }); } }; diff --git a/packages/hms-video-store/src/interfaces/webrtc-stats.ts b/packages/hms-video-store/src/interfaces/webrtc-stats.ts index edcf6452d5..05d5613e25 100644 --- a/packages/hms-video-store/src/interfaces/webrtc-stats.ts +++ b/packages/hms-video-store/src/interfaces/webrtc-stats.ts @@ -57,6 +57,7 @@ export interface MissingInboundStats extends RTCInboundRtpStreamStats, MissingCo totalFreezesDuration?: number; jitterBufferDelay?: number; jitterBufferEmittedCount?: number; + estimatedPlayoutTimestamp?: DOMHighResTimeStamp; } export type PeerConnectionType = 'publish' | 'subscribe';