livekit-client 2.0.2 → 2.0.4

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.
Files changed (73) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +53 -17
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +158 -65
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/api/SignalClient.d.ts.map +1 -1
  10. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  11. package/dist/src/e2ee/KeyProvider.d.ts +1 -1
  12. package/dist/src/e2ee/KeyProvider.d.ts.map +1 -1
  13. package/dist/src/e2ee/types.d.ts +2 -0
  14. package/dist/src/e2ee/types.d.ts.map +1 -1
  15. package/dist/src/e2ee/worker/FrameCryptor.d.ts +1 -0
  16. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  17. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts +2 -2
  18. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
  19. package/dist/src/index.d.ts +2 -2
  20. package/dist/src/index.d.ts.map +1 -1
  21. package/dist/src/logger.d.ts +2 -0
  22. package/dist/src/logger.d.ts.map +1 -1
  23. package/dist/src/room/DeviceManager.d.ts.map +1 -1
  24. package/dist/src/room/RTCEngine.d.ts +1 -0
  25. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  26. package/dist/src/room/Room.d.ts +1 -0
  27. package/dist/src/room/Room.d.ts.map +1 -1
  28. package/dist/src/room/events.d.ts +7 -2
  29. package/dist/src/room/events.d.ts.map +1 -1
  30. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  31. package/dist/src/room/track/LocalTrack.d.ts +4 -1
  32. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  33. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  34. package/dist/src/room/track/Track.d.ts +2 -0
  35. package/dist/src/room/track/Track.d.ts.map +1 -1
  36. package/dist/src/room/track/options.d.ts +10 -0
  37. package/dist/src/room/track/options.d.ts.map +1 -1
  38. package/dist/src/room/track/types.d.ts +4 -0
  39. package/dist/src/room/track/types.d.ts.map +1 -1
  40. package/dist/ts4.2/src/e2ee/KeyProvider.d.ts +1 -1
  41. package/dist/ts4.2/src/e2ee/types.d.ts +2 -0
  42. package/dist/ts4.2/src/e2ee/worker/FrameCryptor.d.ts +1 -0
  43. package/dist/ts4.2/src/e2ee/worker/ParticipantKeyHandler.d.ts +2 -2
  44. package/dist/ts4.2/src/index.d.ts +2 -2
  45. package/dist/ts4.2/src/logger.d.ts +2 -0
  46. package/dist/ts4.2/src/room/RTCEngine.d.ts +1 -0
  47. package/dist/ts4.2/src/room/Room.d.ts +1 -0
  48. package/dist/ts4.2/src/room/events.d.ts +7 -2
  49. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +4 -1
  50. package/dist/ts4.2/src/room/track/Track.d.ts +2 -0
  51. package/dist/ts4.2/src/room/track/options.d.ts +10 -0
  52. package/dist/ts4.2/src/room/track/types.d.ts +4 -0
  53. package/package.json +1 -1
  54. package/src/api/SignalClient.ts +1 -0
  55. package/src/e2ee/E2eeManager.ts +2 -1
  56. package/src/e2ee/KeyProvider.ts +6 -1
  57. package/src/e2ee/types.ts +2 -0
  58. package/src/e2ee/worker/FrameCryptor.ts +26 -0
  59. package/src/e2ee/worker/ParticipantKeyHandler.ts +9 -5
  60. package/src/e2ee/worker/e2ee.worker.ts +17 -17
  61. package/src/index.ts +2 -1
  62. package/src/logger.ts +2 -0
  63. package/src/room/DeviceManager.ts +10 -1
  64. package/src/room/RTCEngine.ts +14 -0
  65. package/src/room/Room.ts +29 -4
  66. package/src/room/events.ts +5 -0
  67. package/src/room/participant/LocalParticipant.ts +4 -4
  68. package/src/room/track/LocalAudioTrack.ts +11 -0
  69. package/src/room/track/LocalTrack.ts +62 -36
  70. package/src/room/track/LocalVideoTrack.ts +10 -0
  71. package/src/room/track/Track.ts +2 -0
  72. package/src/room/track/options.ts +41 -8
  73. package/src/room/track/types.ts +5 -0
