@observertc/observer-js 0.40.6-beta → 0.40.7-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,14 +21,16 @@ export type ObservedInboundTrackStats<K extends MediaKind> = ObservedInboundTrac
21
21
  bitrate: number;
22
22
  fractionLost: number;
23
23
  rttInMs?: number;
24
- lostPackets?: number;
25
- receivedPackets?: number;
26
- receivedFrames?: number;
27
- decodedFrames?: number;
28
- droppedFrames?: number;
29
- receivedSamples?: number;
30
- silentConcealedSamples?: number;
24
+ deltaReceivedBytes?: number;
25
+ deltaLostPackets?: number;
26
+ deltaReceivedPackets?: number;
27
+ deltaReceivedFrames?: number;
28
+ deltaDecodedFrames?: number;
29
+ deltaDroppedFrames?: number;
30
+ deltaReceivedSamples?: number;
31
+ deltaSilentConcealedSamples?: number;
31
32
  fractionLoss?: number;
33
+ statsTimestamp: number;
32
34
  };
33
35
  export declare interface ObservedInboundTrack<Kind extends MediaKind> {
34
36
  on<U extends keyof ObservedInboundTrackEvents<Kind>>(event: U, listener: (...args: ObservedInboundTrackEvents<Kind>[U]) => void): this;
@@ -45,6 +47,7 @@ export declare class ObservedInboundTrack<Kind extends MediaKind> extends EventE
45
47
  private _closed;
46
48
  private _updated;
47
49
  private _remoteOutboundTrack?;
50
+ private _lastMaxStatsTimestamp;
48
51
  bitrate: number;
49
52
  rttInMs?: number;
50
53
  fractionLoss: number;
@@ -83,6 +86,6 @@ export declare class ObservedInboundTrack<Kind extends MediaKind> extends EventE
83
86
  get remoteOutboundTrack(): ObservedOutboundTrack<Kind> | undefined;
84
87
  get closed(): boolean;
85
88
  close(): void;
86
- resetMetrics(): void;
89
+ updateMetrics(): void;
87
90
  }
88
91
  //# sourceMappingURL=ObservedInboundTrack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedInboundTrack.d.ts","sourceRoot":"","sources":["../src/ObservedInboundTrack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ObservedInboundTrack.d.ts","sourceRoot":"","sources":["../src/ObservedInboundTrack.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ class ObservedInboundTrack extends events_1.EventEmitter {
11
11
  this._stats = new Map();
12
12
  this._closed = false;
13
13
  this._updated = Date.now();
14
+ this._lastMaxStatsTimestamp = 0;
14
15
  this.bitrate = 0;
15
16
  this.fractionLoss = 0;
16
17
  this.totalLostPackets = 0;
@@ -95,24 +96,12 @@ class ObservedInboundTrack extends events_1.EventEmitter {
95
96
  this._closed = true;
96
97
  this.emit('close');
97
98
  }
