@whereby.com/media 2.6.3 → 2.6.5

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/dist/index.cjs CHANGED
@@ -2167,7 +2167,7 @@ var _a$4;
2167
2167
  const adapter$4 = (_a$4 = adapterRaw.default) !== null && _a$4 !== void 0 ? _a$4 : adapterRaw;
2168
2168
  const logger$7 = new Logger();
2169
2169
  class Session {
2170
- constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, }) {
2170
+ constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, incrementAnalyticMetric, }) {
2171
2171
  this.peerConnectionId = peerConnectionId;
2172
2172
  this.relayCandidateSeen = false;
2173
2173
  this.serverReflexiveCandidateSeen = false;
@@ -2194,6 +2194,7 @@ class Session {
2194
2194
  });
2195
2195
  this.offerOptions = { offerToReceiveAudio: true, offerToReceiveVideo: true };
2196
2196
  this._deprioritizeH264Encoding = deprioritizeH264Encoding;
2197
+ this._incrementAnalyticMetric = incrementAnalyticMetric;
2197
2198
  }
2198
2199
  setAndGetPeerConnection({ clientId, constraints, peerConnectionConfig, shouldAddLocalVideo, }) {
2199
2200
  this.peerConnectionConfig = peerConnectionConfig;
@@ -2352,15 +2353,21 @@ class Session {
2352
2353
  return this.pc && this.pc.connectionState === "connected";
2353
2354
  }
2354
2355
  replaceTrack(oldTrack, newTrack) {
2356
+ var _a;
2355
2357
  const pc = this.pc;
2356
- if (!pc)
2358
+ if (!pc) {
2359
+ rtcStats.sendEvent("P2PReplaceTrackNoPC", {
2360
+ oldTrackId: oldTrack === null || oldTrack === void 0 ? void 0 : oldTrack.id,
2361
+ newTrackId: newTrack === null || newTrack === void 0 ? void 0 : newTrack.id,
2362
+ });
2363
+ this._incrementAnalyticMetric("P2PReplaceTrackNoPC");
2357
2364
  return false;
2358
- const senders = pc.getSenders();
2359
- if (!oldTrack) {
2360
- oldTrack = (senders.find((s) => s.track && s.track.kind === newTrack.kind) || {}).track;
2361
2365
  }
2366
+ const senders = pc.getSenders();
2367
+ const oldTrackFallback = (_a = senders.find((s) => { var _a; return ((_a = s.track) === null || _a === void 0 ? void 0 : _a.kind) === newTrack.kind; })) === null || _a === void 0 ? void 0 : _a.track;
2368
+ const oldTrackToReplace = oldTrack || oldTrackFallback;
2362
2369
  if (window.RTCRtpSender && window.RTCRtpSender.prototype.replaceTrack) {
2363
- if (oldTrack) {
2370
+ if (oldTrackToReplace) {
2364
2371
  const process = () => {
2365
2372
  for (let i = 0; i < senders.length; i++) {
2366
2373
  const sender = senders[i];
@@ -2368,39 +2375,52 @@ class Session {
2368
2375
  if ((track === null || track === void 0 ? void 0 : track.id) === newTrack.id) {
2369
2376
  return Promise.resolve(newTrack);
2370
2377
  }
2371
- if ((track === null || track === void 0 ? void 0 : track.id) === oldTrack.id) {
2378
+ if ((track === null || track === void 0 ? void 0 : track.id) === oldTrackToReplace.id) {
2372
2379
  return senders[i].replaceTrack(newTrack);
2373
2380
  }
2374
2381
  }
2375
2382
  return null;
2376
2383
  };
2377
- let result = process();
2384
+ const result = process();
2378
2385
  if (result) {
2379
2386
  return result;
2380
2387
  }
2381
- let resolve = null;
2382
- let reject = null;
2383
- result = new Promise((_resolve, _reject) => {
2384
- resolve = _resolve;
2385
- reject = _reject;
2386
- });
2387
- let retried = 0;
2388
- let timer = setInterval(() => __awaiter(this, void 0, void 0, function* () {
2389
- const trackReplacedPromise = process();
2390
- if (!trackReplacedPromise) {
2391
- if (3 < ++retried) {
2392
- clearInterval(timer);
2393
- timer = null;
2394
- reject("No sender track to replace");
2388
+ return new Promise((resolve, reject) => {
2389
+ let retried = 0;
2390
+ let timer = setInterval(() => __awaiter(this, void 0, void 0, function* () {
2391
+ const trackReplacedPromise = process();
2392
+ if (!trackReplacedPromise) {
2393
+ if (3 < ++retried) {
2394
+ clearInterval(timer);
2395
+ timer = null;
2396
+ const sendersAnalytics = senders.map((s) => {
2397
+ const track = s.track;
2398
+ if (track) {
2399
+ return {
2400
+ id: track.id,
2401
+ kind: track.kind,
2402
+ readyState: track.readyState,
2403
+ replaced: track.replaced,
2404
+ };
2405
+ }
2406
+ });
2407
+ rtcStats.sendEvent("P2PReplaceTrackFailed", {
2408
+ newTrackId: newTrack === null || newTrack === void 0 ? void 0 : newTrack.id,
2409
+ oldTrackId: oldTrack === null || oldTrack === void 0 ? void 0 : oldTrack.id,
2410
+ oldTrackFallbackId: oldTrackFallback === null || oldTrackFallback === void 0 ? void 0 : oldTrackFallback.id,
2411
+ sendersCount: senders === null || senders === void 0 ? void 0 : senders.length,
2412
+ sendersAnalytics,
2413
+ });
2414
+ reject("No sender track to replace");
2415
+ }
2416
+ return;
2395
2417
  }
2396
- return;
2397
- }
2398
- clearInterval(timer);
2399
- timer = null;
2400
- const trackReplaced = yield trackReplacedPromise;
2401
- resolve(trackReplaced);
2402
- }), 1000);
2403
- return result;
2418
+ clearInterval(timer);
2419
+ timer = null;
2420
+ const trackReplaced = yield trackReplacedPromise;
2421
+ resolve(trackReplaced);
2422
+ }), 1000);
2423
+ });
2404
2424
  }
2405
2425
  const stream = this.streams.find((s) => s.getTracks().find((t) => t.id === newTrack.id)) || this.streams[0];
2406
2426
  if (!stream) {
@@ -2410,14 +2430,16 @@ class Session {
2410
2430
  }
2411
2431
  if (!this.canModifyPeerConnection()) {
2412
2432
  this.pending.push(() => {
2413
- this.replaceTrack(oldTrack, newTrack);
2433
+ this.replaceTrack(oldTrackToReplace, newTrack);
2414
2434
  });
2415
2435
  return;
2416
2436
  }
2417
2437
  this.isOperationPending = true;
2418
2438
  const onn = pc.onnegotiationneeded;
2419
2439
  pc.onnegotiationneeded = null;
2420
- this.removeTrack(oldTrack);
2440
+ if (oldTrackToReplace) {
2441
+ this.removeTrack(oldTrackToReplace);
2442
+ }
2421
2443
  this.addTrack(newTrack);
2422
2444
  setTimeout(() => {
2423
2445
  pc.onnegotiationneeded = onn;
@@ -2575,10 +2597,6 @@ class RtcStream {
2575
2597
  static getCameraId() {
2576
2598
  return CAMERA_STREAM_ID$1;
2577
2599
  }
2578
- static getTypeFromId(id) {
2579
- const streamId = "" + id;
2580
- return streamId === CAMERA_STREAM_ID$1 ? STREAM_TYPES.CAMERA : STREAM_TYPES.SCREEN_SHARE;
2581
- }
2582
2600
  }
2583
2601
 
2584
2602
  var rtcManagerEvents = {
@@ -2655,6 +2673,9 @@ class P2pRtcManager {
2655
2673
  mediaserverConfigTtlSeconds,
2656
2674
  });
2657
2675
  this.totalSessionsCreated = 0;
2676
+ this.analytics = {
2677
+ P2PReplaceTrackNoPC: 0,
2678
+ };
2658
2679
  }
2659
2680
  numberOfPeerconnections() {
2660
2681
  return Object.keys(this.peerConnections).length;
@@ -2737,23 +2758,6 @@ class P2pRtcManager {
2737
2758
  this._localStreamDeregisterFunction = null;
2738
2759
  }
2739
2760
  }
2740
- fixChromeAudio(constraints) {
2741
- if (browserName$1 !== "chrome") {
2742
- return;
2743
- }
2744
- const localStream = this._getLocalCameraStream();
2745
- const audioTrack = localStream.getAudioTracks()[0];
2746
- if (!audioTrack || audioTrack.readyState !== "ended") {
2747
- return;
2748
- }
2749
- return navigator.mediaDevices.getUserMedia({ audio: constraints }).then((stream) => {
2750
- const track = stream.getAudioTracks()[0];
2751
- track.enabled = audioTrack.enabled;
2752
- localStream.removeTrack(audioTrack);
2753
- localStream.addTrack(track);
2754
- return this.replaceTrack(audioTrack, track);
2755
- });
2756
- }
2757
2761
  setupSocketListeners() {
2758
2762
  this._socketListenerDeregisterFunctions = [
2759
2763
  () => this._clearMediaServersRefresh(),
@@ -2955,6 +2959,7 @@ class P2pRtcManager {
2955
2959
  peerConnectionId,
2956
2960
  bandwidth: initialBandwidth,
2957
2961
  deprioritizeH264Encoding,
2962
+ incrementAnalyticMetric: (metric) => this.analytics[metric]++,
2958
2963
  });
2959
2964
  this.totalSessionsCreated++;
2960
2965
  }
package/dist/index.d.cts CHANGED
@@ -447,6 +447,7 @@ type GetDeviceDataResult = {
447
447
  };
448
448
  interface CustomMediaStreamTrack extends MediaStreamTrack {
449
449
  effectTrack?: boolean;
450
+ replaced?: boolean;
450
451
  }
451
452
 
452
453
  declare function getMediaConstraints({ disableAEC, disableAGC, hd, lax, lowDataMode, preferredDeviceIds, resolution, simulcast, widescreen, }: GetMediaConstraintsOptions): any;
@@ -1077,6 +1078,11 @@ declare function fromLocation({ host, protocol }?: {
1077
1078
  subdomain: string;
1078
1079
  };
1079
1080
 
1081
+ type P2PAnalytics = {
1082
+ P2PReplaceTrackNoPC: number;
1083
+ };
1084
+ type P2PAnalyticMetric = "P2PReplaceTrackNoPC";
1085
+ type P2PIncrementAnalyticMetric = (metric: P2PAnalyticMetric) => void;
1080
1086
  declare class P2pRtcManager implements RtcManager {
1081
1087
  _selfId: any;
1082
1088
  _roomName: any;
@@ -1115,6 +1121,7 @@ declare class P2pRtcManager implements RtcManager {
1115
1121
  _audioTrackBeingMonitored?: CustomMediaStreamTrack;
1116
1122
  _closed: boolean;
1117
1123
  skipEmittingServerMessageCount: number;
1124
+ analytics: P2PAnalytics;
1118
1125
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features, }: {
1119
1126
  selfId: any;
1120
1127
  room: any;
@@ -1134,7 +1141,6 @@ declare class P2pRtcManager implements RtcManager {
1134
1141
  replaceTrack(oldTrack: CustomMediaStreamTrack | null, newTrack: CustomMediaStreamTrack): Promise<any[]>;
1135
1142
  close(): void;
1136
1143
  disconnectAll(): void;
1137
- fixChromeAudio(constraints: any): Promise<any[]> | undefined;
1138
1144
  setupSocketListeners(): void;
1139
1145
  sendAudioMutedStats(muted: boolean): void;
1140
1146
  sendVideoMutedStats(muted: boolean): void;
@@ -1313,10 +1319,12 @@ declare class Session {
1313
1319
  shouldAddLocalVideo: any;
1314
1320
  signalingState: any;
1315
1321
  srdComplete: any;
1316
- constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, }: {
1322
+ _incrementAnalyticMetric: P2PIncrementAnalyticMetric;
1323
+ constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, incrementAnalyticMetric, }: {
1317
1324
  peerConnectionId: any;
1318
1325
  bandwidth: any;
1319
1326
  deprioritizeH264Encoding: any;
1327
+ incrementAnalyticMetric: P2PIncrementAnalyticMetric;
1320
1328
  });
1321
1329
  setAndGetPeerConnection({ clientId, constraints, peerConnectionConfig, shouldAddLocalVideo, }: {
1322
1330
  clientId: any;
@@ -1335,7 +1343,7 @@ declare class Session {
1335
1343
  canModifyPeerConnection(): boolean;
1336
1344
  close(): void;
1337
1345
  hasConnectedPeerConnection(): any;
1338
- replaceTrack(oldTrack: MediaStreamTrack, newTrack: MediaStreamTrack): any;
1346
+ replaceTrack(oldTrack: CustomMediaStreamTrack | undefined | null, newTrack: MediaStreamTrack): any;
1339
1347
  changeBandwidth(bandwidth: any): void;
1340
1348
  setAudioOnly(enable: boolean, excludedTrackIds?: any[]): void;
1341
1349
  }
@@ -1861,7 +1869,6 @@ declare class RtcStream {
1861
1869
  setVideoEnabled(isEnabled: boolean): void;
1862
1870
  setAudioEnabled(isEnabled: boolean): void;
1863
1871
  static getCameraId(): string;
1864
- static getTypeFromId(id: string): string;
1865
1872
  }
1866
1873
 
1867
1874
  export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, EVENTS, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, RtcStream, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, changeMediaDirection, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isMobile, issueDetectorOrMetricEnabled, maybeRejectNoH264, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceSSRCs, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, turnServerOverride, variance };
package/dist/index.d.mts CHANGED
@@ -447,6 +447,7 @@ type GetDeviceDataResult = {
447
447
  };
448
448
  interface CustomMediaStreamTrack extends MediaStreamTrack {
449
449
  effectTrack?: boolean;
450
+ replaced?: boolean;
450
451
  }
451
452
 
452
453
  declare function getMediaConstraints({ disableAEC, disableAGC, hd, lax, lowDataMode, preferredDeviceIds, resolution, simulcast, widescreen, }: GetMediaConstraintsOptions): any;
@@ -1077,6 +1078,11 @@ declare function fromLocation({ host, protocol }?: {
1077
1078
  subdomain: string;
1078
1079
  };
1079
1080
 
1081
+ type P2PAnalytics = {
1082
+ P2PReplaceTrackNoPC: number;
1083
+ };
1084
+ type P2PAnalyticMetric = "P2PReplaceTrackNoPC";
1085
+ type P2PIncrementAnalyticMetric = (metric: P2PAnalyticMetric) => void;
1080
1086
  declare class P2pRtcManager implements RtcManager {
1081
1087
  _selfId: any;
1082
1088
  _roomName: any;
@@ -1115,6 +1121,7 @@ declare class P2pRtcManager implements RtcManager {
1115
1121
  _audioTrackBeingMonitored?: CustomMediaStreamTrack;
1116
1122
  _closed: boolean;
1117
1123
  skipEmittingServerMessageCount: number;
1124
+ analytics: P2PAnalytics;
1118
1125
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features, }: {
1119
1126
  selfId: any;
1120
1127
  room: any;
@@ -1134,7 +1141,6 @@ declare class P2pRtcManager implements RtcManager {
1134
1141
  replaceTrack(oldTrack: CustomMediaStreamTrack | null, newTrack: CustomMediaStreamTrack): Promise<any[]>;
1135
1142
  close(): void;
1136
1143
  disconnectAll(): void;
1137
- fixChromeAudio(constraints: any): Promise<any[]> | undefined;
1138
1144
  setupSocketListeners(): void;
1139
1145
  sendAudioMutedStats(muted: boolean): void;
1140
1146
  sendVideoMutedStats(muted: boolean): void;
@@ -1313,10 +1319,12 @@ declare class Session {
1313
1319
  shouldAddLocalVideo: any;
1314
1320
  signalingState: any;
1315
1321
  srdComplete: any;
1316
- constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, }: {
1322
+ _incrementAnalyticMetric: P2PIncrementAnalyticMetric;
1323
+ constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, incrementAnalyticMetric, }: {
1317
1324
  peerConnectionId: any;
1318
1325
  bandwidth: any;
1319
1326
  deprioritizeH264Encoding: any;
1327
+ incrementAnalyticMetric: P2PIncrementAnalyticMetric;
1320
1328
  });
1321
1329
  setAndGetPeerConnection({ clientId, constraints, peerConnectionConfig, shouldAddLocalVideo, }: {
1322
1330
  clientId: any;
@@ -1335,7 +1343,7 @@ declare class Session {
1335
1343
  canModifyPeerConnection(): boolean;
1336
1344
  close(): void;
1337
1345
  hasConnectedPeerConnection(): any;
1338
- replaceTrack(oldTrack: MediaStreamTrack, newTrack: MediaStreamTrack): any;
1346
+ replaceTrack(oldTrack: CustomMediaStreamTrack | undefined | null, newTrack: MediaStreamTrack): any;
1339
1347
  changeBandwidth(bandwidth: any): void;
1340
1348
  setAudioOnly(enable: boolean, excludedTrackIds?: any[]): void;
1341
1349
  }
@@ -1861,7 +1869,6 @@ declare class RtcStream {
1861
1869
  setVideoEnabled(isEnabled: boolean): void;
1862
1870
  setAudioEnabled(isEnabled: boolean): void;
1863
1871
  static getCameraId(): string;
1864
- static getTypeFromId(id: string): string;
1865
1872
  }
1866
1873
 
1867
1874
  export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, EVENTS, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, RtcStream, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, changeMediaDirection, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isMobile, issueDetectorOrMetricEnabled, maybeRejectNoH264, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceSSRCs, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, turnServerOverride, variance };
package/dist/index.d.ts CHANGED
@@ -447,6 +447,7 @@ type GetDeviceDataResult = {
447
447
  };
448
448
  interface CustomMediaStreamTrack extends MediaStreamTrack {
449
449
  effectTrack?: boolean;
450
+ replaced?: boolean;
450
451
  }
451
452
 
452
453
  declare function getMediaConstraints({ disableAEC, disableAGC, hd, lax, lowDataMode, preferredDeviceIds, resolution, simulcast, widescreen, }: GetMediaConstraintsOptions): any;
@@ -1077,6 +1078,11 @@ declare function fromLocation({ host, protocol }?: {
1077
1078
  subdomain: string;
1078
1079
  };
1079
1080
 
1081
+ type P2PAnalytics = {
1082
+ P2PReplaceTrackNoPC: number;
1083
+ };
1084
+ type P2PAnalyticMetric = "P2PReplaceTrackNoPC";
1085
+ type P2PIncrementAnalyticMetric = (metric: P2PAnalyticMetric) => void;
1080
1086
  declare class P2pRtcManager implements RtcManager {
1081
1087
  _selfId: any;
1082
1088
  _roomName: any;
@@ -1115,6 +1121,7 @@ declare class P2pRtcManager implements RtcManager {
1115
1121
  _audioTrackBeingMonitored?: CustomMediaStreamTrack;
1116
1122
  _closed: boolean;
1117
1123
  skipEmittingServerMessageCount: number;
1124
+ analytics: P2PAnalytics;
1118
1125
  constructor({ selfId, room, emitter, serverSocket, webrtcProvider, features, }: {
1119
1126
  selfId: any;
1120
1127
  room: any;
@@ -1134,7 +1141,6 @@ declare class P2pRtcManager implements RtcManager {
1134
1141
  replaceTrack(oldTrack: CustomMediaStreamTrack | null, newTrack: CustomMediaStreamTrack): Promise<any[]>;
1135
1142
  close(): void;
1136
1143
  disconnectAll(): void;
1137
- fixChromeAudio(constraints: any): Promise<any[]> | undefined;
1138
1144
  setupSocketListeners(): void;
1139
1145
  sendAudioMutedStats(muted: boolean): void;
1140
1146
  sendVideoMutedStats(muted: boolean): void;
@@ -1313,10 +1319,12 @@ declare class Session {
1313
1319
  shouldAddLocalVideo: any;
1314
1320
  signalingState: any;
1315
1321
  srdComplete: any;
1316
- constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, }: {
1322
+ _incrementAnalyticMetric: P2PIncrementAnalyticMetric;
1323
+ constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, incrementAnalyticMetric, }: {
1317
1324
  peerConnectionId: any;
1318
1325
  bandwidth: any;
1319
1326
  deprioritizeH264Encoding: any;
1327
+ incrementAnalyticMetric: P2PIncrementAnalyticMetric;
1320
1328
  });
1321
1329
  setAndGetPeerConnection({ clientId, constraints, peerConnectionConfig, shouldAddLocalVideo, }: {
1322
1330
  clientId: any;
@@ -1335,7 +1343,7 @@ declare class Session {
1335
1343
  canModifyPeerConnection(): boolean;
1336
1344
  close(): void;
1337
1345
  hasConnectedPeerConnection(): any;
1338
- replaceTrack(oldTrack: MediaStreamTrack, newTrack: MediaStreamTrack): any;
1346
+ replaceTrack(oldTrack: CustomMediaStreamTrack | undefined | null, newTrack: MediaStreamTrack): any;
1339
1347
  changeBandwidth(bandwidth: any): void;
1340
1348
  setAudioOnly(enable: boolean, excludedTrackIds?: any[]): void;
1341
1349
  }
@@ -1861,7 +1869,6 @@ declare class RtcStream {
1861
1869
  setVideoEnabled(isEnabled: boolean): void;
1862
1870
  setAudioEnabled(isEnabled: boolean): void;
1863
1871
  static getCameraId(): string;
1864
- static getTypeFromId(id: string): string;
1865
1872
  }
1866
1873
 
1867
1874
  export { ADDITIONAL_SCREEN_SHARE_SETTINGS, AUDIO_SETTINGS, BandwidthTester, EVENTS, KNOCK_MESSAGES, KalmanFilter, Logger, MEDIA_JITTER_BUFFER_TARGET, NoDevicesError, P2pRtcManager, PROTOCOL_ERRORS, PROTOCOL_EVENTS, PROTOCOL_REQUESTS, PROTOCOL_RESPONSES, RELAY_MESSAGES, ReconnectManager, RtcEventNames, RtcManagerDispatcher, RtcStream, SCREEN_SHARE_SETTINGS, SCREEN_SHARE_SIMULCAST_SETTINGS, STREAM_TYPES, ServerSocket, Session, SfuV2Parser, TYPES, VIDEO_SETTINGS_HD, VIDEO_SETTINGS_SD, VIDEO_SETTINGS_VP9, VIDEO_SETTINGS_VP9_LOW_BANDWIDTH, VegaConnection, VegaMediaQualityMonitor, VegaRtcManager, addAbsCaptureTimeExtMap, addExtMap, assert, buildDeviceList, calculateStd, captureAudioSsrcMetrics, captureCandidatePairInfoMetrics, captureCommonSsrcMetrics, captureSsrcInfo, captureVideoSsrcMetrics, changeMediaDirection, cleanSdp, compareLocalDevices, createACFCalculator, createMicAnalyser, createWorker, deprioritizeH264, detectMicrophoneNotWorking, enumerate, external_stun_servers, filterMidExtension, filterMsidSemantic, fromLocation, generateByteString, getConstraints, getCurrentPeerConnections, getDeviceData, getDisplayMedia, getIssuesAndMetrics, getMediaConstraints, getMediaSettings, getMediasoupDeviceAsync, getNumFailedStatsReports, getNumFailedTrackSsrcLookups, getNumMissingTrackSsrcLookups, getPeerConnectionIndex, getStats, getStream, getUpdatedDevices, getUpdatedStats, getUserMedia, hasGetDisplayMedia, ipRegex, isMobile, issueDetectorOrMetricEnabled, maybeRejectNoH264, maybeTurnOnly, modifyMediaCapabilities, removePeerConnection, replaceSSRCs, replaceTracksInStream, _default as rtcManagerEvents, rtcStats, setClientProvider, setCodecPreferenceSDP, setPeerConnectionsForTests, setVideoBandwidthUsingSetParameters, sortCodecs, standardDeviation, startPerformanceMonitor, stopStreamTracks, subscribeIssues, subscribeStats, turnServerOverride, variance };
package/dist/index.mjs CHANGED
@@ -2146,7 +2146,7 @@ var _a$4;
2146
2146
  const adapter$4 = (_a$4 = adapterRaw.default) !== null && _a$4 !== void 0 ? _a$4 : adapterRaw;
2147
2147
  const logger$7 = new Logger();
2148
2148
  class Session {
2149
- constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, }) {
2149
+ constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, incrementAnalyticMetric, }) {
2150
2150
  this.peerConnectionId = peerConnectionId;
2151
2151
  this.relayCandidateSeen = false;
2152
2152
  this.serverReflexiveCandidateSeen = false;
@@ -2173,6 +2173,7 @@ class Session {
2173
2173
  });
2174
2174
  this.offerOptions = { offerToReceiveAudio: true, offerToReceiveVideo: true };
2175
2175
  this._deprioritizeH264Encoding = deprioritizeH264Encoding;
2176
+ this._incrementAnalyticMetric = incrementAnalyticMetric;
2176
2177
  }
2177
2178
  setAndGetPeerConnection({ clientId, constraints, peerConnectionConfig, shouldAddLocalVideo, }) {
2178
2179
  this.peerConnectionConfig = peerConnectionConfig;
@@ -2331,15 +2332,21 @@ class Session {
2331
2332
  return this.pc && this.pc.connectionState === "connected";
2332
2333
  }
2333
2334
  replaceTrack(oldTrack, newTrack) {
2335
+ var _a;
2334
2336
  const pc = this.pc;
2335
- if (!pc)
2337
+ if (!pc) {
2338
+ rtcStats.sendEvent("P2PReplaceTrackNoPC", {
2339
+ oldTrackId: oldTrack === null || oldTrack === void 0 ? void 0 : oldTrack.id,
2340
+ newTrackId: newTrack === null || newTrack === void 0 ? void 0 : newTrack.id,
2341
+ });
2342
+ this._incrementAnalyticMetric("P2PReplaceTrackNoPC");
2336
2343
  return false;
2337
- const senders = pc.getSenders();
2338
- if (!oldTrack) {
2339
- oldTrack = (senders.find((s) => s.track && s.track.kind === newTrack.kind) || {}).track;
2340
2344
  }
2345
+ const senders = pc.getSenders();
2346
+ const oldTrackFallback = (_a = senders.find((s) => { var _a; return ((_a = s.track) === null || _a === void 0 ? void 0 : _a.kind) === newTrack.kind; })) === null || _a === void 0 ? void 0 : _a.track;
2347
+ const oldTrackToReplace = oldTrack || oldTrackFallback;
2341
2348
  if (window.RTCRtpSender && window.RTCRtpSender.prototype.replaceTrack) {
2342
- if (oldTrack) {
2349
+ if (oldTrackToReplace) {
2343
2350
  const process = () => {
2344
2351
  for (let i = 0; i < senders.length; i++) {
2345
2352
  const sender = senders[i];
@@ -2347,39 +2354,52 @@ class Session {
2347
2354
  if ((track === null || track === void 0 ? void 0 : track.id) === newTrack.id) {
2348
2355
  return Promise.resolve(newTrack);
2349
2356
  }
2350
- if ((track === null || track === void 0 ? void 0 : track.id) === oldTrack.id) {
2357
+ if ((track === null || track === void 0 ? void 0 : track.id) === oldTrackToReplace.id) {
2351
2358
  return senders[i].replaceTrack(newTrack);
2352
2359
  }
2353
2360
  }
2354
2361
  return null;
2355
2362
  };
2356
- let result = process();
2363
+ const result = process();
2357
2364
  if (result) {
2358
2365
  return result;
2359
2366
  }
2360
- let resolve = null;
2361
- let reject = null;
2362
- result = new Promise((_resolve, _reject) => {
2363
- resolve = _resolve;
2364
- reject = _reject;
2365
- });
2366
- let retried = 0;
2367
- let timer = setInterval(() => __awaiter(this, void 0, void 0, function* () {
2368
- const trackReplacedPromise = process();
2369
- if (!trackReplacedPromise) {
2370
- if (3 < ++retried) {
2371
- clearInterval(timer);
2372
- timer = null;
2373
- reject("No sender track to replace");
2367
+ return new Promise((resolve, reject) => {
2368
+ let retried = 0;
2369
+ let timer = setInterval(() => __awaiter(this, void 0, void 0, function* () {
2370
+ const trackReplacedPromise = process();
2371
+ if (!trackReplacedPromise) {
2372
+ if (3 < ++retried) {
2373
+ clearInterval(timer);
2374
+ timer = null;
2375
+ const sendersAnalytics = senders.map((s) => {
2376
+ const track = s.track;
2377
+ if (track) {
2378
+ return {
2379
+ id: track.id,
2380
+ kind: track.kind,
2381
+ readyState: track.readyState,
2382
+ replaced: track.replaced,
2383
+ };
2384
+ }
2385
+ });
2386
+ rtcStats.sendEvent("P2PReplaceTrackFailed", {
2387
+ newTrackId: newTrack === null || newTrack === void 0 ? void 0 : newTrack.id,
2388
+ oldTrackId: oldTrack === null || oldTrack === void 0 ? void 0 : oldTrack.id,
2389
+ oldTrackFallbackId: oldTrackFallback === null || oldTrackFallback === void 0 ? void 0 : oldTrackFallback.id,
2390
+ sendersCount: senders === null || senders === void 0 ? void 0 : senders.length,
2391
+ sendersAnalytics,
2392
+ });
2393
+ reject("No sender track to replace");
2394
+ }
2395
+ return;
2374
2396
  }
2375
- return;
2376
- }
2377
- clearInterval(timer);
2378
- timer = null;
2379
- const trackReplaced = yield trackReplacedPromise;
2380
- resolve(trackReplaced);
2381
- }), 1000);
2382
- return result;
2397
+ clearInterval(timer);
2398
+ timer = null;
2399
+ const trackReplaced = yield trackReplacedPromise;
2400
+ resolve(trackReplaced);
2401
+ }), 1000);
2402
+ });
2383
2403
  }
2384
2404
  const stream = this.streams.find((s) => s.getTracks().find((t) => t.id === newTrack.id)) || this.streams[0];
2385
2405
  if (!stream) {
@@ -2389,14 +2409,16 @@ class Session {
2389
2409
  }
2390
2410
  if (!this.canModifyPeerConnection()) {
2391
2411
  this.pending.push(() => {
2392
- this.replaceTrack(oldTrack, newTrack);
2412
+ this.replaceTrack(oldTrackToReplace, newTrack);
2393
2413
  });
2394
2414
  return;
2395
2415
  }
2396
2416
  this.isOperationPending = true;
2397
2417
  const onn = pc.onnegotiationneeded;
2398
2418
  pc.onnegotiationneeded = null;
2399
- this.removeTrack(oldTrack);
2419
+ if (oldTrackToReplace) {
2420
+ this.removeTrack(oldTrackToReplace);
2421
+ }
2400
2422
  this.addTrack(newTrack);
2401
2423
  setTimeout(() => {
2402
2424
  pc.onnegotiationneeded = onn;
@@ -2554,10 +2576,6 @@ class RtcStream {
2554
2576
  static getCameraId() {
2555
2577
  return CAMERA_STREAM_ID$1;
2556
2578
  }
2557
- static getTypeFromId(id) {
2558
- const streamId = "" + id;
2559
- return streamId === CAMERA_STREAM_ID$1 ? STREAM_TYPES.CAMERA : STREAM_TYPES.SCREEN_SHARE;
2560
- }
2561
2579
  }
2562
2580
 
2563
2581
  var rtcManagerEvents = {
@@ -2634,6 +2652,9 @@ class P2pRtcManager {
2634
2652
  mediaserverConfigTtlSeconds,
2635
2653
  });
2636
2654
  this.totalSessionsCreated = 0;
2655
+ this.analytics = {
2656
+ P2PReplaceTrackNoPC: 0,
2657
+ };
2637
2658
  }
2638
2659
  numberOfPeerconnections() {
2639
2660
  return Object.keys(this.peerConnections).length;
@@ -2716,23 +2737,6 @@ class P2pRtcManager {
2716
2737
  this._localStreamDeregisterFunction = null;
2717
2738
  }
2718
2739
  }
2719
- fixChromeAudio(constraints) {
2720
- if (browserName$1 !== "chrome") {
2721
- return;
2722
- }
2723
- const localStream = this._getLocalCameraStream();
2724
- const audioTrack = localStream.getAudioTracks()[0];
2725
- if (!audioTrack || audioTrack.readyState !== "ended") {
2726
- return;
2727
- }
2728
- return navigator.mediaDevices.getUserMedia({ audio: constraints }).then((stream) => {
2729
- const track = stream.getAudioTracks()[0];
2730
- track.enabled = audioTrack.enabled;
2731
- localStream.removeTrack(audioTrack);
2732
- localStream.addTrack(track);
2733
- return this.replaceTrack(audioTrack, track);
2734
- });
2735
- }
2736
2740
  setupSocketListeners() {
2737
2741
  this._socketListenerDeregisterFunctions = [
2738
2742
  () => this._clearMediaServersRefresh(),
@@ -2934,6 +2938,7 @@ class P2pRtcManager {
2934
2938
  peerConnectionId,
2935
2939
  bandwidth: initialBandwidth,
2936
2940
  deprioritizeH264Encoding,
2941
+ incrementAnalyticMetric: (metric) => this.analytics[metric]++,
2937
2942
  });
2938
2943
  this.totalSessionsCreated++;
2939
2944
  }
@@ -2146,7 +2146,7 @@ var _a$4;
2146
2146
  const adapter$4 = (_a$4 = adapterRaw.default) !== null && _a$4 !== void 0 ? _a$4 : adapterRaw;
2147
2147
  const logger$7 = new Logger();
2148
2148
  class Session {
2149
- constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, }) {
2149
+ constructor({ peerConnectionId, bandwidth, deprioritizeH264Encoding, incrementAnalyticMetric, }) {
2150
2150
  this.peerConnectionId = peerConnectionId;
2151
2151
  this.relayCandidateSeen = false;
2152
2152
  this.serverReflexiveCandidateSeen = false;
@@ -2173,6 +2173,7 @@ class Session {
2173
2173
  });
2174
2174
  this.offerOptions = { offerToReceiveAudio: true, offerToReceiveVideo: true };
2175
2175
  this._deprioritizeH264Encoding = deprioritizeH264Encoding;
2176
+ this._incrementAnalyticMetric = incrementAnalyticMetric;
2176
2177
  }
2177
2178
  setAndGetPeerConnection({ clientId, constraints, peerConnectionConfig, shouldAddLocalVideo, }) {
2178
2179
  this.peerConnectionConfig = peerConnectionConfig;
@@ -2331,15 +2332,21 @@ class Session {
2331
2332
  return this.pc && this.pc.connectionState === "connected";
2332
2333
  }
2333
2334
  replaceTrack(oldTrack, newTrack) {
2335
+ var _a;
2334
2336
  const pc = this.pc;
2335
- if (!pc)
2337
+ if (!pc) {
2338
+ rtcStats.sendEvent("P2PReplaceTrackNoPC", {
2339
+ oldTrackId: oldTrack === null || oldTrack === void 0 ? void 0 : oldTrack.id,
2340
+ newTrackId: newTrack === null || newTrack === void 0 ? void 0 : newTrack.id,
2341
+ });
2342
+ this._incrementAnalyticMetric("P2PReplaceTrackNoPC");
2336
2343
  return false;
2337
- const senders = pc.getSenders();
2338
- if (!oldTrack) {
2339
- oldTrack = (senders.find((s) => s.track && s.track.kind === newTrack.kind) || {}).track;
2340
2344
  }
2345
+ const senders = pc.getSenders();
2346
+ const oldTrackFallback = (_a = senders.find((s) => { var _a; return ((_a = s.track) === null || _a === void 0 ? void 0 : _a.kind) === newTrack.kind; })) === null || _a === void 0 ? void 0 : _a.track;
2347
+ const oldTrackToReplace = oldTrack || oldTrackFallback;
2341
2348
  if (window.RTCRtpSender && window.RTCRtpSender.prototype.replaceTrack) {
2342
- if (oldTrack) {
2349
+ if (oldTrackToReplace) {
2343
2350
  const process = () => {
2344
2351
  for (let i = 0; i < senders.length; i++) {
2345
2352
  const sender = senders[i];
@@ -2347,39 +2354,52 @@ class Session {
2347
2354
  if ((track === null || track === void 0 ? void 0 : track.id) === newTrack.id) {
2348
2355
  return Promise.resolve(newTrack);
2349
2356
  }
2350
- if ((track === null || track === void 0 ? void 0 : track.id) === oldTrack.id) {
2357
+ if ((track === null || track === void 0 ? void 0 : track.id) === oldTrackToReplace.id) {
2351
2358
  return senders[i].replaceTrack(newTrack);
2352
2359
  }
2353
2360
  }
2354
2361
  return null;
2355
2362
  };
2356
- let result = process();
2363
+ const result = process();
2357
2364
  if (result) {
2358
2365
  return result;
2359
2366
  }
2360
- let resolve = null;
2361
- let reject = null;
2362
- result = new Promise((_resolve, _reject) => {
2363
- resolve = _resolve;
2364
- reject = _reject;
2365
- });
2366
- let retried = 0;
2367
- let timer = setInterval(() => __awaiter(this, void 0, void 0, function* () {
2368
- const trackReplacedPromise = process();
2369
- if (!trackReplacedPromise) {
2370
- if (3 < ++retried) {
2371
- clearInterval(timer);
2372
- timer = null;
2373
- reject("No sender track to replace");
2367
+ return new Promise((resolve, reject) => {
2368
+ let retried = 0;
2369
+ let timer = setInterval(() => __awaiter(this, void 0, void 0, function* () {
2370
+ const trackReplacedPromise = process();
2371
+ if (!trackReplacedPromise) {
2372
+ if (3 < ++retried) {
2373
+ clearInterval(timer);
2374
+ timer = null;
2375
+ const sendersAnalytics = senders.map((s) => {
2376
+ const track = s.track;
2377
+ if (track) {
2378
+ return {
2379
+ id: track.id,
2380
+ kind: track.kind,
2381
+ readyState: track.readyState,
2382
+ replaced: track.replaced,
2383
+ };
2384
+ }
2385
+ });
2386
+ rtcStats.sendEvent("P2PReplaceTrackFailed", {
2387
+ newTrackId: newTrack === null || newTrack === void 0 ? void 0 : newTrack.id,
2388
+ oldTrackId: oldTrack === null || oldTrack === void 0 ? void 0 : oldTrack.id,
2389
+ oldTrackFallbackId: oldTrackFallback === null || oldTrackFallback === void 0 ? void 0 : oldTrackFallback.id,
2390
+ sendersCount: senders === null || senders === void 0 ? void 0 : senders.length,
2391
+ sendersAnalytics,
2392
+ });
2393
+ reject("No sender track to replace");
2394
+ }
2395
+ return;
2374
2396
  }
2375
- return;
2376
- }
2377
- clearInterval(timer);
2378
- timer = null;
2379
- const trackReplaced = yield trackReplacedPromise;
2380
- resolve(trackReplaced);
2381
- }), 1000);
2382
- return result;
2397
+ clearInterval(timer);
2398
+ timer = null;
2399
+ const trackReplaced = yield trackReplacedPromise;
2400
+ resolve(trackReplaced);
2401
+ }), 1000);
2402
+ });
2383
2403
  }
2384
2404
  const stream = this.streams.find((s) => s.getTracks().find((t) => t.id === newTrack.id)) || this.streams[0];
2385
2405
  if (!stream) {
@@ -2389,14 +2409,16 @@ class Session {
2389
2409
  }
2390
2410
  if (!this.canModifyPeerConnection()) {
2391
2411
  this.pending.push(() => {
2392
- this.replaceTrack(oldTrack, newTrack);
2412
+ this.replaceTrack(oldTrackToReplace, newTrack);
2393
2413
  });
2394
2414
  return;
2395
2415
  }
2396
2416
  this.isOperationPending = true;
2397
2417
  const onn = pc.onnegotiationneeded;
2398
2418
  pc.onnegotiationneeded = null;
2399
- this.removeTrack(oldTrack);
2419
+ if (oldTrackToReplace) {
2420
+ this.removeTrack(oldTrackToReplace);
2421
+ }
2400
2422
  this.addTrack(newTrack);
2401
2423
  setTimeout(() => {
2402
2424
  pc.onnegotiationneeded = onn;
@@ -2554,10 +2576,6 @@ class RtcStream {
2554
2576
  static getCameraId() {
2555
2577
  return CAMERA_STREAM_ID$1;
2556
2578
  }
2557
- static getTypeFromId(id) {
2558
- const streamId = "" + id;
2559
- return streamId === CAMERA_STREAM_ID$1 ? STREAM_TYPES.CAMERA : STREAM_TYPES.SCREEN_SHARE;
2560
- }
2561
2579
  }
2562
2580
 
2563
2581
  var rtcManagerEvents = {
@@ -2634,6 +2652,9 @@ class P2pRtcManager {
2634
2652
  mediaserverConfigTtlSeconds,
2635
2653
  });
2636
2654
  this.totalSessionsCreated = 0;
2655
+ this.analytics = {
2656
+ P2PReplaceTrackNoPC: 0,
2657
+ };
2637
2658
  }
2638
2659
  numberOfPeerconnections() {
2639
2660
  return Object.keys(this.peerConnections).length;
@@ -2716,23 +2737,6 @@ class P2pRtcManager {
2716
2737
  this._localStreamDeregisterFunction = null;
2717
2738
  }
2718
2739
  }
2719
- fixChromeAudio(constraints) {
2720
- if (browserName$1 !== "chrome") {
2721
- return;
2722
- }
2723
- const localStream = this._getLocalCameraStream();
2724
- const audioTrack = localStream.getAudioTracks()[0];
2725
- if (!audioTrack || audioTrack.readyState !== "ended") {
2726
- return;
2727
- }
2728
- return navigator.mediaDevices.getUserMedia({ audio: constraints }).then((stream) => {
2729
- const track = stream.getAudioTracks()[0];
2730
- track.enabled = audioTrack.enabled;
2731
- localStream.removeTrack(audioTrack);
2732
- localStream.addTrack(track);
2733
- return this.replaceTrack(audioTrack, track);
2734
- });
2735
- }
2736
2740
  setupSocketListeners() {
2737
2741
  this._socketListenerDeregisterFunctions = [
2738
2742
  () => this._clearMediaServersRefresh(),
@@ -2934,6 +2938,7 @@ class P2pRtcManager {
2934
2938
  peerConnectionId,
2935
2939
  bandwidth: initialBandwidth,
2936
2940
  deprioritizeH264Encoding,
2941
+ incrementAnalyticMetric: (metric) => this.analytics[metric]++,
2937
2942
  });
2938
2943
  this.totalSessionsCreated++;
2939
2944
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@whereby.com/media",
3
3
  "description": "Media library for Whereby",
4
- "version": "2.6.3",
4
+ "version": "2.6.5",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/whereby/sdk",
7
7
  "repository": {