@@ -352,7 +352,7 @@ function setLogExtension(extension) {
352
352
  };
353
353
  logger.setLevel(logger.getLevel()); // Be sure to call setLevel method in order to apply plugin
354
354
  }
355
- loglevelExports.getLogger('lk-e2ee');
355
+ const workerLogger = loglevelExports.getLogger('lk-e2ee');
356
356
 
357
357
  // Copyright 2021-2023 Buf Technologies, Inc.
358
358
  //
@@ -9980,6 +9980,9 @@ class BaseKeyProvider extends eventsExports.EventEmitter {
9980
9980
  participantIdentity,
9981
9981
  keyIndex
9982
9982
  };
9983
+ if (!this.options.sharedKey && !participantIdentity) {
9984
+ throw new Error('participant identity needs to be passed for encryption key if sharedKey option is false');
9985
+ }
9983
9986
  this.keyInfoMap.set("".concat(participantIdentity !== null && participantIdentity !== void 0 ? participantIdentity : 'shared', "-").concat(keyIndex !== null && keyIndex !== void 0 ? keyIndex : 0), keyInfo);
9984
9987
  this.emit(KeyProviderEvent.SetKey, keyInfo);
9985
9988
  }
@@ -10534,6 +10537,7 @@ var EngineEvent;
10534
10537
  EngineEvent["RemoteMute"] = "remoteMute";
10535
10538
  EngineEvent["SubscribedQualityUpdate"] = "subscribedQualityUpdate";
10536
10539
  EngineEvent["LocalTrackUnpublished"] = "localTrackUnpublished";
10540
+ EngineEvent["Offline"] = "offline";
10537
10541
  })(EngineEvent || (EngineEvent = {}));
10538
10542
  var TrackEvent;
10539
10543
  (function (TrackEvent) {
@@ -10595,6 +10599,10 @@ var TrackEvent;
10595
10599
  * Fires on RemoteTrackPublication
10596
10600
  */
10597
10601
  TrackEvent["SubscriptionFailed"] = "subscriptionFailed";
10602
+ /**
10603
+ * @internal
10604
+ */
10605
+ TrackEvent["TrackProcessorUpdate"] = "trackProcessorUpdate";
10598
10606
  })(TrackEvent || (TrackEvent = {}));
10599
10607
 