98
- resetMetrics() {
99
- this.bitrate = 0;
100
- this.rttInMs = undefined;
101
- this.deltaBytesReceived = 0;
102
- this.deltaLostPackets = 0;
103
- this.deltaReceivedFrames = 0;
104
- this.deltaDecodedFrames = 0;
105
- this.deltaDroppedFrames = 0;
106
- this.deltaReceivedSamples = 0;
107
- this.deltaSilentConcealedSamples = 0;
108
- this.fractionLoss = 0;
109
- }
110
- update(sample, timestamp) {
99
+ update(sample, statsTimestamp) {
111
100
  var _a, _b, _c, _d, _e;
112
101
  if (this._closed)
113
102
  return;
114
103
  const now = Date.now();
115
- const report = Object.assign(Object.assign({ serviceId: this.peerConnection.client.call.serviceId, roomId: this.peerConnection.client.call.roomId, callId: this.peerConnection.client.call.callId, clientId: this.peerConnection.client.clientId, userId: this.peerConnection.client.userId, mediaUnitId: this.peerConnection.client.mediaUnitId, peerConnectionId: this.peerConnection.peerConnectionId }, sample), { timestamp, sampleSeq: -1, remoteClientId: (_a = sample.remoteClientId) !== null && _a !== void 0 ? _a : (_b = this.remoteOutboundTrack) === null || _b === void 0 ? void 0 : _b.peerConnection.client.clientId, remoteUserId: (_c = this.remoteOutboundTrack) === null || _c === void 0 ? void 0 : _c.peerConnection.client.userId, remoteTrackId: (_d = this.remoteOutboundTrack) === null || _d === void 0 ? void 0 : _d.trackId, remotePeerConnectionId: (_e = this.remoteOutboundTrack) === null || _e === void 0 ? void 0 : _e.peerConnection.peerConnectionId, marker: this.marker });
104
+ const report = Object.assign(Object.assign({ serviceId: this.peerConnection.client.call.serviceId, roomId: this.peerConnection.client.call.roomId, callId: this.peerConnection.client.call.callId, clientId: this.peerConnection.client.clientId, userId: this.peerConnection.client.userId, mediaUnitId: this.peerConnection.client.mediaUnitId, peerConnectionId: this.peerConnection.peerConnectionId }, sample), { timestamp: statsTimestamp, sampleSeq: -1, remoteClientId: (_a = sample.remoteClientId) !== null && _a !== void 0 ? _a : (_b = this.remoteOutboundTrack) === null || _b === void 0 ? void 0 : _b.peerConnection.client.clientId, remoteUserId: (_c = this.remoteOutboundTrack) === null || _c === void 0 ? void 0 : _c.peerConnection.client.userId, remoteTrackId: (_d = this.remoteOutboundTrack) === null || _d === void 0 ? void 0 : _d.trackId, remotePeerConnectionId: (_e = this.remoteOutboundTrack) === null || _e === void 0 ? void 0 : _e.peerConnection.peerConnectionId, marker: this.marker });
116
105
  if (this.kind === 'audio')
117
106
  this.reports.addInboundAudioTrackReport(report);
118
107
  else if (this.kind === 'video')
@@ -127,75 +116,103 @@ class ObservedInboundTrack extends events_1.EventEmitter {
127
116
  const lastStat = this._stats.get(sample.ssrc);
128
117
  const rttInMs = sample.roundTripTime ? sample.roundTripTime * 1000 : undefined;
129
118
  let bitrate = 0;
119
+ let deltaReceivedBytes = 0;
130
120
  let fractionLost = 0;
131
- let lostPackets = 0;
132
- let receivedPackets = 0;
121
+ let deltaLostPackets = 0;
122
+ let deltaReceivedPackets = 0;
133
123
  if ((lastStat === null || lastStat === void 0 ? void 0 : lastStat.bytesReceived) && sample.bytesReceived && lastStat.bytesReceived < sample.bytesReceived) {
134
- bitrate = (sample.bytesReceived - lastStat.bytesReceived) / (elapsedTimeInMs / 1000);
124
+ deltaReceivedBytes = sample.bytesReceived - lastStat.bytesReceived;
125
+ bitrate = deltaReceivedBytes / (elapsedTimeInMs / 1000);
135
126
  }
136
127
  if ((lastStat === null || lastStat === void 0 ? void 0 : lastStat.packetsReceived) && (sample === null || sample === void 0 ? void 0 : sample.packetsReceived) && lastStat.packetsReceived < sample.packetsReceived) {
137
- receivedPackets = sample.packetsReceived - lastStat.packetsReceived;
128
+ deltaReceivedPackets = sample.packetsReceived - lastStat.packetsReceived;
138
129
  }
139
130
  if ((lastStat === null || lastStat === void 0 ? void 0 : lastStat.packetsLost) && sample.packetsLost && lastStat.packetsLost < sample.packetsLost) {
140
- lostPackets = sample.packetsLost - lastStat.packetsLost;
141
- if (0 < receivedPackets) {
142
- fractionLost = lostPackets / (receivedPackets + lostPackets);
131
+ deltaLostPackets = sample.packetsLost - lastStat.packetsLost;
132
+ if (0 < deltaReceivedPackets) {
133
+ fractionLost = deltaLostPackets / (deltaReceivedPackets + deltaLostPackets);
143
134
  }
144
135
  }
145
- let decodedFrames;
146
- let droppedFrames;
147
- let receivedFrames;
148
- let silentConcealedSamples;
136
+ let deltaDecodedFrames;
137
+ let deltaDroppedFrames;
138
+ let deltaReceivedFrames;
139
+ let deltaSilentConcealedSamples;
149
140
  if (this.kind === 'video') {
150
141
  const videoSample = sample;
151
142
  const lastVideoStat = lastStat;
152
143
  if (videoSample.framesDecoded && (lastVideoStat === null || lastVideoStat === void 0 ? void 0 : lastVideoStat.framesDecoded) && lastVideoStat.framesDecoded < videoSample.framesDecoded) {
153
- decodedFrames = videoSample.framesDecoded - lastVideoStat.framesDecoded;
144
+ deltaDecodedFrames = videoSample.framesDecoded - lastVideoStat.framesDecoded;
154
145
  }
155
146
  if (videoSample.framesDropped && (lastVideoStat === null || lastVideoStat === void 0 ? void 0 : lastVideoStat.framesDropped) && lastVideoStat.framesDropped < videoSample.framesDropped) {
156
- droppedFrames = videoSample.framesDropped - lastVideoStat.framesDropped;
147
+ deltaDroppedFrames = videoSample.framesDropped - lastVideoStat.framesDropped;
157
148
  }
158
149
  if (videoSample.framesReceived && (lastVideoStat === null || lastVideoStat === void 0 ? void 0 : lastVideoStat.framesReceived) && lastVideoStat.framesReceived < videoSample.framesReceived) {
159
- receivedFrames = videoSample.framesReceived - lastVideoStat.framesReceived;
150
+ deltaReceivedFrames = videoSample.framesReceived - lastVideoStat.framesReceived;
160
151
  }
161
152
  }
162
153
  else if (this.kind === 'audio') {
163
154
  const audioSample = sample;
164
155
  const lastAudioStat = lastStat;
165
156
  if (audioSample.silentConcealedSamples && (lastAudioStat === null || lastAudioStat === void 0 ? void 0 : lastAudioStat.silentConcealedSamples) && lastAudioStat.silentConcealedSamples < audioSample.silentConcealedSamples) {
166
- silentConcealedSamples = audioSample.silentConcealedSamples - lastAudioStat.silentConcealedSamples;
157
+ deltaSilentConcealedSamples = audioSample.silentConcealedSamples - lastAudioStat.silentConcealedSamples;
167
158
  }
168
159
  }
169
160
  const stats = Object.assign(Object.assign({}, sample), { fractionLost,
170
161
  rttInMs,
171
- bitrate, ssrc: sample.ssrc, lostPackets,
172
- receivedPackets,
173
- receivedFrames,
174
- decodedFrames,
175
- droppedFrames,
176
- silentConcealedSamples });
162
+ bitrate, ssrc: sample.ssrc, deltaReceivedBytes,
163
+ deltaLostPackets,
164
+ deltaReceivedPackets,
165
+ deltaReceivedFrames,
166
+ deltaDecodedFrames,
167
+ deltaDroppedFrames,
168
+ deltaSilentConcealedSamples,
169
+ statsTimestamp });
177
170
  this._stats.set(sample.ssrc, stats);
178
- this.bitrate = [...this._stats.values()].reduce((acc, stat) => acc + stat.bitrate, 0);
179
- this.rttInMs = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.rttInMs) !== null && _a !== void 0 ? _a : 0); }, 0) / (this._stats.size || 1);
180
- this.totalLostPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.lostPackets) !== null && _a !== void 0 ? _a : 0); }, 0);
181
- this.totalReceivedPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.receivedPackets) !== null && _a !== void 0 ? _a : 0); }, 0);
182
- this.totalBytesReceived = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.bytesReceived) !== null && _a !== void 0 ? _a : 0); }, 0);
183
- this.totalReceivedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.receivedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
184
- this.totalDecodedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.decodedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
185
- this.totalDroppedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.droppedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
186
- this.totalReceivedSamples = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.receivedSamples) !== null && _a !== void 0 ? _a : 0); }, 0);
187
- this.totalSilentConcealedSamples = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.silentConcealedSamples) !== null && _a !== void 0 ? _a : 0); }, 0);
188
- this.deltaLostPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.lostPackets) !== null && _a !== void 0 ? _a : 0); }, 0);
189
- this.deltaReceivedPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.receivedPackets) !== null && _a !== void 0 ? _a : 0); }, 0);
190
- this.deltaBytesReceived = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.bytesReceived) !== null && _a !== void 0 ? _a : 0); }, 0);
191
- this.deltaReceivedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.receivedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
192
- this.deltaDecodedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.decodedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
193
- this.deltaDroppedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.droppedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
194
- this.deltaReceivedSamples = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.receivedSamples) !== null && _a !== void 0 ? _a : 0); }, 0);
195
- this.deltaSilentConcealedSamples = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.silentConcealedSamples) !== null && _a !== void 0 ? _a : 0); }, 0);
196
- this.fractionLoss = 0 < this.deltaReceivedPackets && 0 < this.deltaLostPackets ? (this.deltaLostPackets / (this.deltaReceivedPackets + this.deltaLostPackets)) : 0;
197
171
  this._updated = now;
