@observertc/observer-js 1.0.0-beta.4 → 1.0.0-beta.6
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.
- package/README.md +133 -65
- package/dist/index.d.mts +104 -126
- package/dist/index.d.ts +2771 -0
- package/dist/index.js +3665 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +232 -355
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -8
package/dist/index.mjs
CHANGED
|
@@ -330,8 +330,7 @@ var ObservedOutboundRtp = class {
|
|
|
330
330
|
return this._peerConnection.observedMediaSources.get(this.mediaSourceId ?? "");
|
|
331
331
|
}
|
|
332
332
|
getTrack() {
|
|
333
|
-
|
|
334
|
-
return (_a = this.getMediaSource()) == null ? void 0 : _a.getTrack();
|
|
333
|
+
return this.getMediaSource()?.getTrack();
|
|
335
334
|
}
|
|
336
335
|
update(stats) {
|
|
337
336
|
this._visited = true;
|
|
@@ -1064,20 +1063,6 @@ var ObservedInboundTrack = class {
|
|
|
1064
1063
|
this._peerConnection = _peerConnection;
|
|
1065
1064
|
this._inboundRtp = _inboundRtp;
|
|
1066
1065
|
this._mediaPlayout = _mediaPlayout;
|
|
1067
|
-
this.report = {
|
|
1068
|
-
trackId: this.id,
|
|
1069
|
-
kind: this.kind,
|
|
1070
|
-
fractionLostDistribution: {
|
|
1071
|
-
gtOrEq050: 0,
|
|
1072
|
-
lt001: 0,
|
|
1073
|
-
lt005: 0,
|
|
1074
|
-
lt010: 0,
|
|
1075
|
-
lt020: 0,
|
|
1076
|
-
lt050: 0,
|
|
1077
|
-
count: 0,
|
|
1078
|
-
sum: 0
|
|
1079
|
-
}
|
|
1080
|
-
};
|
|
1081
1066
|
}
|
|
1082
1067
|
timestamp;
|
|
1083
1068
|
id;
|
|
@@ -1090,7 +1075,7 @@ var ObservedInboundTrack = class {
|
|
|
1090
1075
|
value: void 0
|
|
1091
1076
|
};
|
|
1092
1077
|
appData;
|
|
1093
|
-
|
|
1078
|
+
remoteOutboundTrack;
|
|
1094
1079
|
_visited = false;
|
|
1095
1080
|
addedAt;
|
|
1096
1081
|
removedAt;
|
|
@@ -1113,27 +1098,11 @@ var ObservedInboundTrack = class {
|
|
|
1113
1098
|
getMediaPlayout() {
|
|
1114
1099
|
return this._mediaPlayout;
|
|
1115
1100
|
}
|
|
1116
|
-
getRemoteOutboundTrack() {
|
|
1117
|
-
var _a;
|
|
1118
|
-
return (_a = this._peerConnection.client.call.remoteTrackResolver) == null ? void 0 : _a.resolveRemoteOutboundTrack(this);
|
|
1119
|
-
}
|
|
1120
1101
|
update(stats) {
|
|
1121
|
-
var _a;
|
|
1122
1102
|
this._visited = true;
|
|
1123
1103
|
this.timestamp = stats.timestamp;
|
|
1124
1104
|
this.calculatedScore.value = stats.score;
|
|
1125
1105
|
this.attachments = stats.attachments;
|
|
1126
|
-
const fl = (_a = this._inboundRtp) == null ? void 0 : _a.fractionLost;
|
|
1127
|
-
if (fl !== void 0) {
|
|
1128
|
-
if (fl < 0.01) this.report.fractionLostDistribution.lt001 += 1;
|
|
1129
|
-
else if (fl < 0.05) this.report.fractionLostDistribution.lt005 += 1;
|
|
1130
|
-
else if (fl < 0.1) this.report.fractionLostDistribution.lt010 += 1;
|
|
1131
|
-
else if (fl < 0.2) this.report.fractionLostDistribution.lt020 += 1;
|
|
1132
|
-
else if (fl < 0.5) this.report.fractionLostDistribution.lt050 += 1;
|
|
1133
|
-
else this.report.fractionLostDistribution.gtOrEq050 += 1;
|
|
1134
|
-
this.report.fractionLostDistribution.count += 1;
|
|
1135
|
-
this.report.fractionLostDistribution.sum += fl;
|
|
1136
|
-
}
|
|
1137
1106
|
}
|
|
1138
1107
|
};
|
|
1139
1108
|
|
|
@@ -1146,10 +1115,6 @@ var ObservedOutboundTrack = class {
|
|
|
1146
1115
|
this._peerConnection = _peerConnection;
|
|
1147
1116
|
this._outboundRtps = _outboundRtps;
|
|
1148
1117
|
this._mediaSource = _mediaSource;
|
|
1149
|
-
this.report = {
|
|
1150
|
-
trackId: this.id,
|
|
1151
|
-
kind: this.kind
|
|
1152
|
-
};
|
|
1153
1118
|
}
|
|
1154
1119
|
timestamp;
|
|
1155
1120
|
id;
|
|
@@ -1159,7 +1124,7 @@ var ObservedOutboundTrack = class {
|
|
|
1159
1124
|
_mediaSource;
|
|
1160
1125
|
_visited = false;
|
|
1161
1126
|
appData;
|
|
1162
|
-
|
|
1127
|
+
remoteInboundTracks = /* @__PURE__ */ new Set();
|
|
1163
1128
|
calculatedScore = {
|
|
1164
1129
|
weight: 1,
|
|
1165
1130
|
value: void 0
|
|
@@ -1185,10 +1150,6 @@ var ObservedOutboundTrack = class {
|
|
|
1185
1150
|
getMediaSource() {
|
|
1186
1151
|
return this._mediaSource;
|
|
1187
1152
|
}
|
|
1188
|
-
getRemoteInboundTracks() {
|
|
1189
|
-
var _a;
|
|
1190
|
-
return (_a = this._peerConnection.client.call.remoteTrackResolver) == null ? void 0 : _a.resolveRemoteInboundTracks(this);
|
|
1191
|
-
}
|
|
1192
1153
|
update(stats) {
|
|
1193
1154
|
this._visited = true;
|
|
1194
1155
|
this.timestamp = stats.timestamp;
|
|
@@ -1364,10 +1325,7 @@ var ObservedPeerConnection = class extends EventEmitter {
|
|
|
1364
1325
|
}
|
|
1365
1326
|
get selectedIceCandiadtePairForTurn() {
|
|
1366
1327
|
return this.selectedIceCandidatePairs.filter(
|
|
1367
|
-
(pair) =>
|
|
1368
|
-
var _a, _b, _c;
|
|
1369
|
-
return ((_a = pair.getLocalCandidate()) == null ? void 0 : _a.candidateType) === "relay" && ((_c = (_b = pair.getRemoteCandidate()) == null ? void 0 : _b.url) == null ? void 0 : _c.startsWith("turn:"));
|
|
1370
|
-
}
|
|
1328
|
+
(pair) => pair.getLocalCandidate()?.candidateType === "relay" && pair.getRemoteCandidate()?.url?.startsWith("turn:")
|
|
1371
1329
|
);
|
|
1372
1330
|
}
|
|
1373
1331
|
close() {
|
|
@@ -1415,7 +1373,6 @@ var ObservedPeerConnection = class extends EventEmitter {
|
|
|
1415
1373
|
this._notify("peer-connection-closed", { ...this.eventScope });
|
|
1416
1374
|
}
|
|
1417
1375
|
accept(sample, context) {
|
|
1418
|
-
var _a, _b, _c, _d, _e;
|
|
1419
1376
|
if (this.closed) return;
|
|
1420
1377
|
this._visited = true;
|
|
1421
1378
|
if (context) this.appData = { ...this.appData, ...context };
|
|
@@ -1641,10 +1598,10 @@ var ObservedPeerConnection = class extends EventEmitter {
|
|
|
1641
1598
|
this.usingTCP = false;
|
|
1642
1599
|
this.usingTURN = false;
|
|
1643
1600
|
for (const selectedCandidatePair of selectedIceCandidatePairs) {
|
|
1644
|
-
if (
|
|
1601
|
+
if (selectedCandidatePair.getLocalCandidate()?.protocol === "tcp") {
|
|
1645
1602
|
this.usingTCP = true;
|
|
1646
1603
|
}
|
|
1647
|
-
if (
|
|
1604
|
+
if (selectedCandidatePair.getLocalCandidate()?.candidateType === "relay" && selectedCandidatePair.getRemoteCandidate()?.url?.startsWith("turn:")) {
|
|
1648
1605
|
selectedCandidatePairForTurn.push(selectedCandidatePair);
|
|
1649
1606
|
this.usingTURN = true;
|
|
1650
1607
|
}
|
|
@@ -1655,7 +1612,7 @@ var ObservedPeerConnection = class extends EventEmitter {
|
|
|
1655
1612
|
if (!this.observedTurnServer) {
|
|
1656
1613
|
this.observedTurnServer = this.client.call.observer.observedTURN.addPeerConnection(this);
|
|
1657
1614
|
}
|
|
1658
|
-
|
|
1615
|
+
this.observedTurnServer?.updateTurnUsage(...selectedCandidatePairForTurn);
|
|
1659
1616
|
} else if (wasUsingTURN) {
|
|
1660
1617
|
if (!this.usingTURN) {
|
|
1661
1618
|
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
@@ -1995,7 +1952,7 @@ var ObservedPeerConnection = class extends EventEmitter {
|
|
|
1995
1952
|
);
|
|
1996
1953
|
}
|
|
1997
1954
|
const observedMediaSource = [...this.observedMediaSources.values()].find((mediaSource) => mediaSource.trackIdentifier === stats.id);
|
|
1998
|
-
const outboundRtps = observedMediaSource ? [...this.observedOutboundRtps.values()].filter((outboundRtp) => outboundRtp.mediaSourceId ===
|
|
1955
|
+
const outboundRtps = observedMediaSource ? [...this.observedOutboundRtps.values()].filter((outboundRtp) => outboundRtp.mediaSourceId === observedMediaSource?.id) : void 0;
|
|
1999
1956
|
observedOutboundTrack = new ObservedOutboundTrack(
|
|
2000
1957
|
stats.timestamp,
|
|
2001
1958
|
stats.id,
|
|
@@ -2142,60 +2099,19 @@ var ClientMetaTypes = /* @__PURE__ */ ((ClientMetaTypes2) => {
|
|
|
2142
2099
|
var logger2 = createLogger("ObservedClient");
|
|
2143
2100
|
var ObservedClient = class extends EventEmitter2 {
|
|
2144
2101
|
constructor(settings, call) {
|
|
2145
|
-
var _a, _b;
|
|
2146
2102
|
super();
|
|
2147
2103
|
this.call = call;
|
|
2148
2104
|
this.setMaxListeners(Infinity);
|
|
2149
2105
|
this.eventScope = { observer: call.observer, observedCall: call, observedClient: this };
|
|
2150
|
-
this.sink =
|
|
2106
|
+
this.sink = call.observer.config.createClientSink?.({ clientId: settings.clientId, observedCall: call });
|
|
2151
2107
|
this.clientId = settings.clientId;
|
|
2152
2108
|
this.appData = settings.appData ?? {};
|
|
2153
2109
|
this.settings = {
|
|
2154
2110
|
closeClientIfIdleForMs: settings.closeClientIfIdleForMs
|
|
2155
2111
|
};
|
|
2156
|
-
this.report = {
|
|
2157
|
-
callId: this.call.callId,
|
|
2158
|
-
clientId: this.clientId,
|
|
2159
|
-
rttDistribution: {
|
|
2160
|
-
gtOrEq300ms: 0,
|
|
2161
|
-
lt50ms: 0,
|
|
2162
|
-
lt150ms: 0,
|
|
2163
|
-
lt300ms: 0,
|
|
2164
|
-
count: 0,
|
|
2165
|
-
sum: 0
|
|
2166
|
-
},
|
|
2167
|
-
scoreDistribution: {
|
|
2168
|
-
"0": 0,
|
|
2169
|
-
"1": 0,
|
|
2170
|
-
"2": 0,
|
|
2171
|
-
"3": 0,
|
|
2172
|
-
"4": 0,
|
|
2173
|
-
"5": 0,
|
|
2174
|
-
count: 0,
|
|
2175
|
-
sum: 0
|
|
2176
|
-
},
|
|
2177
|
-
issues: {},
|
|
2178
|
-
totalAudioBytesReceived: 0,
|
|
2179
|
-
totalVideoBytesReceived: 0,
|
|
2180
|
-
totalAudioBytesSent: 0,
|
|
2181
|
-
totalVideoBytesSent: 0,
|
|
2182
|
-
totalDataChannelBytesReceived: 0,
|
|
2183
|
-
totalDataChannelBytesSent: 0,
|
|
2184
|
-
totalDataChannelMessagesReceived: 0,
|
|
2185
|
-
totalDataChannelMessagesSent: 0,
|
|
2186
|
-
totalInboundRtpBytesReceived: 0,
|
|
2187
|
-
totalInboundRtpPacketsLost: 0,
|
|
2188
|
-
totalInboundRtpPacketsReceived: 0,
|
|
2189
|
-
totalOutboundRtpBytesSent: 0,
|
|
2190
|
-
totalOutboundRtpPacketsSent: 0,
|
|
2191
|
-
totalNumberOfIssues: 0
|
|
2192
|
-
};
|
|
2193
2112
|
if (this.sink) {
|
|
2194
2113
|
const onError = (err) => logger2.warn("ClientSampleSink error for client %s: %o", this.clientId, err);
|
|
2195
|
-
this.sink.once("close", () =>
|
|
2196
|
-
var _a2;
|
|
2197
|
-
return (_a2 = this.sink) == null ? void 0 : _a2.off("error", onError);
|
|
2198
|
-
});
|
|
2114
|
+
this.sink.once("close", () => this.sink?.off("error", onError));
|
|
2199
2115
|
this.sink.on("error", onError);
|
|
2200
2116
|
}
|
|
2201
2117
|
}
|
|
@@ -2263,7 +2179,6 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2263
2179
|
totalScoreSum = 0;
|
|
2264
2180
|
numberOfScoreMeasurements = 0;
|
|
2265
2181
|
// public totalNumberOfIssues = 0;
|
|
2266
|
-
report;
|
|
2267
2182
|
mediaDevices = [];
|
|
2268
2183
|
issues = [];
|
|
2269
2184
|
_injections = {};
|
|
@@ -2275,13 +2190,12 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2275
2190
|
return this.calculatedScore.value;
|
|
2276
2191
|
}
|
|
2277
2192
|
close() {
|
|
2278
|
-
var _a, _b, _c, _d, _e;
|
|
2279
2193
|
if (this.closed) return;
|
|
2280
2194
|
this.closed = true;
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2195
|
+
this._injections.clientEvents?.forEach((clientEvent) => this._processClientEvent(clientEvent));
|
|
2196
|
+
this._injections.clientIssues?.forEach((clientIssue) => this.addIssue(clientIssue));
|
|
2197
|
+
this._injections.extensionStats?.forEach((extensionStat) => this.addExtensionStats(extensionStat));
|
|
2198
|
+
this._injections.clientMetaItems?.forEach((clientMetaItem) => this.addMetadata(clientMetaItem));
|
|
2285
2199
|
Array.from(this.observedPeerConnections.values()).forEach((peerConnection) => peerConnection.close());
|
|
2286
2200
|
if (!this.leftAt) {
|
|
2287
2201
|
this.leftAt = this.lastSampleTimestamp;
|
|
@@ -2294,18 +2208,17 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2294
2208
|
this.emit("close");
|
|
2295
2209
|
this._notify("client-closed", { ...this.eventScope });
|
|
2296
2210
|
try {
|
|
2297
|
-
|
|
2211
|
+
this.sink?.end();
|
|
2298
2212
|
} catch (err) {
|
|
2299
2213
|
logger2.warn("ClientSampleSink.end failed for client %s: %o", this.clientId, err);
|
|
2300
2214
|
}
|
|
2301
2215
|
}
|
|
2302
2216
|
accept(sample, context) {
|
|
2303
|
-
var _a;
|
|
2304
2217
|
if (this.closed) {
|
|
2305
2218
|
logger2.warn("Attempted to accept a sample on a closed client %s", this.clientId);
|
|
2306
2219
|
return;
|
|
2307
2220
|
}
|
|
2308
|
-
|
|
2221
|
+
this.sink?.write(sample);
|
|
2309
2222
|
if (this.closeTimer) {
|
|
2310
2223
|
clearTimeout(this.closeTimer);
|
|
2311
2224
|
this.closeTimer = void 0;
|
|
@@ -2398,19 +2311,13 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2398
2311
|
}
|
|
2399
2312
|
if (observedPeerConnection.currentRttInMs < 50) {
|
|
2400
2313
|
this.deltaRttLt50Measurements += 1;
|
|
2401
|
-
this.report.rttDistribution.lt50ms += 1;
|
|
2402
2314
|
} else if (observedPeerConnection.currentRttInMs < 150) {
|
|
2403
2315
|
this.deltaRttLt150Measurements += 1;
|
|
2404
|
-
this.report.rttDistribution.lt150ms += 1;
|
|
2405
2316
|
} else if (observedPeerConnection.currentRttInMs < 300) {
|
|
2406
2317
|
this.deltaRttLt300Measurements += 1;
|
|
2407
|
-
this.report.rttDistribution.lt300ms += 1;
|
|
2408
2318
|
} else if (300 <= observedPeerConnection.currentRttInMs) {
|
|
2409
2319
|
this.deltaRttGtOrEq300Measurements += 1;
|
|
2410
|
-
this.report.rttDistribution.gtOrEq300ms += 1;
|
|
2411
2320
|
}
|
|
2412
|
-
this.report.rttDistribution.count += 1;
|
|
2413
|
-
this.report.rttDistribution.sum += observedPeerConnection.currentRttInMs;
|
|
2414
2321
|
sumOfRtts += observedPeerConnection.currentRttInMs;
|
|
2415
2322
|
++numberOfRttMeasurements;
|
|
2416
2323
|
}
|
|
@@ -2419,32 +2326,12 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2419
2326
|
this._processClientEvent(clientEvent);
|
|
2420
2327
|
}
|
|
2421
2328
|
this.attachments = sample.attachments;
|
|
2422
|
-
this.report.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
|
|
2423
|
-
this.report.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
|
|
2424
|
-
this.report.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
|
|
2425
|
-
this.report.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
|
|
2426
|
-
this.report.totalInboundRtpPacketsLost += this.deltaInboundPacketsLost;
|
|
2427
|
-
this.report.totalInboundRtpPacketsReceived += this.deltaInboundPacketsReceived;
|
|
2428
|
-
this.report.totalOutboundRtpPacketsSent += this.deltaOutboundPacketsSent;
|
|
2429
|
-
this.report.totalAudioBytesReceived += this.deltaReceivedAudioBytes;
|
|
2430
|
-
this.report.totalVideoBytesReceived += this.deltaReceivedVideoBytes;
|
|
2431
|
-
this.report.totalAudioBytesSent += this.deltaSentAudioBytes;
|
|
2432
|
-
this.report.totalVideoBytesSent += this.deltaSentVideoBytes;
|
|
2433
|
-
this.report.totalInboundRtpBytesReceived += this.deltaTransportReceivedBytes;
|
|
2434
|
-
this.report.totalOutboundRtpBytesSent += this.deltaTransportSentBytes;
|
|
2435
|
-
this.report.totalNumberOfIssues += this.deltaNumberOfIssues;
|
|
2436
2329
|
this.receivingAudioBitrate = this.deltaReceivedAudioBytes * 8 / elapsedInSeconds;
|
|
2437
2330
|
this.receivingVideoBitrate = this.deltaReceivedVideoBytes * 8 / elapsedInSeconds;
|
|
2438
2331
|
this.sendingAudioBitrate = this.deltaSentAudioBytes * 8 / elapsedInSeconds;
|
|
2439
2332
|
this.sendingVideoBitrate = this.deltaSentVideoBytes * 8 / elapsedInSeconds;
|
|
2440
2333
|
this.currentAvgRttInMs = 0 < numberOfRttMeasurements ? sumOfRtts / numberOfRttMeasurements : void 0;
|
|
2441
2334
|
this.calculatedScore.value = sample.score;
|
|
2442
|
-
if (sample.score !== void 0) {
|
|
2443
|
-
const bucket = Math.floor(sample.score).toString();
|
|
2444
|
-
this.report.scoreDistribution[bucket] = (this.report.scoreDistribution[bucket] ?? 0) + 1;
|
|
2445
|
-
this.report.scoreDistribution.count += 1;
|
|
2446
|
-
this.report.scoreDistribution.sum += sample.score;
|
|
2447
|
-
}
|
|
2448
2335
|
this.lastSampleTimestamp = sample.timestamp;
|
|
2449
2336
|
const elapsedTimeInMs = now - this.updated;
|
|
2450
2337
|
this.emit("update", sample, elapsedTimeInMs, context);
|
|
@@ -2509,7 +2396,6 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2509
2396
|
}
|
|
2510
2397
|
addIssue(issue) {
|
|
2511
2398
|
if (this.closed) return;
|
|
2512
|
-
this.report.issues[issue.type] = (this.report.issues[issue.type] ?? 0) + 1;
|
|
2513
2399
|
this._notify("client-issue", { ...this.eventScope, issue });
|
|
2514
2400
|
}
|
|
2515
2401
|
addExtensionStats(stats) {
|
|
@@ -2548,7 +2434,7 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2548
2434
|
}
|
|
2549
2435
|
case "PEER_CONNECTION_OPENED" /* PEER_CONNECTION_OPENED */: {
|
|
2550
2436
|
const payload = parseJsonAs(event.payload);
|
|
2551
|
-
if (
|
|
2437
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string") {
|
|
2552
2438
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2553
2439
|
if (observedPeerConnection) {
|
|
2554
2440
|
observedPeerConnection.openedAt = event.timestamp;
|
|
@@ -2562,7 +2448,7 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2562
2448
|
}
|
|
2563
2449
|
case "PEER_CONNECTION_CLOSED" /* PEER_CONNECTION_CLOSED */: {
|
|
2564
2450
|
const payload = parseJsonAs(event.payload);
|
|
2565
|
-
if (
|
|
2451
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string") {
|
|
2566
2452
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2567
2453
|
if (observedPeerConnection) {
|
|
2568
2454
|
observedPeerConnection.closedAt = event.timestamp;
|
|
@@ -2576,9 +2462,9 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2576
2462
|
}
|
|
2577
2463
|
case "MEDIA_TRACK_ADDED" /* MEDIA_TRACK_ADDED */: {
|
|
2578
2464
|
const payload = parseJsonAs(event.payload);
|
|
2579
|
-
if (
|
|
2465
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.trackId && typeof payload.trackId === "string") {
|
|
2580
2466
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2581
|
-
const observedTrack =
|
|
2467
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
2582
2468
|
if (observedTrack) {
|
|
2583
2469
|
observedTrack.addedAt = event.timestamp;
|
|
2584
2470
|
} else if (postBuffer) {
|
|
@@ -2591,9 +2477,9 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2591
2477
|
}
|
|
2592
2478
|
case "MEDIA_TRACK_REMOVED" /* MEDIA_TRACK_REMOVED */: {
|
|
2593
2479
|
const payload = parseJsonAs(event.payload);
|
|
2594
|
-
if (
|
|
2480
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.trackId && typeof payload.trackId === "string") {
|
|
2595
2481
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2596
|
-
const observedTrack =
|
|
2482
|
+
const observedTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId) ?? observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
2597
2483
|
if (observedTrack) {
|
|
2598
2484
|
observedTrack.removedAt = event.timestamp;
|
|
2599
2485
|
} else if (postBuffer) {
|
|
@@ -2606,9 +2492,9 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2606
2492
|
}
|
|
2607
2493
|
case "DATA_CHANNEL_OPEN" /* DATA_CHANNEL_OPEN */: {
|
|
2608
2494
|
const payload = parseJsonAs(event.payload);
|
|
2609
|
-
if (
|
|
2495
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.dataChannelId && typeof payload.dataChannelId === "string") {
|
|
2610
2496
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2611
|
-
const observedDataChannel = observedPeerConnection
|
|
2497
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
2612
2498
|
if (observedDataChannel) {
|
|
2613
2499
|
observedDataChannel.addedAt = event.timestamp;
|
|
2614
2500
|
} else if (postBuffer) {
|
|
@@ -2621,9 +2507,9 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2621
2507
|
}
|
|
2622
2508
|
case "DATA_CHANNEL_CLOSED" /* DATA_CHANNEL_CLOSED */: {
|
|
2623
2509
|
const payload = parseJsonAs(event.payload);
|
|
2624
|
-
if (
|
|
2510
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.dataChannelId && typeof payload.dataChannelId === "string") {
|
|
2625
2511
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2626
|
-
const observedDataChannel = observedPeerConnection
|
|
2512
|
+
const observedDataChannel = observedPeerConnection?.observedDataChannels.get(payload.dataChannelId);
|
|
2627
2513
|
if (observedDataChannel) {
|
|
2628
2514
|
observedDataChannel.removedAt = event.timestamp;
|
|
2629
2515
|
} else if (postBuffer) {
|
|
@@ -2636,10 +2522,10 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2636
2522
|
}
|
|
2637
2523
|
case "MEDIA_TRACK_MUTED" /* MEDIA_TRACK_MUTED */: {
|
|
2638
2524
|
const payload = parseJsonAs(event.payload);
|
|
2639
|
-
if (
|
|
2525
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.trackId && typeof payload.trackId === "string") {
|
|
2640
2526
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2641
|
-
const observedInboundTrack = observedPeerConnection
|
|
2642
|
-
const observedOutboundTrack = observedPeerConnection
|
|
2527
|
+
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
|
|
2528
|
+
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
2643
2529
|
if (observedPeerConnection) {
|
|
2644
2530
|
if (observedInboundTrack) {
|
|
2645
2531
|
observedInboundTrack.muted = true;
|
|
@@ -2658,10 +2544,10 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2658
2544
|
}
|
|
2659
2545
|
case "MEDIA_TRACK_UNMUTED" /* MEDIA_TRACK_UNMUTED */: {
|
|
2660
2546
|
const payload = parseJsonAs(event.payload);
|
|
2661
|
-
if (
|
|
2547
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.trackId && typeof payload.trackId === "string") {
|
|
2662
2548
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2663
|
-
const observedInboundTrack = observedPeerConnection
|
|
2664
|
-
const observedOutboundTrack = observedPeerConnection
|
|
2549
|
+
const observedInboundTrack = observedPeerConnection?.observedInboundTracks.get(payload.trackId);
|
|
2550
|
+
const observedOutboundTrack = observedPeerConnection?.observedOutboundTracks.get(payload.trackId);
|
|
2665
2551
|
if (observedPeerConnection) {
|
|
2666
2552
|
if (observedInboundTrack) {
|
|
2667
2553
|
observedInboundTrack.muted = false;
|
|
@@ -2680,7 +2566,7 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2680
2566
|
}
|
|
2681
2567
|
case "ICE_CONNECTION_STATE_CHANGED" /* ICE_CONNECTION_STATE_CHANGED */: {
|
|
2682
2568
|
const payload = parseJsonAs(event.payload);
|
|
2683
|
-
if (
|
|
2569
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.iceConnectionState && typeof payload.iceConnectionState === "string") {
|
|
2684
2570
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2685
2571
|
if (observedPeerConnection) {
|
|
2686
2572
|
observedPeerConnection.iceConnectionState = payload.iceConnectionState;
|
|
@@ -2695,7 +2581,7 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2695
2581
|
}
|
|
2696
2582
|
case "ICE_GATHERING_STATE_CHANGED" /* ICE_GATHERING_STATE_CHANGED */: {
|
|
2697
2583
|
const payload = parseJsonAs(event.payload);
|
|
2698
|
-
if (
|
|
2584
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.iceGatheringState && typeof payload.iceGatheringState === "string") {
|
|
2699
2585
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2700
2586
|
if (observedPeerConnection) {
|
|
2701
2587
|
observedPeerConnection.iceGatheringState = payload.iceGatheringState;
|
|
@@ -2710,7 +2596,7 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2710
2596
|
}
|
|
2711
2597
|
case "PEER_CONNECTION_STATE_CHANGED" /* PEER_CONNECTION_STATE_CHANGED */: {
|
|
2712
2598
|
const payload = parseJsonAs(event.payload);
|
|
2713
|
-
if (
|
|
2599
|
+
if (payload?.peerConnectionId && typeof payload.peerConnectionId === "string" && payload?.peerConnectionState && typeof payload.peerConnectionState === "string") {
|
|
2714
2600
|
const observedPeerConnection = this.observedPeerConnections.get(payload.peerConnectionId);
|
|
2715
2601
|
if (observedPeerConnection) {
|
|
2716
2602
|
observedPeerConnection.connectionState = payload.peerConnectionState;
|
|
@@ -2736,31 +2622,9 @@ var ObservedClient = class extends EventEmitter2 {
|
|
|
2736
2622
|
), void 0;
|
|
2737
2623
|
}
|
|
2738
2624
|
const newObservedPeerConnection = new ObservedPeerConnection(sample.peerConnectionId, this);
|
|
2739
|
-
const onInboundTrackRemoved = (track) => {
|
|
2740
|
-
this._notify("client-track-report", {
|
|
2741
|
-
...this.eventScope,
|
|
2742
|
-
report: {
|
|
2743
|
-
direction: "inbound",
|
|
2744
|
-
...track.report
|
|
2745
|
-
}
|
|
2746
|
-
});
|
|
2747
|
-
};
|
|
2748
|
-
const onOutboundTrackRemoved = (track) => {
|
|
2749
|
-
this._notify("client-track-report", {
|
|
2750
|
-
...this.eventScope,
|
|
2751
|
-
report: {
|
|
2752
|
-
direction: "outbound",
|
|
2753
|
-
...track.report
|
|
2754
|
-
}
|
|
2755
|
-
});
|
|
2756
|
-
};
|
|
2757
2625
|
newObservedPeerConnection.once("close", () => {
|
|
2758
|
-
newObservedPeerConnection == null ? void 0 : newObservedPeerConnection.off("removed-inbound-track", onInboundTrackRemoved);
|
|
2759
|
-
newObservedPeerConnection == null ? void 0 : newObservedPeerConnection.off("removed-outbound-track", onOutboundTrackRemoved);
|
|
2760
2626
|
this.observedPeerConnections.delete(sample.peerConnectionId);
|
|
2761
2627
|
});
|
|
2762
|
-
newObservedPeerConnection.on("removed-inbound-track", onInboundTrackRemoved);
|
|
2763
|
-
newObservedPeerConnection.on("removed-outbound-track", onOutboundTrackRemoved);
|
|
2764
2628
|
this.observedPeerConnections.set(sample.peerConnectionId, newObservedPeerConnection);
|
|
2765
2629
|
this._notify("peer-connection-added", { ...this.eventScope, observedPeerConnection: newObservedPeerConnection });
|
|
2766
2630
|
observedPeerConnection = newObservedPeerConnection;
|
|
@@ -2867,21 +2731,6 @@ var OnAllClientCallUpdater = class {
|
|
|
2867
2731
|
}
|
|
2868
2732
|
};
|
|
2869
2733
|
|
|
2870
|
-
// src/updaters/OnIntervalUpdater.ts
|
|
2871
|
-
var OnIntervalUpdater = class {
|
|
2872
|
-
constructor(intervalInMs, _update) {
|
|
2873
|
-
this._update = _update;
|
|
2874
|
-
this.timer = setInterval(() => this._update(), intervalInMs);
|
|
2875
|
-
}
|
|
2876
|
-
_update;
|
|
2877
|
-
name = "OnIntervalUpdater";
|
|
2878
|
-
description = "Call the update() method given in the constructor once the interval elapsed";
|
|
2879
|
-
timer;
|
|
2880
|
-
close() {
|
|
2881
|
-
clearInterval(this.timer);
|
|
2882
|
-
}
|
|
2883
|
-
};
|
|
2884
|
-
|
|
2885
2734
|
// src/updaters/OnAnyClientCallUpdater.ts
|
|
2886
2735
|
var OnAnyClientCallUpdater = class {
|
|
2887
2736
|
constructor(_observedCall) {
|
|
@@ -2934,7 +2783,7 @@ var Detectors = class {
|
|
|
2934
2783
|
try {
|
|
2935
2784
|
detector.update();
|
|
2936
2785
|
} catch (err) {
|
|
2937
|
-
logger3.warn(`Error updating detector ${detector
|
|
2786
|
+
logger3.warn(`Error updating detector ${detector?.name}`, err);
|
|
2938
2787
|
}
|
|
2939
2788
|
}
|
|
2940
2789
|
}
|
|
@@ -2955,9 +2804,6 @@ var ObservedCall = class extends EventEmitter3 {
|
|
|
2955
2804
|
this.appData = settings.appData ?? {};
|
|
2956
2805
|
this.scoreCalculator = new DefaultCallScoreCalculator(this);
|
|
2957
2806
|
this.detectors = new Detectors();
|
|
2958
|
-
if (settings.updateIntervalInMs && settings.updatePolicy !== "update-on-interval") {
|
|
2959
|
-
logger4.warn('updateIntervalInMs is ignored unless updatePolicy is "update-on-interval" (callId: %s)', settings.callId);
|
|
2960
|
-
}
|
|
2961
2807
|
switch (settings.updatePolicy) {
|
|
2962
2808
|
case "update-on-any-client-updated":
|
|
2963
2809
|
this.updater = new OnAnyClientCallUpdater(this);
|
|
@@ -2965,17 +2811,6 @@ var ObservedCall = class extends EventEmitter3 {
|
|
|
2965
2811
|
case "update-when-all-client-updated":
|
|
2966
2812
|
this.updater = new OnAllClientCallUpdater(this);
|
|
2967
2813
|
break;
|
|
2968
|
-
case "update-on-interval":
|
|
2969
|
-
if (!settings.updateIntervalInMs) {
|
|
2970
|
-
logger4.warn('updateIntervalInMs must be set when updatePolicy is "update-on-interval"; falling back to "update-when-all-client-updated" (callId: %s)', settings.callId);
|
|
2971
|
-
this.updater = new OnAllClientCallUpdater(this);
|
|
2972
|
-
} else {
|
|
2973
|
-
this.updater = new OnIntervalUpdater(
|
|
2974
|
-
settings.updateIntervalInMs,
|
|
2975
|
-
this.update.bind(this)
|
|
2976
|
-
);
|
|
2977
|
-
}
|
|
2978
|
-
break;
|
|
2979
2814
|
}
|
|
2980
2815
|
this.settings = {
|
|
2981
2816
|
closeCallIfEmptyForMs: settings.closeCallIfEmptyForMs
|
|
@@ -3027,11 +2862,10 @@ var ObservedCall = class extends EventEmitter3 {
|
|
|
3027
2862
|
this._notify("call-issue", { ...this.eventScope, issue });
|
|
3028
2863
|
}
|
|
3029
2864
|
close() {
|
|
3030
|
-
var _a;
|
|
3031
2865
|
if (this.closed) return;
|
|
3032
2866
|
this.update();
|
|
3033
2867
|
this.closed = true;
|
|
3034
|
-
|
|
2868
|
+
this.updater?.close();
|
|
3035
2869
|
let minSampleTimestamps;
|
|
3036
2870
|
let maxSampleTimestamps;
|
|
3037
2871
|
for (const client of this.observedClients.values()) {
|
|
@@ -3050,7 +2884,6 @@ var ObservedCall = class extends EventEmitter3 {
|
|
|
3050
2884
|
return this.observedClients.get(clientId);
|
|
3051
2885
|
}
|
|
3052
2886
|
createObservedClient(settings) {
|
|
3053
|
-
var _a, _b;
|
|
3054
2887
|
if (this.closed) {
|
|
3055
2888
|
logger4.warn("Attempted to create a client (clientId: %s) on a closed call %s", settings.clientId, this.callId);
|
|
3056
2889
|
return void 0;
|
|
@@ -3063,7 +2896,7 @@ var ObservedCall = class extends EventEmitter3 {
|
|
|
3063
2896
|
settings.closeClientIfIdleForMs = this.observer.config.closeClientIfIdleForMs;
|
|
3064
2897
|
}
|
|
3065
2898
|
if (settings.appData === void 0) {
|
|
3066
|
-
settings.appData =
|
|
2899
|
+
settings.appData = this.observer.config.createClientAppData?.({ clientId: settings.clientId, observedCall: this });
|
|
3067
2900
|
}
|
|
3068
2901
|
const result = new ObservedClient(settings, this);
|
|
3069
2902
|
const wasEmpty = this.observedClients.size === 0;
|
|
@@ -3241,16 +3074,12 @@ var ObservedTURN = class extends EventEmitter4 {
|
|
|
3241
3074
|
this.numberOfClients = clientIds.size;
|
|
3242
3075
|
}
|
|
3243
3076
|
addPeerConnection(peerConnection) {
|
|
3244
|
-
|
|
3245
|
-
const turnPairs = peerConnection.selectedIceCandidatePairs.filter((pair) => {
|
|
3246
|
-
var _a2, _b, _c;
|
|
3247
|
-
return ((_a2 = pair.getLocalCandidate()) == null ? void 0 : _a2.candidateType) === "relay" && ((_c = (_b = pair.getRemoteCandidate()) == null ? void 0 : _b.url) == null ? void 0 : _c.startsWith("turn:"));
|
|
3248
|
-
});
|
|
3077
|
+
const turnPairs = peerConnection.selectedIceCandidatePairs.filter((pair) => pair.getLocalCandidate()?.candidateType === "relay" && pair.getRemoteCandidate()?.url?.startsWith("turn:"));
|
|
3249
3078
|
if (turnPairs.length !== 1) {
|
|
3250
3079
|
return logger5.warn(`Expected exactly one TURN pair, but found for peerconnection ${peerConnection.peerConnectionId}`, turnPairs.length), void 0;
|
|
3251
3080
|
}
|
|
3252
3081
|
const candidatePair = turnPairs[0];
|
|
3253
|
-
const rawUrl =
|
|
3082
|
+
const rawUrl = candidatePair.getRemoteCandidate()?.url;
|
|
3254
3083
|
if (!rawUrl) {
|
|
3255
3084
|
return logger5.warn(`No remote candidate URL found for peerconnection ${peerConnection.peerConnectionId}`), void 0;
|
|
3256
3085
|
}
|
|
@@ -3343,122 +3172,60 @@ var OnAnyCallObserverUpdater = class {
|
|
|
3343
3172
|
}
|
|
3344
3173
|
};
|
|
3345
3174
|
|
|
3346
|
-
// src/
|
|
3347
|
-
var
|
|
3348
|
-
constructor(
|
|
3349
|
-
this.
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
});
|
|
3373
|
-
}
|
|
3374
|
-
observedCall;
|
|
3375
|
-
_consumerIdToProducerId = /* @__PURE__ */ new Map();
|
|
3376
|
-
_producerIdToOutboundTrack = /* @__PURE__ */ new Map();
|
|
3377
|
-
_consumerIdToInboundTrack = /* @__PURE__ */ new Map();
|
|
3378
|
-
// private _producerIdToOutboundTrack = new Map<string, ObservedOutboundTrack>();
|
|
3379
|
-
_inboundTrackToConsumerId = /* @__PURE__ */ new Map();
|
|
3380
|
-
_producerIdToConsumerIds = /* @__PURE__ */ new Map();
|
|
3381
|
-
_outboundTrackToProducerId = /* @__PURE__ */ new Map();
|
|
3382
|
-
resolveRemoteOutboundTrack(inboundTrack) {
|
|
3383
|
-
const consumerId = this._inboundTrackToConsumerId.get(inboundTrack.id);
|
|
3384
|
-
if (!consumerId) return;
|
|
3385
|
-
const producerId = this._consumerIdToProducerId.get(consumerId);
|
|
3386
|
-
if (!producerId) return;
|
|
3387
|
-
return this._producerIdToOutboundTrack.get(producerId);
|
|
3388
|
-
}
|
|
3389
|
-
resolveRemoteInboundTracks(outboundTrack) {
|
|
3390
|
-
const producerId = this._outboundTrackToProducerId.get(outboundTrack.id);
|
|
3391
|
-
if (!producerId) return;
|
|
3392
|
-
const consumerIds = this._producerIdToConsumerIds.get(producerId);
|
|
3393
|
-
if (!consumerIds) return;
|
|
3394
|
-
return consumerIds.map((consumerId) => this._consumerIdToInboundTrack.get(consumerId)).filter((inboundTrack) => Boolean(inboundTrack));
|
|
3175
|
+
// src/common/Middleware.ts
|
|
3176
|
+
var Executor = class {
|
|
3177
|
+
constructor(stack, finalCallback) {
|
|
3178
|
+
this.stack = stack;
|
|
3179
|
+
this.finalCallback = finalCallback;
|
|
3180
|
+
}
|
|
3181
|
+
stack;
|
|
3182
|
+
finalCallback;
|
|
3183
|
+
done = false;
|
|
3184
|
+
index = 0;
|
|
3185
|
+
prevIndex = -1;
|
|
3186
|
+
// Executes the middleware stack
|
|
3187
|
+
execute(input) {
|
|
3188
|
+
if (this.index <= this.prevIndex) {
|
|
3189
|
+
throw new Error("Middleware must call next() only once!");
|
|
3190
|
+
} else if (this.done) {
|
|
3191
|
+
throw new Error("Middleware stack has already been executed!");
|
|
3192
|
+
}
|
|
3193
|
+
this.prevIndex = this.index;
|
|
3194
|
+
const middleware = this.stack[this.index];
|
|
3195
|
+
this.index++;
|
|
3196
|
+
if (middleware) {
|
|
3197
|
+
return middleware(input, (nextInput) => this.execute(nextInput));
|
|
3198
|
+
}
|
|
3199
|
+
this.done = true;
|
|
3200
|
+
this.finalCallback?.(input);
|
|
3395
3201
|
}
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
this
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
if (
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
const consumerId = this._inboundTrackToConsumerId.get(inboundTrack.id);
|
|
3415
|
-
if (!consumerId) return;
|
|
3416
|
-
this._inboundTrackToConsumerId.delete(inboundTrack.id);
|
|
3417
|
-
this._consumerIdToProducerId.delete(consumerId);
|
|
3418
|
-
this._consumerIdToInboundTrack.delete(consumerId);
|
|
3419
|
-
const producerConsumers = this._producerIdToConsumerIds.get(consumerId);
|
|
3420
|
-
if (!producerConsumers) return;
|
|
3421
|
-
const filteredProducerConsumers = producerConsumers.filter((id) => id !== consumerId);
|
|
3422
|
-
if (filteredProducerConsumers.length === 0) {
|
|
3423
|
-
this._producerIdToConsumerIds.delete(consumerId);
|
|
3424
|
-
} else {
|
|
3425
|
-
this._producerIdToConsumerIds.set(consumerId, filteredProducerConsumers);
|
|
3202
|
+
};
|
|
3203
|
+
var MiddlewareProcessor = class {
|
|
3204
|
+
stack = [];
|
|
3205
|
+
finalCallback;
|
|
3206
|
+
addMiddleware(...middlewares) {
|
|
3207
|
+
if (middlewares && middlewares.length > 0) {
|
|
3208
|
+
this.stack.push(...middlewares);
|
|
3209
|
+
}
|
|
3210
|
+
return this;
|
|
3211
|
+
}
|
|
3212
|
+
removeMiddleware(...middlewares) {
|
|
3213
|
+
if (middlewares && middlewares.length > 0) {
|
|
3214
|
+
for (const middleware of middlewares) {
|
|
3215
|
+
const index = this.stack.indexOf(middleware);
|
|
3216
|
+
if (index >= 0) {
|
|
3217
|
+
this.stack.splice(index, 1);
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3426
3220
|
}
|
|
3221
|
+
return this;
|
|
3427
3222
|
}
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
this._producerIdToOutboundTrack.set(producerId, outboundTrack);
|
|
3435
|
-
this._outboundTrackToProducerId.set(outboundTrack.id, producerId);
|
|
3436
|
-
}
|
|
3437
|
-
_removeOutboundTrack(outboundTrack) {
|
|
3438
|
-
const producerId = this._outboundTrackToProducerId.get(outboundTrack.id);
|
|
3439
|
-
if (!producerId) return;
|
|
3440
|
-
this._producerIdToOutboundTrack.delete(producerId);
|
|
3441
|
-
this._outboundTrackToProducerId.delete(outboundTrack.id);
|
|
3442
|
-
}
|
|
3443
|
-
_getInboundTrackAttachments(inboundTrack) {
|
|
3444
|
-
const {
|
|
3445
|
-
producerId,
|
|
3446
|
-
consumerId
|
|
3447
|
-
} = inboundTrack.attachments ?? {};
|
|
3448
|
-
if (!producerId || !consumerId || typeof producerId !== "string" || typeof consumerId !== "string") return;
|
|
3449
|
-
return {
|
|
3450
|
-
producerId,
|
|
3451
|
-
consumerId
|
|
3452
|
-
};
|
|
3453
|
-
}
|
|
3454
|
-
_getOutboundTrackAttachments(outboundTrack) {
|
|
3455
|
-
const {
|
|
3456
|
-
producerId
|
|
3457
|
-
} = outboundTrack.attachments ?? {};
|
|
3458
|
-
if (!producerId || typeof producerId !== "string") return;
|
|
3459
|
-
return {
|
|
3460
|
-
producerId
|
|
3461
|
-
};
|
|
3223
|
+
process(value) {
|
|
3224
|
+
if (this.stack.length === 0) {
|
|
3225
|
+
return this.finalCallback?.(value);
|
|
3226
|
+
}
|
|
3227
|
+
const executor = new Executor(this.stack, this.finalCallback);
|
|
3228
|
+
executor.execute(value);
|
|
3462
3229
|
}
|
|
3463
3230
|
};
|
|
3464
3231
|
|
|
@@ -3473,7 +3240,7 @@ var Observer = class extends EventEmitter5 {
|
|
|
3473
3240
|
this.config = config;
|
|
3474
3241
|
this.setMaxListeners(Infinity);
|
|
3475
3242
|
this.update = this.update.bind(this);
|
|
3476
|
-
const currentUpdatePolicy =
|
|
3243
|
+
const currentUpdatePolicy = config?.updatePolicy ?? "update-when-all-call-updated";
|
|
3477
3244
|
switch (currentUpdatePolicy) {
|
|
3478
3245
|
case "update-on-any-call-updated":
|
|
3479
3246
|
this.updater = new OnAnyCallObserverUpdater(this);
|
|
@@ -3481,19 +3248,6 @@ var Observer = class extends EventEmitter5 {
|
|
|
3481
3248
|
case "update-when-all-call-updated":
|
|
3482
3249
|
this.updater = new OnAllCallObserverUpdater(this);
|
|
3483
3250
|
break;
|
|
3484
|
-
case "update-on-interval": {
|
|
3485
|
-
const interval = config == null ? void 0 : config.updateIntervalInMs;
|
|
3486
|
-
if (!interval) {
|
|
3487
|
-
logger6.warn('updateIntervalInMs must be set when updatePolicy is "update-on-interval"; falling back to "update-when-all-call-updated"');
|
|
3488
|
-
this.updater = new OnAllCallObserverUpdater(this);
|
|
3489
|
-
} else {
|
|
3490
|
-
this.updater = new OnIntervalUpdater(
|
|
3491
|
-
interval,
|
|
3492
|
-
this.update.bind(this)
|
|
3493
|
-
);
|
|
3494
|
-
}
|
|
3495
|
-
break;
|
|
3496
|
-
}
|
|
3497
3251
|
}
|
|
3498
3252
|
}
|
|
3499
3253
|
config;
|
|
@@ -3511,7 +3265,8 @@ var Observer = class extends EventEmitter5 {
|
|
|
3511
3265
|
numberOfOutboundRtpStreams = 0;
|
|
3512
3266
|
numberOfDataChannels = 0;
|
|
3513
3267
|
numberOfPeerConnections = 0;
|
|
3514
|
-
|
|
3268
|
+
/** Global, pre-dispatch middleware chain run on every accepted sample. */
|
|
3269
|
+
acceptMiddlewares = new MiddlewareProcessor();
|
|
3515
3270
|
get numberOfCalls() {
|
|
3516
3271
|
return this.observedCalls.size;
|
|
3517
3272
|
}
|
|
@@ -3523,7 +3278,6 @@ var Observer = class extends EventEmitter5 {
|
|
|
3523
3278
|
return this.observedCalls.get(callId);
|
|
3524
3279
|
}
|
|
3525
3280
|
createObservedCall(settings) {
|
|
3526
|
-
var _a, _b;
|
|
3527
3281
|
if (this.closed) {
|
|
3528
3282
|
logger6.warn("Attempted to create a call (callId: %s) on a closed observer", settings.callId);
|
|
3529
3283
|
return void 0;
|
|
@@ -3535,14 +3289,11 @@ var Observer = class extends EventEmitter5 {
|
|
|
3535
3289
|
const callSettings = {
|
|
3536
3290
|
...settings,
|
|
3537
3291
|
updatePolicy: settings.updatePolicy ?? this.config.defaultCallUpdatePolicy,
|
|
3538
|
-
updateIntervalInMs: settings.updateIntervalInMs ?? this.config.defaultCallUpdateIntervalInMs,
|
|
3539
3292
|
closeCallIfEmptyForMs: settings.closeCallIfEmptyForMs ?? this.config.closeCallIfEmptyForMs,
|
|
3540
|
-
appData: settings.appData ??
|
|
3293
|
+
appData: settings.appData ?? this.config.createCallAppData?.({ callId: settings.callId, observer: this })
|
|
3541
3294
|
};
|
|
3542
3295
|
const observedCall = new ObservedCall(callSettings, this);
|
|
3543
|
-
|
|
3544
|
-
observedCall.remoteTrackResolver = new MediasoupRemoteTrackResolver(observedCall);
|
|
3545
|
-
}
|
|
3296
|
+
observedCall.remoteTrackResolver = this.config.createTrackResolver?.(observedCall);
|
|
3546
3297
|
observedCall.once("close", () => {
|
|
3547
3298
|
this.observedCalls.delete(observedCall.callId);
|
|
3548
3299
|
++this.totalRemovedCall;
|
|
@@ -3560,16 +3311,17 @@ var Observer = class extends EventEmitter5 {
|
|
|
3560
3311
|
return logger6.debug("Attempted to close twice");
|
|
3561
3312
|
}
|
|
3562
3313
|
this.closed = true;
|
|
3563
|
-
clearInterval(this._timer);
|
|
3564
|
-
this._timer = void 0;
|
|
3565
3314
|
this.observedCalls.forEach((call) => call.close());
|
|
3566
3315
|
this._notify("observer-closed", { ...this.eventScope });
|
|
3567
3316
|
}
|
|
3568
3317
|
accept(sample, context) {
|
|
3569
|
-
var _a, _b, _c, _d;
|
|
3570
3318
|
if (this.closed) {
|
|
3571
|
-
this._notify("sample-rejected", { ...this.eventScope, reason: "observer-closed", sample });
|
|
3572
|
-
|
|
3319
|
+
return this._notify("sample-rejected", { ...this.eventScope, reason: "observer-closed", sample });
|
|
3320
|
+
}
|
|
3321
|
+
try {
|
|
3322
|
+
this.acceptMiddlewares.process({ sample, context });
|
|
3323
|
+
} catch (err) {
|
|
3324
|
+
logger6.warn("An accept middleware threw; dropping the sample. %o", err);
|
|
3573
3325
|
}
|
|
3574
3326
|
if (!sample.callId) {
|
|
3575
3327
|
this._notify("sample-rejected", { ...this.eventScope, reason: "missing-callId", sample });
|
|
@@ -3583,7 +3335,7 @@ var Observer = class extends EventEmitter5 {
|
|
|
3583
3335
|
if (!call) {
|
|
3584
3336
|
call = this.createObservedCall({
|
|
3585
3337
|
callId: sample.callId,
|
|
3586
|
-
appData:
|
|
3338
|
+
appData: this.config.createCallAppData?.({ callId: sample.callId, observer: this })
|
|
3587
3339
|
});
|
|
3588
3340
|
}
|
|
3589
3341
|
if (!call) return;
|
|
@@ -3591,7 +3343,7 @@ var Observer = class extends EventEmitter5 {
|
|
|
3591
3343
|
if (!client) {
|
|
3592
3344
|
client = call.createObservedClient({
|
|
3593
3345
|
clientId: sample.clientId,
|
|
3594
|
-
appData:
|
|
3346
|
+
appData: this.config.createClientAppData?.({ clientId: sample.clientId, observedCall: call })
|
|
3595
3347
|
});
|
|
3596
3348
|
}
|
|
3597
3349
|
if (!client) return;
|
|
@@ -3633,11 +3385,14 @@ var ClientSampleSink = class extends EventEmitter6 {
|
|
|
3633
3385
|
import * as fs from "fs";
|
|
3634
3386
|
import * as path from "path";
|
|
3635
3387
|
var JsonlFileSink = class extends ClientSampleSink {
|
|
3388
|
+
/** The file this sink writes to. Read it (e.g. in a `close` handler) to upload/move the file. */
|
|
3389
|
+
path;
|
|
3636
3390
|
_stream;
|
|
3637
3391
|
_serializeSample;
|
|
3638
3392
|
constructor(options) {
|
|
3639
3393
|
super();
|
|
3640
|
-
this.
|
|
3394
|
+
this.path = options.path;
|
|
3395
|
+
this._stream = fs.createWriteStream(this.path, { flags: "a" });
|
|
3641
3396
|
this._stream.on("close", () => this.emit("close"));
|
|
3642
3397
|
this._stream.on("finish", () => this.emit("finish"));
|
|
3643
3398
|
this._stream.on("drain", () => this.emit("drain"));
|
|
@@ -3657,8 +3412,7 @@ function createJsonlFileSink(options) {
|
|
|
3657
3412
|
}
|
|
3658
3413
|
function createJsonlFileSinkFactory(options) {
|
|
3659
3414
|
return ({ clientId, observedCall }) => {
|
|
3660
|
-
|
|
3661
|
-
const filename = ((_a = options.getFileName) == null ? void 0 : _a.call(options, { callId: observedCall.callId, clientId })) ?? `${observedCall.callId}__${clientId}.jsonl`;
|
|
3415
|
+
const filename = options.getFileName?.({ callId: observedCall.callId, clientId }) ?? `${observedCall.callId}__${clientId}.jsonl`;
|
|
3662
3416
|
return createJsonlFileSink({
|
|
3663
3417
|
path: path.join(options.directory, filename),
|
|
3664
3418
|
serializeSample: options.serializeSample
|
|
@@ -3684,6 +3438,126 @@ var InMemorySink = class extends ClientSampleSink {
|
|
|
3684
3438
|
function createInMemorySink(samples) {
|
|
3685
3439
|
return new InMemorySink(samples);
|
|
3686
3440
|
}
|
|
3441
|
+
|
|
3442
|
+
// src/utils/RemoteTrackResolver.ts
|
|
3443
|
+
var RemoteTrackResolver = class {
|
|
3444
|
+
constructor(observedCall, resolvers) {
|
|
3445
|
+
this.observedCall = observedCall;
|
|
3446
|
+
this.resolvers = resolvers;
|
|
3447
|
+
const observer = observedCall.observer;
|
|
3448
|
+
const onInboundAdded = (p) => {
|
|
3449
|
+
if (p.observedCall === this.observedCall) this._addInboundTrack(p.observedInboundTrack);
|
|
3450
|
+
};
|
|
3451
|
+
const onInboundRemoved = (p) => {
|
|
3452
|
+
if (p.observedCall === this.observedCall) this._removeInboundTrack(p.observedInboundTrack);
|
|
3453
|
+
};
|
|
3454
|
+
const onOutboundAdded = (p) => {
|
|
3455
|
+
if (p.observedCall === this.observedCall) this._addOutboundTrack(p.observedOutboundTrack);
|
|
3456
|
+
};
|
|
3457
|
+
const onOutboundRemoved = (p) => {
|
|
3458
|
+
if (p.observedCall === this.observedCall) this._removeOutboundTrack(p.observedOutboundTrack);
|
|
3459
|
+
};
|
|
3460
|
+
observedCall.once("close", () => {
|
|
3461
|
+
observer.off("inbound-track-added", onInboundAdded);
|
|
3462
|
+
observer.off("inbound-track-removed", onInboundRemoved);
|
|
3463
|
+
observer.off("outbound-track-added", onOutboundAdded);
|
|
3464
|
+
observer.off("outbound-track-removed", onOutboundRemoved);
|
|
3465
|
+
});
|
|
3466
|
+
observer.on("inbound-track-added", onInboundAdded);
|
|
3467
|
+
observer.on("inbound-track-removed", onInboundRemoved);
|
|
3468
|
+
observer.on("outbound-track-added", onOutboundAdded);
|
|
3469
|
+
observer.on("outbound-track-removed", onOutboundRemoved);
|
|
3470
|
+
}
|
|
3471
|
+
observedCall;
|
|
3472
|
+
resolvers;
|
|
3473
|
+
_publisherIdToOutboundTrack = /* @__PURE__ */ new Map();
|
|
3474
|
+
_subscriberIdToInboundTrack = /* @__PURE__ */ new Map();
|
|
3475
|
+
/** The published (outbound) track for a publisher id, if any. */
|
|
3476
|
+
getOutboundTrackByPublisherId(publisherId) {
|
|
3477
|
+
return this._publisherIdToOutboundTrack.get(publisherId);
|
|
3478
|
+
}
|
|
3479
|
+
/** The subscribed (inbound) track for a subscriber id, if the strategy resolves subscriber ids. */
|
|
3480
|
+
getInboundTrackBySubscriberId(subscriberId) {
|
|
3481
|
+
return this._subscriberIdToInboundTrack.get(subscriberId);
|
|
3482
|
+
}
|
|
3483
|
+
// RemoteTrackResolver interface — thin readers over the links maintained on the tracks.
|
|
3484
|
+
resolveRemoteOutboundTrack(inboundTrack) {
|
|
3485
|
+
return inboundTrack.remoteOutboundTrack;
|
|
3486
|
+
}
|
|
3487
|
+
resolveRemoteInboundTracks(outboundTrack) {
|
|
3488
|
+
return [...outboundTrack.remoteInboundTracks];
|
|
3489
|
+
}
|
|
3490
|
+
_addInboundTrack(inboundTrack) {
|
|
3491
|
+
const publisherId = this.resolvers.resolveInboundTrackPublisherId(inboundTrack);
|
|
3492
|
+
if (!publisherId) return;
|
|
3493
|
+
const subscriberId = this.resolvers.resolveInboundTrackSubscriberId?.(inboundTrack);
|
|
3494
|
+
if (subscriberId) {
|
|
3495
|
+
this._subscriberIdToInboundTrack.set(subscriberId, inboundTrack);
|
|
3496
|
+
}
|
|
3497
|
+
const outboundTrack = this._publisherIdToOutboundTrack.get(publisherId);
|
|
3498
|
+
if (!outboundTrack) return;
|
|
3499
|
+
outboundTrack.remoteInboundTracks.add(inboundTrack);
|
|
3500
|
+
inboundTrack.remoteOutboundTrack = outboundTrack;
|
|
3501
|
+
}
|
|
3502
|
+
_removeInboundTrack(inboundTrack) {
|
|
3503
|
+
inboundTrack.remoteOutboundTrack?.remoteInboundTracks.delete(inboundTrack);
|
|
3504
|
+
inboundTrack.remoteOutboundTrack = void 0;
|
|
3505
|
+
const subscriberId = this.resolvers.resolveInboundTrackSubscriberId?.(inboundTrack);
|
|
3506
|
+
if (subscriberId) {
|
|
3507
|
+
this._subscriberIdToInboundTrack.delete(subscriberId);
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
_addOutboundTrack(outboundTrack) {
|
|
3511
|
+
const publisherId = this.resolvers.resolveOutboundTrackPublisherId(outboundTrack);
|
|
3512
|
+
if (!publisherId) return;
|
|
3513
|
+
this._publisherIdToOutboundTrack.set(publisherId, outboundTrack);
|
|
3514
|
+
for (const observedClient of this.observedCall.observedClients.values()) {
|
|
3515
|
+
for (const observedPeerConnection of observedClient.observedPeerConnections.values()) {
|
|
3516
|
+
for (const inboundTrack of observedPeerConnection.observedInboundTracks.values()) {
|
|
3517
|
+
if (this.resolvers.resolveInboundTrackPublisherId(inboundTrack) !== publisherId) continue;
|
|
3518
|
+
outboundTrack.remoteInboundTracks.add(inboundTrack);
|
|
3519
|
+
inboundTrack.remoteOutboundTrack = outboundTrack;
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
_removeOutboundTrack(outboundTrack) {
|
|
3525
|
+
const publisherId = this.resolvers.resolveOutboundTrackPublisherId(outboundTrack);
|
|
3526
|
+
if (publisherId && this._publisherIdToOutboundTrack.get(publisherId) === outboundTrack) {
|
|
3527
|
+
this._publisherIdToOutboundTrack.delete(publisherId);
|
|
3528
|
+
}
|
|
3529
|
+
for (const inboundTrack of outboundTrack.remoteInboundTracks) {
|
|
3530
|
+
inboundTrack.remoteOutboundTrack = void 0;
|
|
3531
|
+
}
|
|
3532
|
+
outboundTrack.remoteInboundTracks.clear();
|
|
3533
|
+
}
|
|
3534
|
+
};
|
|
3535
|
+
|
|
3536
|
+
// src/utils/RemoteTrackResolverFactories.ts
|
|
3537
|
+
function createDefaultMediasoupRemoteTrackResolverFactory() {
|
|
3538
|
+
return (observedCall) => new RemoteTrackResolver(observedCall, {
|
|
3539
|
+
resolveInboundTrackPublisherId: (inboundTrack) => inboundTrack.attachments?.producerId,
|
|
3540
|
+
resolveInboundTrackSubscriberId: (inboundTrack) => inboundTrack.attachments?.consumerId,
|
|
3541
|
+
resolveOutboundTrackPublisherId: (outboundTrack) => outboundTrack.attachments?.producerId
|
|
3542
|
+
});
|
|
3543
|
+
}
|
|
3544
|
+
function createP2pRemoteTrackResolverFactory() {
|
|
3545
|
+
return (observedCall) => new RemoteTrackResolver(observedCall, {
|
|
3546
|
+
resolveInboundTrackPublisherId: (inboundTrack) => {
|
|
3547
|
+
const ssrc = inboundTrack.getInboundRtp()?.ssrc;
|
|
3548
|
+
return ssrc ? `${ssrc}` : void 0;
|
|
3549
|
+
},
|
|
3550
|
+
resolveInboundTrackSubscriberId: (inboundTrack) => {
|
|
3551
|
+
const ssrc = inboundTrack.getInboundRtp()?.ssrc;
|
|
3552
|
+
return ssrc ? `${ssrc}` : void 0;
|
|
3553
|
+
},
|
|
3554
|
+
resolveOutboundTrackPublisherId: (outboundTrack) => {
|
|
3555
|
+
const rtps = outboundTrack.getOutboundRtps();
|
|
3556
|
+
if (!rtps || rtps.length === 0) return void 0;
|
|
3557
|
+
return rtps.map((rtp) => rtp.ssrc).join(",");
|
|
3558
|
+
}
|
|
3559
|
+
});
|
|
3560
|
+
}
|
|
3687
3561
|
export {
|
|
3688
3562
|
ClientEventTypes,
|
|
3689
3563
|
ClientMetaTypes,
|
|
@@ -3710,10 +3584,13 @@ export {
|
|
|
3710
3584
|
ObservedRemoteInboundRtp,
|
|
3711
3585
|
ObservedRemoteOutboundRtp,
|
|
3712
3586
|
Observer,
|
|
3587
|
+
RemoteTrackResolver,
|
|
3588
|
+
createDefaultMediasoupRemoteTrackResolverFactory,
|
|
3713
3589
|
createInMemorySink,
|
|
3714
3590
|
createJsonlFileSink,
|
|
3715
3591
|
createJsonlFileSinkFactory,
|
|
3716
3592
|
createLogger,
|
|
3593
|
+
createP2pRemoteTrackResolverFactory,
|
|
3717
3594
|
setObserverLogger
|
|
3718
3595
|
};
|
|
3719
3596
|
//# sourceMappingURL=index.mjs.map
|