10600
10608
  function r(r, e, n) {
@@ -10703,7 +10711,7 @@ function getMatch(exp, ua) {
10703
10711
  return match && match.length >= id && match[id] || '';
10704
10712
  }
10705
10713
 
10706
- var version$1 = "2.0.2";
10714
+ var version$1 = "2.0.4";
10707
10715
 
10708
10716
  const version = version$1;
10709
10717
  const protocolVersion = 12;
@@ -10730,21 +10738,35 @@ CriticalTimers.clearInterval = function () {
10730
10738
  };
10731
10739
 
10732
10740
  class VideoPreset {
10733
- constructor(width, height, maxBitrate, maxFramerate, priority) {
10734
- this.width = width;
10735
- this.height = height;
10736
- this.encoding = {
10737
- maxBitrate,
10738
- maxFramerate,
10739
- priority
10740
- };
10741
+ constructor(widthOrOptions, height, maxBitrate, maxFramerate, priority) {
10742
+ if (typeof widthOrOptions === 'object') {
10743
+ this.width = widthOrOptions.width;
10744
+ this.height = widthOrOptions.height;
10745
+ this.aspectRatio = widthOrOptions.aspectRatio;
10746
+ this.encoding = {
10747
+ maxBitrate: widthOrOptions.maxBitrate,
10748
+ maxFramerate: widthOrOptions.maxFramerate,
10749
+ priority: widthOrOptions.priority
10750
+ };
10751
+ } else if (height !== undefined && maxBitrate !== undefined) {
10752
+ this.width = widthOrOptions;
10753
+ this.height = height;
10754
+ this.aspectRatio = widthOrOptions / height;
10755
+ this.encoding = {
10756
+ maxBitrate,
10757
+ maxFramerate,
10758
+ priority
10759
+ };
10760
+ } else {
10761
+ throw new TypeError('Unsupported options: provide at least width, height and maxBitrate');
10762
+ }
10741
10763
  }
10742
10764
  get resolution() {
10743
10765
  return {
10744
10766
  width: this.width,
10745
10767
  height: this.height,
10746
10768
  frameRate: this.encoding.maxFramerate,
10747
- aspectRatio: this.width / this.height
10769
+ aspectRatio: this.aspectRatio
10748
10770
  };
10749
10771
  }
10750
10772
  }
@@ -14157,7 +14179,16 @@ class DeviceManager {
14157
14179
  // resolve actual device id if it's 'default': Chrome returns it when no
14158
14180
  // device has been chosen
14159
14181
  const devices = yield this.getDevices(kind);
14160
- const device = devices.find(d => d.groupId === groupId && d.deviceId !== defaultId);
14182
+ // `default` devices will have the same groupId as the entry with the actual device id so we store the counts for each group id
14183
+ const groupIdCounts = new Map(devices.map(d => [d.groupId, 0]));
14184
+ devices.forEach(d => {
14185
+ var _a;
14186
+ return groupIdCounts.set(d.groupId, ((_a = groupIdCounts.get(d.groupId)) !== null && _a !== void 0 ? _a : 0) + 1);
14187
+ });
14188
+ const device = devices.find(d => {
14189
+ var _a;
14190
+ return (groupId === d.groupId || ((_a = groupIdCounts.get(d.groupId)) !== null && _a !== void 0 ? _a : 0) > 1) && d.deviceId !== defaultId;
14191
+ });
14161
14192
  return device === null || device === void 0 ? void 0 : device.deviceId;
14162
14193
  });
14163
14194
  }
@@ -14206,6 +14237,7 @@ class LocalTrack extends Track {
14206
14237
  this.muteLock = new Mutex();
14207
14238
  this.pauseUpstreamLock = new Mutex();
14208
14239
  this.processorLock = new Mutex();
14240
+ this.restartLock = new Mutex();
14209
14241
  this.setMediaStreamTrack(mediaTrack, true);
14210
14242
  // added to satisfy TS compiler, constraints are synced with MediaStreamTrack
14211
14243
  this._constraints = mediaTrack.getConstraints();
@@ -14364,18 +14396,25 @@ class LocalTrack extends Track {
14364
14396
  return this;
14365
14397
  });
14366
14398
  }