198
172
  this.emit('update');
199
173
  }
174
+ updateMetrics() {
175
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
176
+ let maxStatsTimestamp = 0;
177
+ let rttInMsSum = 0;
178
+ let size = 0;
179
+ this.bitrate = 0;
180
+ this.rttInMs = undefined;
181
+ this.deltaBytesReceived = 0;
182
+ this.deltaLostPackets = 0;
183
+ this.deltaReceivedFrames = 0;
184
+ this.deltaDecodedFrames = 0;
185
+ this.deltaDroppedFrames = 0;
186
+ this.deltaReceivedSamples = 0;
187
+ this.deltaSilentConcealedSamples = 0;
188
+ this.fractionLoss = 0;
189
+ for (const [, stats] of this._stats) {
190
+ if (stats.statsTimestamp <= this._lastMaxStatsTimestamp)
191
+ continue;
192
+ this.deltaBytesReceived += (_a = stats.deltaReceivedBytes) !== null && _a !== void 0 ? _a : 0;
193
+ this.deltaLostPackets += (_b = stats.deltaLostPackets) !== null && _b !== void 0 ? _b : 0;
194
+ this.deltaReceivedPackets += (_c = stats.deltaReceivedFrames) !== null && _c !== void 0 ? _c : 0;
195
+ this.deltaReceivedFrames += (_d = stats.deltaReceivedFrames) !== null && _d !== void 0 ? _d : 0;
196
+ this.deltaDecodedFrames += (_e = stats.deltaDecodedFrames) !== null && _e !== void 0 ? _e : 0;
197
+ this.deltaDroppedFrames += (_f = stats.deltaDroppedFrames) !== null && _f !== void 0 ? _f : 0;
198
+ this.deltaReceivedSamples += (_g = stats.deltaReceivedSamples) !== null && _g !== void 0 ? _g : 0;
199
+ this.deltaSilentConcealedSamples += (_h = stats.deltaSilentConcealedSamples) !== null && _h !== void 0 ? _h : 0;
200
+ this.bitrate += stats.bitrate;
201
+ maxStatsTimestamp = Math.max(maxStatsTimestamp, stats.statsTimestamp);
202
+ rttInMsSum += (_j = stats.rttInMs) !== null && _j !== void 0 ? _j : 0;
203
+ ++size;
204
+ }
205
+ this.totalBytesReceived += this.deltaBytesReceived;
206
+ this.totalLostPackets += this.deltaLostPackets;
207
+ this.totalReceivedPackets += this.deltaReceivedPackets;
208
+ this.totalReceivedFrames += this.deltaReceivedFrames;
209
+ this.totalDecodedFrames += this.deltaDecodedFrames;
210
+ this.totalDroppedFrames += this.deltaDroppedFrames;
211
+ this.totalReceivedSamples += this.deltaReceivedSamples;
212
+ this.totalSilentConcealedSamples += this.deltaSilentConcealedSamples;
213
+ this.rttInMs = rttInMsSum / Math.max(size, 1);
214
+ this.fractionLoss = 0 < this.deltaReceivedPackets && 0 < this.deltaLostPackets ? (this.deltaLostPackets / (this.deltaReceivedPackets + this.deltaLostPackets)) : 0;
215
+ this._lastMaxStatsTimestamp = maxStatsTimestamp;
216
+ }
200
217
  }
201
218
  exports.ObservedInboundTrack = ObservedInboundTrack;
@@ -23,6 +23,7 @@ export type ObservedOutboundTrackStats<K extends MediaKind> = ObservedOutboundTr
23
23
  deltaSentBytes: number;
24
24
  deltaSentFrames?: number;
25
25
  deltaEncodedFrames?: number;
26
+ statsTimestamp: number;
26
27
  };
27
28
  export declare interface ObservedOutboundTrack<Kind extends MediaKind> {
28
29
  on<U extends keyof ObservedOutboundTrackEvents>(event: U, listener: (...args: ObservedOutboundTrackEvents[U]) => void): this;
@@ -48,6 +49,7 @@ export declare class ObservedOutboundTrack<Kind extends MediaKind> extends Event
48
49
  deltaSentFrames: number;
49
50
  deltaEncodedFrames: number;
50
51
  private readonly _stats;
52
+ private _lastMaxStatsTimestamp;
51
53
  private _closed;
52
54
  private _updated;
53
55
  private _remoteInboundTracks;
@@ -67,7 +69,7 @@ export declare class ObservedOutboundTrack<Kind extends MediaKind> extends Event
67
69
  get stats(): ReadonlyMap<number, ObservedOutboundTrackStats<Kind>>;
68
70
  get closed(): boolean;
69
71
  close(): void;
70
- resetMetrics(): void;
71
72
  connectInboundTrack(track: ObservedInboundTrack<Kind>): void;
73
+ updateMetrics(): void;
72
74
  }
73
75
  //# sourceMappingURL=ObservedOutboundTrack.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedOutboundTrack.d.ts","sourceRoot":"","sources":["../src/ObservedOutboundTrack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ObservedOutboundTrack.d.ts","sourceRoot":"","sources":["../src/ObservedOutboundTrack.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
19
19
  this.deltaSentFrames = 0;
20
20
  this.deltaEncodedFrames = 0;
21
21
  this._stats = new Map();
22
+ this._lastMaxStatsTimestamp = 0;
22
23
  this._closed = false;
23
24
  this._updated = Date.now();
24
25
  this._remoteInboundTracks = new Map();
@@ -72,20 +73,11 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
72
73
  this._closed = true;