14367
- replaceTrack(track) {
14368
- let userProvidedTrack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
14399
+ replaceTrack(track, userProvidedOrOptions) {
14369
14400
  return __awaiter(this, void 0, void 0, function* () {
14370
14401
  if (!this.sender) {
14371
14402
  throw new TrackInvalidError('unable to replace an unpublished track');
14372
14403
  }
14404
+ let userProvidedTrack;
14405
+ let stopProcessor;
14406
+ if (typeof userProvidedOrOptions === 'boolean') {
14407
+ userProvidedTrack = userProvidedOrOptions;
14408
+ } else if (userProvidedOrOptions !== undefined) {
14409
+ userProvidedTrack = userProvidedOrOptions.userProvidedTrack;
14410
+ stopProcessor = userProvidedOrOptions.stopProcessor;
14411
+ }
14412
+ this.providedByUser = userProvidedTrack !== null && userProvidedTrack !== void 0 ? userProvidedTrack : true;
14373
14413
  this.log.debug('replace MediaStreamTrack', this.logContext);
14374
14414
  yield this.setMediaStreamTrack(track);
14375
14415
  // this must be synced *after* setting mediaStreamTrack above, since it relies
14376
14416
  // on the previous state in order to cleanup
14377
- this.providedByUser = userProvidedTrack;
14378
- if (this.processor) {
14417
+ if (stopProcessor && this.processor) {
14379
14418
  yield this.stopProcessor();
14380
14419
  }
14381
14420
  return this;
@@ -14383,40 +14422,45 @@ class LocalTrack extends Track {
14383
14422
  }
14384
14423
  restart(constraints) {
14385
14424
  return __awaiter(this, void 0, void 0, function* () {
14386
- if (!constraints) {
14387
- constraints = this._constraints;
14388
- }
14389
- this.log.debug('restarting track with constraints', Object.assign(Object.assign({}, this.logContext), {
14390
- constraints
14391
- }));
14392
- const streamConstraints = {
14393
- audio: false,
14394
- video: false
14395
- };
14396
- if (this.kind === Track.Kind.Video) {
14397
- streamConstraints.video = constraints;
14398
- } else {
14399
- streamConstraints.audio = constraints;
14425
+ const unlock = yield this.restartLock.lock();
14426
+ try {
14427
+ if (!constraints) {
14428
+ constraints = this._constraints;
14429
+ }
14430
+ this.log.debug('restarting track with constraints', Object.assign(Object.assign({}, this.logContext), {
14431
+ constraints
14432
+ }));
14433
+ const streamConstraints = {
14434
+ audio: false,
14435
+ video: false
14436
+ };
14437
+ if (this.kind === Track.Kind.Video) {
14438
+ streamConstraints.video = constraints;
14439
+ } else {
14440
+ streamConstraints.audio = constraints;
14441
+ }
14442
+ // these steps are duplicated from setMediaStreamTrack because we must stop
14443
+ // the previous tracks before new tracks can be acquired
14444
+ this.attachedElements.forEach(el => {
14445
+ detachTrack(this.mediaStreamTrack, el);
14446
+ });
14447
+ this._mediaStreamTrack.removeEventListener('ended', this.handleEnded);
14448
+ // on Safari, the old audio track must be stopped before attempting to acquire
14449
+ // the new track, otherwise the new track will stop with
14450
+ // 'A MediaStreamTrack ended due to a capture failure`
14451
+ this._mediaStreamTrack.stop();
14452
+ // create new track and attach
14453
+ const mediaStream = yield navigator.mediaDevices.getUserMedia(streamConstraints);
14454
+ const newTrack = mediaStream.getTracks()[0];
14455
+ newTrack.addEventListener('ended', this.handleEnded);
14456
+ this.log.debug('re-acquired MediaStreamTrack', this.logContext);
14457
+ yield this.setMediaStreamTrack(newTrack);
14458
+ this._constraints = constraints;
14459
+ this.emit(TrackEvent.Restarted, this);
14460
+ return this;
14461
+ } finally {
14462
+ unlock();
14400
14463
  }
14401
- // these steps are duplicated from setMediaStreamTrack because we must stop
14402
- // the previous tracks before new tracks can be acquired
14403
- this.attachedElements.forEach(el => {
14404
- detachTrack(this.mediaStreamTrack, el);
14405
- });
14406
- this._mediaStreamTrack.removeEventListener('ended', this.handleEnded);
14407
- // on Safari, the old audio track must be stopped before attempting to acquire
14408
- // the new track, otherwise the new track will stop with
14409
- // 'A MediaStreamTrack ended due to a capture failure`
14410
- this._mediaStreamTrack.stop();
14411
- // create new track and attach
14412
- const mediaStream = yield navigator.mediaDevices.getUserMedia(streamConstraints);
14413
- const newTrack = mediaStream.getTracks()[0];
14414
- newTrack.addEventListener('ended', this.handleEnded);
14415
- this.log.debug('re-acquired MediaStreamTrack', this.logContext);
14416
- yield this.setMediaStreamTrack(newTrack);
14417
- this._constraints = constraints;
14418
- this.emit(TrackEvent.Restarted, this);
14419
- return this;
14420
14464
  });
14421
14465
  }
14422
14466
  setTrackMuted(muted) {
@@ -14569,6 +14613,7 @@ class LocalTrack extends Track {
14569
14613
  }
14570
14614
  yield (_b = this.sender) === null || _b === void 0 ? void 0 : _b.replaceTrack(this.processor.processedTrack);
14571
14615
  }
14616
+ this.emit(TrackEvent.TrackProcessorUpdate, this.processor);
14572
14617
  } finally {
14573
14618
  unlock();
14574
14619
  }
@@ -14595,6 +14640,7 @@ class LocalTrack extends Track {
14595
14640
  (_b = this.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
14596
14641
  this.processorElement = undefined;
14597
14642
  yield this.restart();
14643
+ this.emit(TrackEvent.TrackProcessorUpdate);
14598
14644
  });
14599
14645
  }
14600
14646
  }
@@ -14670,7 +14716,8 @@ class E2EEManager extends eventsExports.EventEmitter {
14670
14716
  const msg = {
14671
14717
  kind: 'init',
14672
14718
  data: {
14673
- keyProviderOptions: this.keyProvider.getOptions()
14719
+ keyProviderOptions: this.keyProvider.getOptions(),
14720
+ loglevel: workerLogger.getLevel()
14674
14721
  }
14675
14722
  };
14676
14723
  if (this.worker) {
@@ -15108,6 +15155,7 @@ class SignalClient {
15108
15155
  };
15109
15156
  this.ws.onerror = ev => __awaiter(this, void 0, void 0, function* () {
15110
15157
  if (this.state !== SignalConnectionState.CONNECTED) {
15158
+ this.state = SignalConnectionState.DISCONNECTED;
15111
15159
  clearTimeout(wsTimeout);
15112
15160
  try {
15113
15161
  const resp = yield fetch("http".concat(url.substring(2), "/validate").concat(params));
@@ -17517,6 +17565,12 @@ class RTCEngine extends eventsExports.EventEmitter {
17517
17565
  this.handleDisconnect('peerconnection failed', subscriberState === 'failed' ? ReconnectReason.RR_SUBSCRIBER_FAILED : ReconnectReason.RR_PUBLISHER_FAILED);
17518
17566
  }
17519
17567
  }
17568
+ // detect cases where both signal client and peer connection are severed and assume that user has lost network connection
17569
+ const isSignalSevered = this.client.isDisconnected || this.client.currentState === SignalConnectionState.RECONNECTING;
17570
+ const isPCSevered = [PCTransportState.FAILED, PCTransportState.CLOSING, PCTransportState.CLOSED].includes(connectionState);
17571
+ if (isSignalSevered && isPCSevered && !this._isClosed) {
17572
+ this.emit(EngineEvent.Offline);
17573
+ }
17520
17574
  });
17521
17575
  this.pcManager.onTrack = ev => {
17522
17576
  this.emit(EngineEvent.MediaTrackAdded, ev.track, ev.streams[0], ev.receiver);
@@ -18347,6 +18401,10 @@ class LocalAudioTrack extends LocalTrack {
18347
18401
  return __awaiter(this, void 0, void 0, function* () {
18348
18402
  const unlock = yield this.muteLock.lock();
18349
18403
  try {
18404
+ if (this.isMuted) {
18405
+ this.log.debug('Track already muted', this.logContext);
18406
+ return this;
18407
+ }
18350
18408
  // disabled special handling as it will cause BT headsets to switch communication modes
18351
18409
  if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
18352
18410
  this.log.debug('stopping mic track', this.logContext);
@@ -18369,6 +18427,10 @@ class LocalAudioTrack extends LocalTrack {
18369
18427
  return __awaiter(this, void 0, void 0, function* () {
18370
18428
  const unlock = yield this.muteLock.lock();
18371
18429
  try {
18430
+ if (!this.isMuted) {
18431
+ this.log.debug('Track already unmuted', this.logContext);
18432
+ return this;
18433
+ }
18372
18434
  const deviceHasChanged = this._constraints.deviceId && this._mediaStreamTrack.getSettings().deviceId !== unwrapConstraint(this._constraints.deviceId);
18373
18435
  if (this.source === Track.Source.Microphone && (this.stopOnMute || this._mediaStreamTrack.readyState === 'ended' || deviceHasChanged) && !this.isUserProvided) {
18374
18436
  this.log.debug('reacquiring mic track', this.logContext);
@@ -18441,6 +18503,7 @@ class LocalAudioTrack extends LocalTrack {
18441
18503
  if (this.processor.processedTrack) {
18442
18504
  yield (_a = this.sender) === null || _a === void 0 ? void 0 : _a.replaceTrack(this.processor.processedTrack);
18443
18505
  }
18506
+ this.emit(TrackEvent.TrackProcessorUpdate, this.processor);
18444
18507
  } finally {
18445
18508
  unlock();
18446
18509
  }
@@ -18937,6 +19000,10 @@ class LocalVideoTrack extends LocalTrack {
18937
19000
  return __awaiter(this, void 0, void 0, function* () {
18938
19001
  const unlock = yield this.muteLock.lock();
18939
19002
  try {
19003
+ if (this.isMuted) {
19004
+ this.log.debug('Track already muted', this.logContext);
19005
+ return this;
19006
+ }
18940
19007
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
18941
19008
  this.log.debug('stopping camera track', this.logContext);
18942
19009
  // also stop the track, so that camera indicator is turned off
@@ -18958,6 +19025,10 @@ class LocalVideoTrack extends LocalTrack {
18958
19025
  return __awaiter(this, void 0, void 0, function* () {
18959
19026
  const unlock = yield this.muteLock.lock();
18960
19027
  try {
19028
+ if (!this.isMuted) {
19029
+ this.log.debug('Track already unmuted', this.logContext);
19030
+ return this;
19031
+ }
18961
19032
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
18962
19033
  this.log.debug('reacquiring camera track', this.logContext);
18963
19034
  yield this.restartTrack();
@@ -20813,6 +20884,9 @@ class LocalParticipant extends Participant {
20813
20884
  publishTrack(track, options) {
20814
20885
  var _a, _b, _c, _d;
20815
20886
  return __awaiter(this, void 0, void 0, function* () {
20887
+ if (track instanceof LocalAudioTrack) {
20888
+ track.setAudioContext(this.audioContext);
20889
+ }
20816
20890
  yield (_a = this.reconnectFuture) === null || _a === void 0 ? void 0 : _a.promise;
20817
20891
  if (track instanceof LocalTrack && this.pendingPublishPromises.has(track)) {
20818
20892
  yield this.pendingPublishPromises.get(track);
@@ -20862,9 +20936,6 @@ class LocalParticipant extends Participant {
20862
20936
  loggerContextCb: () => this.logContext
20863
20937
  });
20864
20938
  }
20865
- if (track instanceof LocalAudioTrack) {
20866
- track.setAudioContext(this.audioContext);
20867
- }
20868
20939
  // is it already published? if so skip
20869
20940
  let existingPublication;
20870
20941
  this.trackPublications.forEach(publication => {
@@ -22041,14 +22112,20 @@ class Room extends eventsExports.EventEmitter {
22041
22112
  const pi = joinResponse.participant;
22042
22113
  this.localParticipant.sid = pi.sid;
22043
22114
  this.localParticipant.identity = pi.identity;
22115
+ if (this.options.e2ee && this.e2eeManager) {
22116
+ try {
22117
+ this.e2eeManager.setSifTrailer(joinResponse.sifTrailer);
22118
+ } catch (e) {
22119
+ this.log.error(e instanceof Error ? e.message : 'Could not set SifTrailer', Object.assign(Object.assign({}, this.logContext), {
22120
+ error: e
22121
+ }));
22122
+ }
22123
+ }
22044
22124
  // populate remote participants, these should not trigger new events
22045
22125
  this.handleParticipantUpdates([pi, ...joinResponse.otherParticipants]);
22046
22126
  if (joinResponse.room) {
22047
22127
  this.handleRoomUpdate(joinResponse.room);
22048
22128
  }
22049
- if (this.options.e2ee && this.e2eeManager) {
22050
- this.e2eeManager.setSifTrailer(joinResponse.sifTrailer);
22051
- }
22052
22129
  };
22053
22130
  this.attemptConnection = (url, token, opts, abortController) => __awaiter(this, void 0, void 0, function* () {
22054
22131
  var _h, _j, _k;
@@ -22158,6 +22235,7 @@ class Room extends eventsExports.EventEmitter {
22158
22235
  });
22159
22236
  };
22160
22237
  this.onPageLeave = () => __awaiter(this, void 0, void 0, function* () {
22238
+ this.log.info('Page leave detected, disconnecting', this.logContext);
22161
22239
  yield this.disconnect();
22162
22240
  });
22163
22241
  /**
@@ -22483,9 +22561,14 @@ class Room extends eventsExports.EventEmitter {
22483
22561
  this.onLocalTrackUnmuted = pub => {
22484
22562
  this.emit(RoomEvent.TrackUnmuted, pub, this.localParticipant);
22485
22563
  };
22564
+ this.onTrackProcessorUpdate = processor => {
22565
+ var _a;
22566
+ (_a = processor === null || processor === void 0 ? void 0 : processor.onPublish) === null || _a === void 0 ? void 0 : _a.call(processor, this);
22567
+ };
22486
22568
  this.onLocalTrackPublished = pub => __awaiter(this, void 0, void 0, function* () {
22487
- var _r, _s, _t, _u;
22488
- (_t = (_s = (_r = pub.track) === null || _r === void 0 ? void 0 : _r.getProcessor()) === null || _s === void 0 ? void 0 : _s.onPublish) === null || _t === void 0 ? void 0 : _t.call(_s, this);
22569
+ var _r, _s, _t, _u, _v;
22570
+ (_r = pub.track) === null || _r === void 0 ? void 0 : _r.on(TrackEvent.TrackProcessorUpdate, this.onTrackProcessorUpdate);
22571
+ (_u = (_t = (_s = pub.track) === null || _s === void 0 ? void 0 : _s.getProcessor()) === null || _t === void 0 ? void 0 : _t.onPublish) === null || _u === void 0 ? void 0 : _u.call(_t, this);
22489
22572
  this.emit(RoomEvent.LocalTrackPublished, pub, this.localParticipant);
22490
22573
  if (pub.track instanceof LocalAudioTrack) {
22491
22574
  const trackIsSilent = yield pub.track.checkForSilence();
@@ -22493,7 +22576,7 @@ class Room extends eventsExports.EventEmitter {
22493
22576
  this.emit(RoomEvent.LocalAudioSilenceDetected, pub);
22494
22577
  }
22495
22578
  }
22496
- const deviceId = yield (_u = pub.track) === null || _u === void 0 ? void 0 : _u.getDeviceId();
22579
+ const deviceId = yield (_v = pub.track) === null || _v === void 0 ? void 0 : _v.getDeviceId();
22497
22580
  const deviceKind = sourceToKind(pub.source);
22498
22581
  if (deviceKind && deviceId && deviceId !== this.localParticipant.activeDeviceMap.get(deviceKind)) {
22499
22582
  this.localParticipant.activeDeviceMap.set(deviceKind, deviceId);
@@ -22501,6 +22584,8 @@ class Room extends eventsExports.EventEmitter {
22501
22584
  }
22502
22585
  });
22503
22586
  this.onLocalTrackUnpublished = pub => {
22587
+ var _a;
22588
+ (_a = pub.track) === null || _a === void 0 ? void 0 : _a.off(TrackEvent.TrackProcessorUpdate, this.onTrackProcessorUpdate);
22504
22589
  this.emit(RoomEvent.LocalTrackUnpublished, pub, this.localParticipant);
22505
22590
  };
22506
22591
  this.onLocalConnectionQualityChanged = quality => {
@@ -22649,7 +22734,11 @@ class Room extends eventsExports.EventEmitter {
22649
22734
  if (this.state === ConnectionState.Reconnecting || this.isResuming) {
22650
22735
  this.sendSyncState();
22651
22736
  }
22652
- }).on(EngineEvent.Restarting, this.handleRestarting).on(EngineEvent.SignalRestarted, this.handleSignalRestarted).on(EngineEvent.DCBufferStatusChanged, (status, kind) => {
22737
+ }).on(EngineEvent.Restarting, this.handleRestarting).on(EngineEvent.SignalRestarted, this.handleSignalRestarted).on(EngineEvent.Offline, () => {
22738
+ if (this.setAndEmitConnectionState(ConnectionState.Reconnecting)) {
22739
+ this.emit(RoomEvent.Reconnecting);
22740
+ }
22741
+ }).on(EngineEvent.DCBufferStatusChanged, (status, kind) => {
22653
22742
  this.emit(RoomEvent.DCBufferStatusChanged, status, kind);
22654
22743
  });
22655
22744
  if (this.localParticipant) {
@@ -22866,8 +22955,8 @@ class Room extends eventsExports.EventEmitter {
22866
22955
  */
22867
22956
  switchActiveDevice(kind, deviceId) {
22868
22957
  let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
22869
- var _a, _b;
22870
- var _c;
22958
+ var _a, _b, _c;
22959
+ var _d;
22871
22960
  return __awaiter(this, void 0, void 0, function* () {
22872
22961
  let deviceHasChanged = false;
22873
22962
  let success = true;
@@ -22906,14 +22995,18 @@ class Room extends eventsExports.EventEmitter {
22906
22995
  if (!supportsSetSinkId() && !this.options.webAudioMix || this.options.webAudioMix && this.audioContext && !('setSinkId' in this.audioContext)) {
22907
22996
  throw new Error('cannot switch audio output, setSinkId not supported');
22908
22997
  }
22909
- (_a = (_c = this.options).audioOutput) !== null && _a !== void 0 ? _a : _c.audioOutput = {};
22998
+ if (this.options.webAudioMix) {
22999
+ // setting `default` for web audio output doesn't work, so we need to normalize the id before
23000
+ deviceId = (_a = yield DeviceManager.getInstance().normalizeDeviceId('audiooutput', deviceId)) !== null && _a !== void 0 ? _a : '';
23001
+ }
23002
+ (_b = (_d = this.options).audioOutput) !== null && _b !== void 0 ? _b : _d.audioOutput = {};
22910
23003
  const prevDeviceId = this.options.audioOutput.deviceId;
22911
23004
  this.options.audioOutput.deviceId = deviceId;
22912
23005
  deviceHasChanged = prevDeviceId !== deviceConstraint;
22913
23006
  try {
22914
23007
  if (this.options.webAudioMix) {
22915
23008
  // @ts-expect-error setSinkId is not yet in the typescript type of AudioContext
22916
- (_b = this.audioContext) === null || _b === void 0 ? void 0 : _b.setSinkId(deviceId);
23009
+ (_c = this.audioContext) === null || _c === void 0 ? void 0 : _c.setSinkId(deviceId);
22917
23010
  } else {
22918
23011
  yield Promise.all(Array.from(this.remoteParticipants.values()).map(p => p.setAudioOutput({
22919
23012
  deviceId
@@ -24036,5 +24129,5 @@ function isFacingModeValue(item) {
24036
24129
  return item === undefined || allowedValues.includes(item);
24037
24130
  }
24038
24131
 
24039
- export { AudioPresets, BaseKeyProvider, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, NegotiationError, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, importKey, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isScriptTransformSupported, isVideoFrame, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
24132
+ export { AudioPresets, BaseKeyProvider, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, NegotiationError, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, importKey, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isScriptTransformSupported, isVideoFrame, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
24040
24133
  //# sourceMappingURL=livekit-client.esm.mjs.map