73
74
  this.emit('close');
74
75
  }
75
- resetMetrics() {
76
- this.bitrate = 0;
77
- this.rttInMs = 0;
78
- this.deltaLostPackets = 0;
79
- this.deltaSentPackets = 0;
80
- this.deltaSentBytes = 0;
81
- this.deltaSentFrames = 0;
82
- this.deltaEncodedFrames = 0;
83
- }
84
- update(sample, timestamp) {
76
+ update(sample, statsTimestamp) {
85
77
  if (this._closed)
86
78
  return;
87
79
  const now = Date.now();
88
- const report = Object.assign(Object.assign({ serviceId: this.peerConnection.client.serviceId, roomId: this.peerConnection.client.call.roomId, callId: this.peerConnection.client.call.callId, clientId: this.peerConnection.client.clientId, userId: this.peerConnection.client.userId, mediaUnitId: this.peerConnection.client.mediaUnitId, peerConnectionId: this.peerConnection.peerConnectionId }, sample), { timestamp, sampleSeq: -1, marker: this.marker });
80
+ const report = Object.assign(Object.assign({ serviceId: this.peerConnection.client.serviceId, roomId: this.peerConnection.client.call.roomId, callId: this.peerConnection.client.call.callId, clientId: this.peerConnection.client.clientId, userId: this.peerConnection.client.userId, mediaUnitId: this.peerConnection.client.mediaUnitId, peerConnectionId: this.peerConnection.peerConnectionId }, sample), { timestamp: statsTimestamp, sampleSeq: -1, marker: this.marker });
89
81
  if (this.kind === 'audio')
90
82
  this.reports.addOutboundAudioTrackReport(report);
91
83
  else if (this.kind === 'video')
@@ -126,19 +118,20 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
126
118
  deltaSentPackets,
127
119
  deltaSentBytes,
128
120
  deltaEncodedFrames,
129
- deltaSentFrames });
121
+ deltaSentFrames,
122
+ statsTimestamp });
130
123
  this._stats.set(sample.ssrc, stats);
131
- this.bitrate = [...this._stats.values()].reduce((acc, stat) => acc + stat.bitrate, 0);
132
- this.rttInMs = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.rttInMs) !== null && _a !== void 0 ? _a : 0); }, 0) / (this._stats.size || 1);
133
- this.totalLostPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.packetsLost) !== null && _a !== void 0 ? _a : 0); }, 0);
134
- this.totalSentPackets = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.packetsSent) !== null && _a !== void 0 ? _a : 0); }, 0);
135
- this.totalSentBytes = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.bytesSent) !== null && _a !== void 0 ? _a : 0); }, 0);
136
- this.totalSentFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.deltaSentPackets) !== null && _a !== void 0 ? _a : 0); }, 0);
137
- this.deltaEncodedFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.deltaEncodedFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
138
- this.deltaSentFrames = [...this._stats.values()].reduce((acc, stat) => { var _a; return acc + ((_a = stat.deltaSentFrames) !== null && _a !== void 0 ? _a : 0); }, 0);
139
- this.deltaLostPackets = [...this._stats.values()].reduce((acc, stat) => acc + stat.deltaLostPackets, 0);
140
- this.deltaSentPackets = [...this._stats.values()].reduce((acc, stat) => acc + stat.deltaSentPackets, 0);
141
- this.deltaSentBytes = [...this._stats.values()].reduce((acc, stat) => acc + stat.deltaSentBytes, 0);
124
+ // this.bitrate = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.bitrate, 0);
125
+ // this.rttInMs = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.rttInMs ?? 0), 0) / (this._stats.size || 1);
126
+ // this.totalLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.packetsLost ?? 0), 0);
127
+ // this.totalSentPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.packetsSent ?? 0), 0);
128
+ // this.totalSentBytes = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.bytesSent ?? 0), 0);
129
+ // this.totalSentFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaSentPackets ?? 0), 0);
130
+ // this.deltaEncodedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaEncodedFrames ?? 0), 0);
131
+ // this.deltaSentFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaSentFrames ?? 0), 0);
132
+ // this.deltaLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaLostPackets, 0);
133
+ // this.deltaSentPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaSentPackets, 0);
134
+ // this.deltaSentBytes = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaSentBytes, 0);
142
135
  // setting up sfu connection as it is not always available at the first sample
143
136
  if (sample.sfuStreamId && !this._model.sfuStreamId) {
144
137
  this._model.sfuStreamId = sample.sfuStreamId;
@@ -167,5 +160,37 @@ class ObservedOutboundTrack extends events_1.EventEmitter {
167
160
  });
168
161
  this._remoteInboundTracks.set(track.trackId, track);
169
162
  }
163
+ updateMetrics() {
164
+ var _a, _b, _c, _d, _e, _f;
165
+ let maxStatsTimestamp = 0;
166
+ let rttInMsSum = 0;
167
+ let size = 0;
168
+ this.bitrate = 0;
169
+ this.rttInMs = undefined;
170
+ this.deltaLostPackets = 0;
171
+ this.deltaSentPackets = 0;
172
+ this.deltaSentBytes = 0;
173
+ this.deltaSentFrames = 0;
174
+ this.deltaEncodedFrames = 0;
175
+ for (const [, stats] of this._stats) {
176
+ if (stats.statsTimestamp <= this._lastMaxStatsTimestamp)
177
+ continue;
178
+ this.deltaLostPackets += (_a = stats.deltaLostPackets) !== null && _a !== void 0 ? _a : 0;
179
+ this.deltaSentPackets += (_b = stats.deltaSentPackets) !== null && _b !== void 0 ? _b : 0;
180
+ this.deltaSentBytes += (_c = stats.deltaSentBytes) !== null && _c !== void 0 ? _c : 0;
181
+ this.deltaSentFrames += (_d = stats.deltaSentFrames) !== null && _d !== void 0 ? _d : 0;
182
+ this.deltaEncodedFrames += (_e = stats.deltaEncodedFrames) !== null && _e !== void 0 ? _e : 0;
183
+ this.bitrate += stats.bitrate;
184
+ maxStatsTimestamp = Math.max(maxStatsTimestamp, stats.statsTimestamp);
185
+ rttInMsSum += (_f = stats.rttInMs) !== null && _f !== void 0 ? _f : 0;
186
+ ++size;
187
+ }
188
+ this.totalLostPackets += this.deltaLostPackets;
189
+ this.totalSentPackets += this.deltaSentPackets;
190
+ this.totalSentBytes += this.deltaSentBytes;
191
+ this.totalSentFrames += this.deltaSentFrames;
192
+ this.rttInMs = rttInMsSum / Math.max(size, 1);
193
+ this._lastMaxStatsTimestamp = maxStatsTimestamp;
194
+ }
170
195
  }
171
196
  exports.ObservedOutboundTrack = ObservedOutboundTrack;
@@ -1 +1 @@
1
- {"version":3,"file":"ObservedPeerConnection.d.ts","sourceRoot":"","sources":["../src/ObservedPeerConnection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ObservedPeerConnection.d.ts","sourceRoot":"","sources":["../src/ObservedPeerConnection.ts"],"names":[],"mappings":"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"}
@@ -163,16 +163,13 @@ class ObservedPeerConnection extends events_1.EventEmitter {
163
163
  this.sendingVideoBitrate = 0;
164
164
  this.receivingAudioBitrate = 0;
165
165
  this.receivingVideoBitrate = 0;
166
- this._inboundAudioTracks.forEach((track) => track.resetMetrics());
167
- this._inboundVideoTracks.forEach((track) => track.resetMetrics());
168
- this._outboundAudioTracks.forEach((track) => track.resetMetrics());
169
- this._outboundVideoTracks.forEach((track) => track.resetMetrics());
170
166
  }
171
167
  updateMetrics() {
172
168
  var _a;
173
169
  let sumRttInMs = 0;
174
170
  this._inboundAudioTracks.forEach((track) => {
175
171
  var _a;
172
+ track.updateMetrics();
176
173
  this.deltaInboundPacketsLost += track.deltaLostPackets;
177
174
  this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
178
175
  this.deltaInboundReceivedBytes += track.deltaBytesReceived;
@@ -183,6 +180,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
183
180
  });
184
181
  this._inboundVideoTracks.forEach((track) => {
185
182
  var _a;
183
+ track.updateMetrics();
186
184
  this.deltaInboundPacketsLost += track.deltaLostPackets;
187
185
  this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
188
186
  this.deltaInboundReceivedBytes += track.deltaBytesReceived;
@@ -193,6 +191,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
193
191
  });
194
192
  this._outboundAudioTracks.forEach((track) => {
195
193
  var _a;
194
+ track.updateMetrics();
196
195
  this.deltaOutboundPacketsSent += track.deltaSentPackets;
197
196
  this.deltaOutboundSentBytes += track.deltaSentBytes;
198
197
  this.deltaSentAudioBytes += track.deltaSentBytes;
@@ -202,6 +201,7 @@ class ObservedPeerConnection extends events_1.EventEmitter {
202
201
  });
203
202
  this._outboundVideoTracks.forEach((track) => {
204
203
  var _a;
204
+ track.updateMetrics();
205
205
  this.deltaOutboundPacketsSent += track.deltaSentPackets;
206
206
  this.deltaOutboundSentBytes += track.deltaSentBytes;
207
207
  this.deltaSentVideoBytes += track.deltaSentBytes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@observertc/observer-js",
3
- "version": "0.40.6-beta",
3
+ "version": "0.40.7-beta",
4
4
  "description": "Server Side NodeJS Library for processing ObserveRTC Samples",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -25,14 +25,16 @@ export type ObservedInboundTrackStats<K extends MediaKind> = ObservedInboundTrac
25
25
  bitrate: number;
26
26
  fractionLost: number;
27
27
  rttInMs?: number;
28
- lostPackets?: number;
29
- receivedPackets?: number;
30
- receivedFrames?: number;
31
- decodedFrames?: number;
32
- droppedFrames?: number;
33
- receivedSamples?: number;
34
- silentConcealedSamples?: number;
28
+ deltaReceivedBytes?: number;
29
+ deltaLostPackets?: number;
30
+ deltaReceivedPackets?: number;
31
+ deltaReceivedFrames?: number;
32
+ deltaDecodedFrames?: number;
33
+ deltaDroppedFrames?: number;
34
+ deltaReceivedSamples?: number;
35
+ deltaSilentConcealedSamples?: number;
35
36
  fractionLoss?: number;
37
+ statsTimestamp: number;
36
38
  };
37
39
 
38
40
  // {
@@ -55,6 +57,8 @@ export class ObservedInboundTrack<Kind extends MediaKind> extends EventEmitter {
55
57
  private _closed = false;
56
58
  private _updated = Date.now();
57
59
  private _remoteOutboundTrack?: ObservedOutboundTrack<Kind>;
60
+ private _lastMaxStatsTimestamp = 0;
61
+
58
62
  public bitrate = 0;
59
63
  public rttInMs?: number;
60
64
  public fractionLoss = 0;
@@ -165,20 +169,7 @@ export class ObservedInboundTrack<Kind extends MediaKind> extends EventEmitter {
165
169
  this.emit('close');
166
170
  }
167
171
 
168
- public resetMetrics() {
169
- this.bitrate = 0;
170
- this.rttInMs = undefined;
171
- this.deltaBytesReceived = 0;
172
- this.deltaLostPackets = 0;
173
- this.deltaReceivedFrames = 0;
174
- this.deltaDecodedFrames = 0;
175
- this.deltaDroppedFrames = 0;
176
- this.deltaReceivedSamples = 0;
177
- this.deltaSilentConcealedSamples = 0;
178
- this.fractionLoss = 0;
179
- }
180
-
181
- public update(sample: ObservedInboundTrackStatsUpdate<Kind>, timestamp: number) {
172
+ public update(sample: ObservedInboundTrackStatsUpdate<Kind>, statsTimestamp: number) {
182
173
  if (this._closed) return;
183
174
 
184
175
  const now = Date.now();
@@ -191,7 +182,7 @@ export class ObservedInboundTrack<Kind extends MediaKind> extends EventEmitter {
191
182
  mediaUnitId: this.peerConnection.client.mediaUnitId,
192
183
  peerConnectionId: this.peerConnection.peerConnectionId,
193
184
  ...sample,
194
- timestamp,
185
+ timestamp: statsTimestamp,
195
186
  sampleSeq: -1,
196
187
 
197
188
  remoteClientId: sample.remoteClientId ?? this.remoteOutboundTrack?.peerConnection.client.clientId,
@@ -216,47 +207,49 @@ export class ObservedInboundTrack<Kind extends MediaKind> extends EventEmitter {
216
207
  const lastStat = this._stats.get(sample.ssrc);
217
208
  const rttInMs = sample.roundTripTime ? sample.roundTripTime * 1000 : undefined;
218
209
  let bitrate = 0;
210
+ let deltaReceivedBytes = 0;
219
211
  let fractionLost = 0;
220
- let lostPackets = 0;
221
- let receivedPackets = 0;
212
+ let deltaLostPackets = 0;
213
+ let deltaReceivedPackets = 0;
222
214
 
223
215
  if (lastStat?.bytesReceived && sample.bytesReceived && lastStat.bytesReceived < sample.bytesReceived) {
224
- bitrate = (sample.bytesReceived - lastStat.bytesReceived) / (elapsedTimeInMs / 1000);
216
+ deltaReceivedBytes = sample.bytesReceived - lastStat.bytesReceived;
217
+ bitrate = deltaReceivedBytes / (elapsedTimeInMs / 1000);
225
218
  }
226
219
  if (lastStat?.packetsReceived && sample?.packetsReceived && lastStat.packetsReceived < sample.packetsReceived) {
227
- receivedPackets = sample.packetsReceived - lastStat.packetsReceived;
220
+ deltaReceivedPackets = sample.packetsReceived - lastStat.packetsReceived;
228
221
  }
229
222
  if (lastStat?.packetsLost && sample.packetsLost && lastStat.packetsLost < sample.packetsLost) {
230
- lostPackets = sample.packetsLost - lastStat.packetsLost;
231
- if (0 < receivedPackets) {
232
- fractionLost = lostPackets / (receivedPackets + lostPackets);
223
+ deltaLostPackets = sample.packetsLost - lastStat.packetsLost;
224
+ if (0 < deltaReceivedPackets) {
225
+ fractionLost = deltaLostPackets / (deltaReceivedPackets + deltaLostPackets);
233
226
  }
234
227
  }
235
228
 
236
- let decodedFrames: number | undefined;
237
- let droppedFrames: number | undefined;
238
- let receivedFrames: number | undefined;
239
- let silentConcealedSamples: number | undefined;
229
+ let deltaDecodedFrames: number | undefined;
230
+ let deltaDroppedFrames: number | undefined;
231
+ let deltaReceivedFrames: number | undefined;
232
+ let deltaSilentConcealedSamples: number | undefined;
240
233
 
241
234
  if (this.kind === 'video') {
242
235
  const videoSample = sample as InboundVideoTrack;
243
236
  const lastVideoStat = lastStat as InboundVideoTrack | undefined;
244
237
 
245
238
  if (videoSample.framesDecoded && lastVideoStat?.framesDecoded && lastVideoStat.framesDecoded < videoSample.framesDecoded) {
246
- decodedFrames = videoSample.framesDecoded - lastVideoStat.framesDecoded;
239
+ deltaDecodedFrames = videoSample.framesDecoded - lastVideoStat.framesDecoded;
247
240
  }
248
241
  if (videoSample.framesDropped && lastVideoStat?.framesDropped && lastVideoStat.framesDropped < videoSample.framesDropped) {
249
- droppedFrames = videoSample.framesDropped - lastVideoStat.framesDropped;
242
+ deltaDroppedFrames = videoSample.framesDropped - lastVideoStat.framesDropped;
250
243
  }
251
244
  if (videoSample.framesReceived && lastVideoStat?.framesReceived && lastVideoStat.framesReceived < videoSample.framesReceived) {
252
- receivedFrames = videoSample.framesReceived - lastVideoStat.framesReceived;
245
+ deltaReceivedFrames = videoSample.framesReceived - lastVideoStat.framesReceived;
253
246
  }
254
247
  } else if (this.kind === 'audio') {
255
248
  const audioSample = sample as InboundAudioTrack;
256
249
  const lastAudioStat = lastStat as InboundAudioTrack | undefined;
257
250
 
258
251
  if (audioSample.silentConcealedSamples && lastAudioStat?.silentConcealedSamples && lastAudioStat.silentConcealedSamples < audioSample.silentConcealedSamples) {
259
- silentConcealedSamples = audioSample.silentConcealedSamples - lastAudioStat.silentConcealedSamples;
252
+ deltaSilentConcealedSamples = audioSample.silentConcealedSamples - lastAudioStat.silentConcealedSamples;
260
253
  }
261
254
  }
262
255
 
@@ -266,38 +259,69 @@ export class ObservedInboundTrack<Kind extends MediaKind> extends EventEmitter {
266
259
  rttInMs,
267
260
  bitrate,
268
261
  ssrc: sample.ssrc,
269
- lostPackets,
270
- receivedPackets,
271
- receivedFrames,
272
- decodedFrames,
273
- droppedFrames,
274
- silentConcealedSamples,
262
+ deltaReceivedBytes,
263
+ deltaLostPackets,
264
+ deltaReceivedPackets,
265
+ deltaReceivedFrames,
266
+ deltaDecodedFrames,
267
+ deltaDroppedFrames,
268
+ deltaSilentConcealedSamples,
269
+ statsTimestamp,
275
270
  };
276
271
 
277
272
  this._stats.set(sample.ssrc, stats);
278
273
 
279
- this.bitrate = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.bitrate, 0);
280
- this.rttInMs = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.rttInMs ?? 0), 0) / (this._stats.size || 1);
281
- this.totalLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.lostPackets ?? 0), 0);
282
- this.totalReceivedPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.receivedPackets ?? 0), 0);
283
- this.totalBytesReceived = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.bytesReceived ?? 0), 0);
284
- this.totalReceivedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.receivedFrames ?? 0), 0);
285
- this.totalDecodedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.decodedFrames ?? 0), 0);
286
- this.totalDroppedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.droppedFrames ?? 0), 0);
287
- this.totalReceivedSamples = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.receivedSamples ?? 0), 0);
288
- this.totalSilentConcealedSamples = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.silentConcealedSamples ?? 0), 0);
289
-
290
- this.deltaLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.lostPackets ?? 0), 0);
291
- this.deltaReceivedPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.receivedPackets ?? 0), 0);
292
- this.deltaBytesReceived = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.bytesReceived ?? 0), 0);
293
- this.deltaReceivedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.receivedFrames ?? 0), 0);
294
- this.deltaDecodedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.decodedFrames ?? 0), 0);
295
- this.deltaDroppedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.droppedFrames ?? 0), 0);
296
- this.deltaReceivedSamples = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.receivedSamples ?? 0), 0);
297
- this.deltaSilentConcealedSamples = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.silentConcealedSamples ?? 0), 0);
298
- this.fractionLoss = 0 < this.deltaReceivedPackets && 0 < this.deltaLostPackets ? (this.deltaLostPackets / (this.deltaReceivedPackets + this.deltaLostPackets)) : 0;
299
-
300
274
  this._updated = now;
301
275
  this.emit('update');
302
276
  }
277
+
278
+ public updateMetrics() {
279
+ let maxStatsTimestamp = 0;
280
+ let rttInMsSum = 0;
281
+ let size = 0;
282
+
283
+ this.bitrate = 0;
284
+ this.rttInMs = undefined;
285
+ this.deltaBytesReceived = 0;
286
+ this.deltaLostPackets = 0;
287
+ this.deltaReceivedFrames = 0;
288
+ this.deltaDecodedFrames = 0;
289
+ this.deltaDroppedFrames = 0;
290
+ this.deltaReceivedSamples = 0;
291
+ this.deltaSilentConcealedSamples = 0;
292
+ this.fractionLoss = 0;
293
+
294
+ for (const [ , stats ] of this._stats) {
295
+ if (stats.statsTimestamp <= this._lastMaxStatsTimestamp) continue;
296
+
297
+ this.deltaBytesReceived += stats.deltaReceivedBytes ?? 0;
298
+ this.deltaLostPackets += stats.deltaLostPackets ?? 0;
299
+ this.deltaReceivedPackets += stats.deltaReceivedFrames ?? 0;
300
+ this.deltaReceivedFrames += stats.deltaReceivedFrames ?? 0;
301
+ this.deltaDecodedFrames += stats.deltaDecodedFrames ?? 0;
302
+ this.deltaDroppedFrames += stats.deltaDroppedFrames ?? 0;
303
+ this.deltaReceivedSamples += stats.deltaReceivedSamples ?? 0;
304
+ this.deltaSilentConcealedSamples += stats.deltaSilentConcealedSamples ?? 0;
305
+ this.bitrate += stats.bitrate;
306
+
307
+ maxStatsTimestamp = Math.max(maxStatsTimestamp, stats.statsTimestamp);
308
+
309
+ rttInMsSum += stats.rttInMs ?? 0;
310
+ ++size;
311
+ }
312
+
313
+ this.totalBytesReceived += this.deltaBytesReceived;
314
+ this.totalLostPackets += this.deltaLostPackets;
315
+ this.totalReceivedPackets += this.deltaReceivedPackets;
316
+ this.totalReceivedFrames += this.deltaReceivedFrames;
317
+ this.totalDecodedFrames += this.deltaDecodedFrames;
318
+ this.totalDroppedFrames += this.deltaDroppedFrames;
319
+ this.totalReceivedSamples += this.deltaReceivedSamples;
320
+ this.totalSilentConcealedSamples += this.deltaSilentConcealedSamples;
321
+
322
+ this.rttInMs = rttInMsSum / Math.max(size, 1);
323
+ this.fractionLoss = 0 < this.deltaReceivedPackets && 0 < this.deltaLostPackets ? (this.deltaLostPackets / (this.deltaReceivedPackets + this.deltaLostPackets)) : 0;
324
+
325
+ this._lastMaxStatsTimestamp = maxStatsTimestamp;
326
+ }
303
327
  }
@@ -28,6 +28,8 @@ export type ObservedOutboundTrackStats<K extends MediaKind> = ObservedOutboundTr
28
28
  deltaSentBytes: number;
29
29
  deltaSentFrames?: number;
30
30
  deltaEncodedFrames?: number;
31
+
32
+ statsTimestamp: number;
31
33
  };
32
34
 
33
35
  // export type ObservedOutboundTrackStatsUpdate<K extends MediaKind> = {
@@ -61,6 +63,7 @@ export class ObservedOutboundTrack<Kind extends MediaKind> extends EventEmitter
61
63
  public deltaEncodedFrames = 0;
62
64
 
63
65
  private readonly _stats = new Map<number, ObservedOutboundTrackStats<Kind>>();
66
+ private _lastMaxStatsTimestamp = 0;
64
67
 
65
68
  private _closed = false;
66
69
  private _updated = Date.now();
@@ -137,18 +140,7 @@ export class ObservedOutboundTrack<Kind extends MediaKind> extends EventEmitter
137
140
  this.emit('close');
138
141
  }
139
142
 
140
- public resetMetrics() {
141
- this.bitrate = 0;
142
- this.rttInMs = 0;
143
-
144
- this.deltaLostPackets = 0;
145
- this.deltaSentPackets = 0;
146
- this.deltaSentBytes = 0;
147
- this.deltaSentFrames = 0;
148
- this.deltaEncodedFrames = 0;
149
- }
150
-
151
- public update(sample: ObservedOutboundTrackStatsUpdate<Kind>, timestamp: number): void {
143
+ public update(sample: ObservedOutboundTrackStatsUpdate<Kind>, statsTimestamp: number): void {
152
144
  if (this._closed) return;
153
145
 
154
146
  const now = Date.now();
@@ -161,7 +153,7 @@ export class ObservedOutboundTrack<Kind extends MediaKind> extends EventEmitter
161
153
  mediaUnitId: this.peerConnection.client.mediaUnitId,
162
154
  peerConnectionId: this.peerConnection.peerConnectionId,
163
155
  ...sample,
164
- timestamp,
156
+ timestamp: statsTimestamp,
165
157
  sampleSeq: -1,
166
158
  marker: this.marker,
167
159
  };
@@ -215,23 +207,25 @@ export class ObservedOutboundTrack<Kind extends MediaKind> extends EventEmitter
215
207
  deltaSentBytes,
216
208
  deltaEncodedFrames,
217
209
  deltaSentFrames,
210
+
211
+ statsTimestamp,
218
212
  };
219
213
 
220
214
  this._stats.set(sample.ssrc, stats);
221
215
 
222
- this.bitrate = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.bitrate, 0);
223
- this.rttInMs = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.rttInMs ?? 0), 0) / (this._stats.size || 1);
216
+ // this.bitrate = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.bitrate, 0);
217
+ // this.rttInMs = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.rttInMs ?? 0), 0) / (this._stats.size || 1);
224
218
 
225
- this.totalLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.packetsLost ?? 0), 0);
226
- this.totalSentPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.packetsSent ?? 0), 0);
227
- this.totalSentBytes = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.bytesSent ?? 0), 0);
228
- this.totalSentFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaSentPackets ?? 0), 0);
219
+ // this.totalLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.packetsLost ?? 0), 0);
220
+ // this.totalSentPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.packetsSent ?? 0), 0);
221
+ // this.totalSentBytes = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.bytesSent ?? 0), 0);
222
+ // this.totalSentFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaSentPackets ?? 0), 0);
229
223
 
230
- this.deltaEncodedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaEncodedFrames ?? 0), 0);
231
- this.deltaSentFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaSentFrames ?? 0), 0);
232
- this.deltaLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaLostPackets, 0);
233
- this.deltaSentPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaSentPackets, 0);
234
- this.deltaSentBytes = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaSentBytes, 0);
224
+ // this.deltaEncodedFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaEncodedFrames ?? 0), 0);
225
+ // this.deltaSentFrames = [ ...this._stats.values() ].reduce((acc, stat) => acc + (stat.deltaSentFrames ?? 0), 0);
226
+ // this.deltaLostPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaLostPackets, 0);
227
+ // this.deltaSentPackets = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaSentPackets, 0);
228
+ // this.deltaSentBytes = [ ...this._stats.values() ].reduce((acc, stat) => acc + stat.deltaSentBytes, 0);
235
229
 
236
230
  // setting up sfu connection as it is not always available at the first sample
237
231
  if (sample.sfuStreamId && !this._model.sfuStreamId) {
@@ -261,4 +255,44 @@ export class ObservedOutboundTrack<Kind extends MediaKind> extends EventEmitter
261
255
 
262
256
  this._remoteInboundTracks.set(track.trackId, track);
263
257
  }
258
+
259
+ public updateMetrics() {
260
+ let maxStatsTimestamp = 0;
261
+ let rttInMsSum = 0;
262
+ let size = 0;
263
+
264
+ this.bitrate = 0;
265
+ this.rttInMs = undefined;
266
+
267
+ this.deltaLostPackets = 0;
268
+ this.deltaSentPackets = 0;
269
+ this.deltaSentBytes = 0;
270
+ this.deltaSentFrames = 0;
271
+ this.deltaEncodedFrames = 0;
272
+
273
+ for (const [ , stats ] of this._stats) {
274
+ if (stats.statsTimestamp <= this._lastMaxStatsTimestamp) continue;
275
+
276
+ this.deltaLostPackets += stats.deltaLostPackets ?? 0;
277
+ this.deltaSentPackets += stats.deltaSentPackets ?? 0;
278
+ this.deltaSentBytes += stats.deltaSentBytes ?? 0;
279
+ this.deltaSentFrames += stats.deltaSentFrames ?? 0;
280
+ this.deltaEncodedFrames += stats.deltaEncodedFrames ?? 0;
281
+ this.bitrate += stats.bitrate;
282
+
283
+ maxStatsTimestamp = Math.max(maxStatsTimestamp, stats.statsTimestamp);
284
+
285
+ rttInMsSum += stats.rttInMs ?? 0;
286
+ ++size;
287
+ }
288
+
289
+ this.totalLostPackets += this.deltaLostPackets;
290
+ this.totalSentPackets += this.deltaSentPackets;
291
+ this.totalSentBytes += this.deltaSentBytes;
292
+ this.totalSentFrames += this.deltaSentFrames;
293
+
294
+ this.rttInMs = rttInMsSum / Math.max(size, 1);
295
+
296
+ this._lastMaxStatsTimestamp = maxStatsTimestamp;
297
+ }
264
298
  }
@@ -224,17 +224,14 @@ export class ObservedPeerConnection extends EventEmitter {
224
224
  this.sendingVideoBitrate = 0;
225
225
  this.receivingAudioBitrate = 0;
226
226
  this.receivingVideoBitrate = 0;
227
-
228
- this._inboundAudioTracks.forEach((track) => track.resetMetrics());
229
- this._inboundVideoTracks.forEach((track) => track.resetMetrics());
230
- this._outboundAudioTracks.forEach((track) => track.resetMetrics());
231
- this._outboundVideoTracks.forEach((track) => track.resetMetrics());
232
227
  }
233
228
 
234
229
  public updateMetrics() {
235
230
  let sumRttInMs = 0;
236
231
 
237
232
  this._inboundAudioTracks.forEach((track) => {
233
+ track.updateMetrics();
234
+
238
235
  this.deltaInboundPacketsLost += track.deltaLostPackets;
239
236
  this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
240
237
  this.deltaInboundReceivedBytes += track.deltaBytesReceived;
@@ -248,6 +245,8 @@ export class ObservedPeerConnection extends EventEmitter {
248
245
  });
249
246
 
250
247
  this._inboundVideoTracks.forEach((track) => {
248
+ track.updateMetrics();
249
+
251
250
  this.deltaInboundPacketsLost += track.deltaLostPackets;
252
251
  this.deltaInboundPacketsReceived += track.deltaReceivedPackets;
253
252
  this.deltaInboundReceivedBytes += track.deltaBytesReceived;
@@ -261,6 +260,8 @@ export class ObservedPeerConnection extends EventEmitter {
261
260
  });
262
261
 
263
262
  this._outboundAudioTracks.forEach((track) => {
263
+ track.updateMetrics();
264
+
264
265
  this.deltaOutboundPacketsSent += track.deltaSentPackets;
265
266
  this.deltaOutboundSentBytes += track.deltaSentBytes;
266
267
 
@@ -273,6 +274,8 @@ export class ObservedPeerConnection extends EventEmitter {
273
274
  });
274
275
 
275
276
  this._outboundVideoTracks.forEach((track) => {
277
+ track.updateMetrics();
278
+
276
279
  this.deltaOutboundPacketsSent += track.deltaSentPackets;
277
280
  this.deltaOutboundSentBytes += track.deltaSentBytes;
278
281