livekit-client 2.0.3 → 2.0.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.
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 +11 -8
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +166 -77
  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 +1 -1
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  12. package/dist/src/e2ee/types.d.ts +2 -0
  13. package/dist/src/e2ee/types.d.ts.map +1 -1
  14. package/dist/src/e2ee/worker/FrameCryptor.d.ts +1 -0
  15. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  16. package/dist/src/index.d.ts +2 -2
  17. package/dist/src/index.d.ts.map +1 -1
  18. package/dist/src/logger.d.ts +4 -2
  19. package/dist/src/logger.d.ts.map +1 -1
  20. package/dist/src/room/DeviceManager.d.ts.map +1 -1
  21. package/dist/src/room/RTCEngine.d.ts +4 -2
  22. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  23. package/dist/src/room/Room.d.ts.map +1 -1
  24. package/dist/src/room/events.d.ts +2 -1
  25. package/dist/src/room/events.d.ts.map +1 -1
  26. package/dist/src/room/participant/Participant.d.ts +1 -2
  27. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  28. package/dist/src/room/participant/RemoteParticipant.d.ts +4 -0
  29. package/dist/src/room/participant/RemoteParticipant.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 +3 -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/options.d.ts +10 -0
  35. package/dist/src/room/track/options.d.ts.map +1 -1
  36. package/dist/src/room/track/types.d.ts +4 -0
  37. package/dist/src/room/track/types.d.ts.map +1 -1
  38. package/dist/src/room/track/utils.d.ts.map +1 -1
  39. package/dist/src/room/utils.d.ts.map +1 -1
  40. package/dist/ts4.2/src/api/SignalClient.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/index.d.ts +2 -2
  44. package/dist/ts4.2/src/logger.d.ts +4 -2
  45. package/dist/ts4.2/src/room/RTCEngine.d.ts +4 -2
  46. package/dist/ts4.2/src/room/events.d.ts +2 -1
  47. package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -2
  48. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +4 -0
  49. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -1
  50. package/dist/ts4.2/src/room/track/options.d.ts +10 -0
  51. package/dist/ts4.2/src/room/track/types.d.ts +4 -0
  52. package/package.json +1 -1
  53. package/src/api/SignalClient.ts +10 -5
  54. package/src/e2ee/E2eeManager.ts +2 -1
  55. package/src/e2ee/types.ts +2 -0
  56. package/src/e2ee/worker/FrameCryptor.ts +12 -6
  57. package/src/e2ee/worker/e2ee.worker.ts +1 -0
  58. package/src/index.ts +2 -1
  59. package/src/logger.ts +23 -18
  60. package/src/room/DeviceManager.ts +10 -1
  61. package/src/room/RTCEngine.ts +26 -8
  62. package/src/room/Room.ts +26 -2
  63. package/src/room/events.ts +1 -0
  64. package/src/room/participant/LocalParticipant.ts +4 -4
  65. package/src/room/participant/Participant.ts +0 -2
  66. package/src/room/participant/RemoteParticipant.ts +8 -0
  67. package/src/room/track/LocalAudioTrack.ts +10 -0
  68. package/src/room/track/LocalTrack.ts +20 -3
  69. package/src/room/track/LocalVideoTrack.ts +15 -1
  70. package/src/room/track/options.ts +41 -8
  71. package/src/room/track/types.ts +5 -0
  72. package/src/room/track/utils.ts +18 -11
  73. package/src/room/utils.ts +3 -0
@@ -309,6 +309,7 @@ var LoggerNames;
309
309
  LoggerNames["E2EE"] = "lk-e2ee";
310
310
  })(LoggerNames || (LoggerNames = {}));
311
311
  let livekitLogger = loglevelExports.getLogger('livekit');
312
+ const livekitLoggers = Object.values(LoggerNames).map(name => loglevelExports.getLogger(name));
312
313
  livekitLogger.setDefaultLevel(LogLevel.info);
313
314
  /**
314
315
  * @internal
@@ -322,13 +323,7 @@ function setLogLevel(level, loggerName) {
322
323
  if (loggerName) {
323
324
  loglevelExports.getLogger(loggerName).setLevel(level);
324
325
  }
325
- for (const logger of Object.entries(loglevelExports.getLoggers()).filter(_ref => {
326
- let [logrName] = _ref;
327
- return logrName.startsWith('livekit');
328
- }).map(_ref2 => {
329
- let [, logr] = _ref2;
330
- return logr;
331
- })) {
326
+ for (const logger of livekitLoggers) {
332
327
  logger.setLevel(level);
333
328
  }
334
329
  }
@@ -336,23 +331,25 @@ function setLogLevel(level, loggerName) {
336
331
  * use this to hook into the logging function to allow sending internal livekit logs to third party services
337
332
  * if set, the browser logs will lose their stacktrace information (see https://github.com/pimterry/loglevel#writing-plugins)
338
333
  */
339
- function setLogExtension(extension) {
340
- let logger = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : livekitLogger;
341
- const originalFactory = logger.methodFactory;
342
- logger.methodFactory = (methodName, configLevel, loggerName) => {
343
- const rawMethod = originalFactory(methodName, configLevel, loggerName);
344
- const logLevel = LogLevel[methodName];
345
- const needLog = logLevel >= configLevel && logLevel < LogLevel.silent;
346
- return (msg, context) => {
347
- if (context) rawMethod(msg, context);else rawMethod(msg);
348
- if (needLog) {
349
- extension(logLevel, msg, context);
350
- }
334
+ function setLogExtension(extension, logger) {
335
+ const loggers = logger ? [logger] : livekitLoggers;
336
+ loggers.forEach(logR => {
337
+ const originalFactory = logR.methodFactory;
338
+ logR.methodFactory = (methodName, configLevel, loggerName) => {
339
+ const rawMethod = originalFactory(methodName, configLevel, loggerName);
340
+ const logLevel = LogLevel[methodName];
341
+ const needLog = logLevel >= configLevel && logLevel < LogLevel.silent;
342
+ return (msg, context) => {
343
+ if (context) rawMethod(msg, context);else rawMethod(msg);
344
+ if (needLog) {
345
+ extension(logLevel, msg, context);
346
+ }
347
+ };
351
348
  };
352
- };
353
- logger.setLevel(logger.getLevel()); // Be sure to call setLevel method in order to apply plugin
349
+ logR.setLevel(logR.getLevel());
350
+ });
354
351
  }
355
- loglevelExports.getLogger('lk-e2ee');
352
+ const workerLogger = loglevelExports.getLogger('lk-e2ee');
356
353
 
357
354
  // Copyright 2021-2023 Buf Technologies, Inc.
358
355
  //
@@ -10537,6 +10534,7 @@ var EngineEvent;
10537
10534
  EngineEvent["RemoteMute"] = "remoteMute";
10538
10535
  EngineEvent["SubscribedQualityUpdate"] = "subscribedQualityUpdate";
10539
10536
  EngineEvent["LocalTrackUnpublished"] = "localTrackUnpublished";
10537
+ EngineEvent["Offline"] = "offline";
10540
10538
  })(EngineEvent || (EngineEvent = {}));
10541
10539
  var TrackEvent;
10542
10540
  (function (TrackEvent) {
@@ -10710,7 +10708,7 @@ function getMatch(exp, ua) {
10710
10708
  return match && match.length >= id && match[id] || '';
10711
10709
  }
10712
10710
 
10713
- var version$1 = "2.0.3";
10711
+ var version$1 = "2.0.5";
10714
10712
 
10715
10713
  const version = version$1;
10716
10714
  const protocolVersion = 12;
@@ -10737,21 +10735,35 @@ CriticalTimers.clearInterval = function () {
10737
10735
  };
10738
10736
 
10739
10737
  class VideoPreset {
10740
- constructor(width, height, maxBitrate, maxFramerate, priority) {
10741
- this.width = width;
10742
- this.height = height;
10743
- this.encoding = {
10744
- maxBitrate,
10745
- maxFramerate,
10746
- priority
10747
- };
10738
+ constructor(widthOrOptions, height, maxBitrate, maxFramerate, priority) {
10739
+ if (typeof widthOrOptions === 'object') {
10740
+ this.width = widthOrOptions.width;
10741
+ this.height = widthOrOptions.height;
10742
+ this.aspectRatio = widthOrOptions.aspectRatio;
10743
+ this.encoding = {
10744
+ maxBitrate: widthOrOptions.maxBitrate,
10745
+ maxFramerate: widthOrOptions.maxFramerate,
10746
+ priority: widthOrOptions.priority
10747
+ };
10748
+ } else if (height !== undefined && maxBitrate !== undefined) {
10749
+ this.width = widthOrOptions;
10750
+ this.height = height;
10751
+ this.aspectRatio = widthOrOptions / height;
10752
+ this.encoding = {
10753
+ maxBitrate,
10754
+ maxFramerate,
10755
+ priority
10756
+ };
10757
+ } else {
10758
+ throw new TypeError('Unsupported options: provide at least width, height and maxBitrate');
10759
+ }
10748
10760
  }
10749
10761
  get resolution() {
10750
10762
  return {
10751
10763
  width: this.width,
10752
10764
  height: this.height,
10753
10765
  frameRate: this.encoding.maxFramerate,
10754
- aspectRatio: this.width / this.height
10766
+ aspectRatio: this.aspectRatio
10755
10767
  };
10756
10768
  }
10757
10769
  }
@@ -13685,20 +13697,26 @@ function getTrackPublicationInfo(tracks) {
13685
13697
  function getLogContextFromTrack(track) {
13686
13698
  if (track instanceof Track) {
13687
13699
  return {
13688
- trackSid: track.sid,
13689
- trackSource: track.source,
13690
- trackMuted: track.isMuted,
13691
- trackEnabled: track.mediaStreamTrack.enabled,
13692
- trackKind: track.kind
13700
+ trackID: track.sid,
13701
+ source: track.source,
13702
+ muted: track.isMuted,
13703
+ enabled: track.mediaStreamTrack.enabled,
13704
+ kind: track.kind,
13705
+ streamID: track.mediaStreamID,
13706
+ streamTrackID: track.mediaStreamTrack.id
13693
13707
  };
13694
13708
  } else {
13695
13709
  return {
13696
- trackSid: track.trackSid,
13697
- trackName: track.trackName,
13698
- track: track.track ? getLogContextFromTrack(track.track) : undefined,
13699
- trackEnabled: track.isEnabled,
13700
- trackEncrypted: track.isEncrypted,
13701
- trackMimeType: track.mimeType
13710
+ trackID: track.trackSid,
13711
+ enabled: track.isEnabled,
13712
+ muted: track.isMuted,
13713
+ trackInfo: Object.assign({
13714
+ mimeType: track.mimeType,
13715
+ name: track.trackName,
13716
+ encrypted: track.isEncrypted,
13717
+ kind: track.kind,
13718
+ source: track.source
13719
+ }, track.track ? getLogContextFromTrack(track.track) : {})
13702
13720
  };
13703
13721
  }
13704
13722
  }
@@ -13815,6 +13833,9 @@ function supportsSetCodecPreferences(transceiver) {
13815
13833
  return false;
13816
13834
  }
13817
13835
  function isBrowserSupported() {
13836
+ if (typeof RTCPeerConnection === 'undefined') {
13837
+ return false;
13838
+ }
13818
13839
  return supportsTransceiver() || supportsAddTrack();
13819
13840
  }
13820
13841
  function isFireFox() {
@@ -14164,7 +14185,16 @@ class DeviceManager {
14164
14185
  // resolve actual device id if it's 'default': Chrome returns it when no
14165
14186
  // device has been chosen
14166
14187
  const devices = yield this.getDevices(kind);
14167
- const device = devices.find(d => d.groupId === groupId && d.deviceId !== defaultId);
14188
+ // `default` devices will have the same groupId as the entry with the actual device id so we store the counts for each group id
14189
+ const groupIdCounts = new Map(devices.map(d => [d.groupId, 0]));
14190
+ devices.forEach(d => {
14191
+ var _a;
14192
+ return groupIdCounts.set(d.groupId, ((_a = groupIdCounts.get(d.groupId)) !== null && _a !== void 0 ? _a : 0) + 1);
14193
+ });
14194
+ const device = devices.find(d => {
14195
+ var _a;
14196
+ return (groupId === d.groupId || ((_a = groupIdCounts.get(d.groupId)) !== null && _a !== void 0 ? _a : 0) > 1) && d.deviceId !== defaultId;
14197
+ });
14168
14198
  return device === null || device === void 0 ? void 0 : device.deviceId;
14169
14199
  });
14170
14200
  }
@@ -14372,18 +14402,25 @@ class LocalTrack extends Track {
14372
14402
  return this;
14373
14403
  });
14374
14404
  }
14375
- replaceTrack(track) {
14376
- let userProvidedTrack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
14405
+ replaceTrack(track, userProvidedOrOptions) {
14377
14406
  return __awaiter(this, void 0, void 0, function* () {
14378
14407
  if (!this.sender) {
14379
14408
  throw new TrackInvalidError('unable to replace an unpublished track');
14380
14409
  }
14410
+ let userProvidedTrack;
14411
+ let stopProcessor;
14412
+ if (typeof userProvidedOrOptions === 'boolean') {
14413
+ userProvidedTrack = userProvidedOrOptions;
14414
+ } else if (userProvidedOrOptions !== undefined) {
14415
+ userProvidedTrack = userProvidedOrOptions.userProvidedTrack;
14416
+ stopProcessor = userProvidedOrOptions.stopProcessor;
14417
+ }
14418
+ this.providedByUser = userProvidedTrack !== null && userProvidedTrack !== void 0 ? userProvidedTrack : true;
14381
14419
  this.log.debug('replace MediaStreamTrack', this.logContext);
14382
14420
  yield this.setMediaStreamTrack(track);
14383
14421
  // this must be synced *after* setting mediaStreamTrack above, since it relies
14384
14422
  // on the previous state in order to cleanup
14385
- this.providedByUser = userProvidedTrack;
14386
- if (this.processor) {
14423
+ if (stopProcessor && this.processor) {
14387
14424
  yield this.stopProcessor();
14388
14425
  }
14389
14426
  return this;
@@ -14685,7 +14722,8 @@ class E2EEManager extends eventsExports.EventEmitter {
14685
14722
  const msg = {
14686
14723
  kind: 'init',
14687
14724
  data: {
14688
- keyProviderOptions: this.keyProvider.getOptions()
14725
+ keyProviderOptions: this.keyProvider.getOptions(),
14726
+ loglevel: workerLogger.getLevel()
14689
14727
  }
14690
14728
  };
14691
14729
  if (this.worker) {
@@ -15123,6 +15161,7 @@ class SignalClient {
15123
15161
  };
15124
15162
  this.ws.onerror = ev => __awaiter(this, void 0, void 0, function* () {
15125
15163
  if (this.state !== SignalConnectionState.CONNECTED) {
15164
+ this.state = SignalConnectionState.DISCONNECTED;
15126
15165
  clearTimeout(wsTimeout);
15127
15166
  try {
15128
15167
  const resp = yield fetch("http".concat(url.substring(2), "/validate").concat(params));
@@ -15141,7 +15180,7 @@ class SignalClient {
15141
15180
  this.handleWSError(ev);
15142
15181
  });
15143
15182
  this.ws.onmessage = ev => __awaiter(this, void 0, void 0, function* () {
15144
- var _a, _b, _c, _d;
15183
+ var _a, _b, _c;
15145
15184
  // not considered connected until JoinResponse is received
15146
15185
  let resp;
15147
15186
  if (typeof ev.data === 'string') {
@@ -15177,16 +15216,17 @@ class SignalClient {
15177
15216
  abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', abortHandler);
15178
15217
  this.startPingInterval();
15179
15218
  if (((_b = resp.message) === null || _b === void 0 ? void 0 : _b.case) === 'reconnect') {
15180
- resolve((_c = resp.message) === null || _c === void 0 ? void 0 : _c.value);
15219
+ resolve(resp.message.value);
15181
15220
  } else {
15182
- resolve();
15221
+ this.log.debug('declaring signal reconnected without reconnect response received', this.logContext);
15222
+ resolve(undefined);
15183
15223
  shouldProcessMessage = true;
15184
15224
  }
15185
15225
  } else if (this.isEstablishingConnection && resp.message.case === 'leave') {
15186
15226
  reject(new ConnectionError('Received leave request while trying to (re)connect', 4 /* ConnectionErrorReason.LeaveRequest */));
15187
15227
  } else if (!opts.reconnect) {
15188
15228
  // non-reconnect case, should receive join response first
15189
- reject(new ConnectionError("did not receive join response, got ".concat((_d = resp.message) === null || _d === void 0 ? void 0 : _d.case, " instead")));
15229
+ reject(new ConnectionError("did not receive join response, got ".concat((_c = resp.message) === null || _c === void 0 ? void 0 : _c.case, " instead")));
15190
15230
  }
15191
15231
  if (!shouldProcessMessage) {
15192
15232
  return;
@@ -17341,11 +17381,12 @@ class RTCEngine extends eventsExports.EventEmitter {
17341
17381
  }
17342
17382
  /** @internal */
17343
17383
  get logContext() {
17344
- var _a, _b, _c, _d, _e, _f;
17384
+ var _a, _b, _c, _d, _e, _f, _g, _h;
17345
17385
  return {
17346
17386
  room: (_b = (_a = this.latestJoinResponse) === null || _a === void 0 ? void 0 : _a.room) === null || _b === void 0 ? void 0 : _b.name,
17347
- roomSid: (_d = (_c = this.latestJoinResponse) === null || _c === void 0 ? void 0 : _c.room) === null || _d === void 0 ? void 0 : _d.sid,
17348
- identity: (_f = (_e = this.latestJoinResponse) === null || _e === void 0 ? void 0 : _e.participant) === null || _f === void 0 ? void 0 : _f.identity
17387
+ roomID: (_d = (_c = this.latestJoinResponse) === null || _c === void 0 ? void 0 : _c.room) === null || _d === void 0 ? void 0 : _d.sid,
17388
+ participant: (_f = (_e = this.latestJoinResponse) === null || _e === void 0 ? void 0 : _e.participant) === null || _f === void 0 ? void 0 : _f.identity,
17389
+ pID: (_h = (_g = this.latestJoinResponse) === null || _g === void 0 ? void 0 : _g.participant) === null || _h === void 0 ? void 0 : _h.sid
17349
17390
  };
17350
17391
  }
17351
17392
  join(url, token, opts, abortSignal) {
@@ -17532,6 +17573,12 @@ class RTCEngine extends eventsExports.EventEmitter {
17532
17573
  this.handleDisconnect('peerconnection failed', subscriberState === 'failed' ? ReconnectReason.RR_SUBSCRIBER_FAILED : ReconnectReason.RR_PUBLISHER_FAILED);
17533
17574
  }
17534
17575
  }
17576
+ // detect cases where both signal client and peer connection are severed and assume that user has lost network connection
17577
+ const isSignalSevered = this.client.isDisconnected || this.client.currentState === SignalConnectionState.RECONNECTING;
17578
+ const isPCSevered = [PCTransportState.FAILED, PCTransportState.CLOSING, PCTransportState.CLOSED].includes(connectionState);
17579
+ if (isSignalSevered && isPCSevered && !this._isClosed) {
17580
+ this.emit(EngineEvent.Offline);
17581
+ }
17535
17582
  });
17536
17583
  this.pcManager.onTrack = ev => {
17537
17584
  this.emit(EngineEvent.MediaTrackAdded, ev.track, ev.streams[0], ev.receiver);
@@ -17935,13 +17982,10 @@ class RTCEngine extends eventsExports.EventEmitter {
17935
17982
  }
17936
17983
  this.log.info("resuming signal connection, attempt ".concat(this.reconnectAttempts), this.logContext);
17937
17984
  this.emit(EngineEvent.Resuming);
17985
+ let res;
17938
17986
  try {
17939
17987
  this.setupSignalClientCallbacks();
17940
- const res = yield this.client.reconnect(this.url, this.token, this.participantSid, reason);
17941
- if (res) {
17942
- const rtcConfig = this.makeRTCConfiguration(res);
17943
- this.pcManager.updateConfiguration(rtcConfig);
17944
- }
17988
+ res = yield this.client.reconnect(this.url, this.token, this.participantSid, reason);
17945
17989
  } catch (error) {
17946
17990
  let message = '';
17947
17991
  if (error instanceof Error) {
@@ -17959,6 +18003,12 @@ class RTCEngine extends eventsExports.EventEmitter {
17959
18003
  throw new SignalReconnectError(message);
17960
18004
  }
17961
18005
  this.emit(EngineEvent.SignalResumed);
18006
+ if (res) {
18007
+ const rtcConfig = this.makeRTCConfiguration(res);
18008
+ this.pcManager.updateConfiguration(rtcConfig);
18009
+ } else {
18010
+ this.log.warn('Did not receive reconnect response', this.logContext);
18011
+ }
17962
18012
  if (this.shouldFailNext) {
17963
18013
  this.shouldFailNext = false;
17964
18014
  throw new Error('simulated failure');
@@ -18362,6 +18412,10 @@ class LocalAudioTrack extends LocalTrack {
18362
18412
  return __awaiter(this, void 0, void 0, function* () {
18363
18413
  const unlock = yield this.muteLock.lock();
18364
18414
  try {
18415
+ if (this.isMuted) {
18416
+ this.log.debug('Track already muted', this.logContext);
18417
+ return this;
18418
+ }
18365
18419
  // disabled special handling as it will cause BT headsets to switch communication modes
18366
18420
  if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
18367
18421
  this.log.debug('stopping mic track', this.logContext);
@@ -18384,6 +18438,10 @@ class LocalAudioTrack extends LocalTrack {
18384
18438
  return __awaiter(this, void 0, void 0, function* () {
18385
18439
  const unlock = yield this.muteLock.lock();
18386
18440
  try {
18441
+ if (!this.isMuted) {
18442
+ this.log.debug('Track already unmuted', this.logContext);
18443
+ return this;
18444
+ }
18387
18445
  const deviceHasChanged = this._constraints.deviceId && this._mediaStreamTrack.getSettings().deviceId !== unwrapConstraint(this._constraints.deviceId);
18388
18446
  if (this.source === Track.Source.Microphone && (this.stopOnMute || this._mediaStreamTrack.readyState === 'ended' || deviceHasChanged) && !this.isUserProvided) {
18389
18447
  this.log.debug('reacquiring mic track', this.logContext);
@@ -18953,6 +19011,10 @@ class LocalVideoTrack extends LocalTrack {
18953
19011
  return __awaiter(this, void 0, void 0, function* () {
18954
19012
  const unlock = yield this.muteLock.lock();
18955
19013
  try {
19014
+ if (this.isMuted) {
19015
+ this.log.debug('Track already muted', this.logContext);
19016
+ return this;
19017
+ }
18956
19018
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
18957
19019
  this.log.debug('stopping camera track', this.logContext);
18958
19020
  // also stop the track, so that camera indicator is turned off
@@ -18974,6 +19036,10 @@ class LocalVideoTrack extends LocalTrack {
18974
19036
  return __awaiter(this, void 0, void 0, function* () {
18975
19037
  const unlock = yield this.muteLock.lock();
18976
19038
  try {
19039
+ if (!this.isMuted) {
19040
+ this.log.debug('Track already unmuted', this.logContext);
19041
+ return this;
19042
+ }
18977
19043
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
18978
19044
  this.log.debug('reacquiring camera track', this.logContext);
18979
19045
  yield this.restartTrack();
@@ -19260,7 +19326,10 @@ function setPublishingLayersForSender(sender, senderEncodings, qualities, sender
19260
19326
  return;
19261
19327
  }
19262
19328
  if (encodings.length !== senderEncodings.length) {
19263
- log.warn('cannot set publishing layers, encodings mismatch');
19329
+ log.warn('cannot set publishing layers, encodings mismatch', Object.assign(Object.assign({}, logContext), {
19330
+ encodings,
19331
+ senderEncodings
19332
+ }));
19264
19333
  return;
19265
19334
  }
19266
19335
  let hasChanged = false;
@@ -20152,10 +20221,7 @@ function qualityFromProto(q) {
20152
20221
  class Participant extends eventsExports.EventEmitter {
20153
20222
  get logContext() {
20154
20223
  var _a, _b;
20155
- return Object.assign(Object.assign({}, (_b = (_a = this.loggerOptions) === null || _a === void 0 ? void 0 : _a.loggerContextCb) === null || _b === void 0 ? void 0 : _b.call(_a)), {
20156
- participantSid: this.sid,
20157
- participantId: this.identity
20158
- });
20224
+ return Object.assign({}, (_b = (_a = this.loggerOptions) === null || _a === void 0 ? void 0 : _a.loggerContextCb) === null || _b === void 0 ? void 0 : _b.call(_a));
20159
20225
  }
20160
20226
  get isEncrypted() {
20161
20227
  return this.trackPublications.size > 0 && Array.from(this.trackPublications.values()).every(tr => tr.isEncrypted);
@@ -20829,6 +20895,9 @@ class LocalParticipant extends Participant {
20829
20895
  publishTrack(track, options) {
20830
20896
  var _a, _b, _c, _d;
20831
20897
  return __awaiter(this, void 0, void 0, function* () {
20898
+ if (track instanceof LocalAudioTrack) {
20899
+ track.setAudioContext(this.audioContext);
20900
+ }
20832
20901
  yield (_a = this.reconnectFuture) === null || _a === void 0 ? void 0 : _a.promise;
20833
20902
  if (track instanceof LocalTrack && this.pendingPublishPromises.has(track)) {
20834
20903
  yield this.pendingPublishPromises.get(track);
@@ -20878,9 +20947,6 @@ class LocalParticipant extends Participant {
20878
20947
  loggerContextCb: () => this.logContext
20879
20948
  });
20880
20949
  }
20881
- if (track instanceof LocalAudioTrack) {
20882
- track.setAudioContext(this.audioContext);
20883
- }
20884
20950
  // is it already published? if so skip
20885
20951
  let existingPublication;
20886
20952
  this.trackPublications.forEach(publication => {
@@ -21645,6 +21711,12 @@ class RemoteParticipant extends Participant {
21645
21711
  static fromParticipantInfo(signalClient, pi) {
21646
21712
  return new RemoteParticipant(signalClient, pi.sid, pi.identity, pi.name, pi.metadata);
21647
21713
  }
21714
+ get logContext() {
21715
+ return Object.assign(Object.assign({}, super.logContext), {
21716
+ rpID: this.sid,
21717
+ remoteParticipant: this.identity
21718
+ });
21719
+ }
21648
21720
  /** @internal */
21649
21721
  constructor(signalClient, sid, identity, name, metadata, loggerOptions) {
21650
21722
  super(sid, identity || '', name, metadata, loggerOptions);
@@ -21939,6 +22011,13 @@ class Room extends eventsExports.EventEmitter {
21939
22011
  this.isResuming = false;
21940
22012
  this.connect = (url, token, opts) => __awaiter(this, void 0, void 0, function* () {
21941
22013
  var _c;
22014
+ if (!isBrowserSupported()) {
22015
+ if (isReactNative()) {
22016
+ throw Error("WebRTC isn't detected, have you called registerGlobals?");
22017
+ } else {
22018
+ throw Error("LiveKit doesn't seem to be supported on this browser. Try to update your browser and make sure no browser extensions are disabling webRTC.");
22019
+ }
22020
+ }
21942
22021
  // In case a disconnect called happened right before the connect call, make sure the disconnect is completed first by awaiting its lock
21943
22022
  const unlockDisconnect = yield this.disconnectLock.lock();
21944
22023
  if (this.state === ConnectionState.Connected) {
@@ -22180,6 +22259,7 @@ class Room extends eventsExports.EventEmitter {
22180
22259
  });
22181
22260
  };
22182
22261
  this.onPageLeave = () => __awaiter(this, void 0, void 0, function* () {
22262
+ this.log.info('Page leave detected, disconnecting', this.logContext);
22183
22263
  yield this.disconnect();
22184
22264
  });
22185
22265
  /**
@@ -22598,8 +22678,9 @@ class Room extends eventsExports.EventEmitter {
22598
22678
  var _a;
22599
22679
  return {
22600
22680
  room: this.name,
22601
- roomSid: (_a = this.roomInfo) === null || _a === void 0 ? void 0 : _a.sid,
22602
- identity: this.localParticipant.identity
22681
+ roomID: (_a = this.roomInfo) === null || _a === void 0 ? void 0 : _a.sid,
22682
+ participant: this.localParticipant.identity,
22683
+ pID: this.localParticipant.sid
22603
22684
  };
22604
22685
  }
22605
22686
  /**
@@ -22678,7 +22759,11 @@ class Room extends eventsExports.EventEmitter {
22678
22759
  if (this.state === ConnectionState.Reconnecting || this.isResuming) {
22679
22760
  this.sendSyncState();
22680
22761
  }
22681
- }).on(EngineEvent.Restarting, this.handleRestarting).on(EngineEvent.SignalRestarted, this.handleSignalRestarted).on(EngineEvent.DCBufferStatusChanged, (status, kind) => {
22762
+ }).on(EngineEvent.Restarting, this.handleRestarting).on(EngineEvent.SignalRestarted, this.handleSignalRestarted).on(EngineEvent.Offline, () => {
22763
+ if (this.setAndEmitConnectionState(ConnectionState.Reconnecting)) {
22764
+ this.emit(RoomEvent.Reconnecting);
22765
+ }
22766
+ }).on(EngineEvent.DCBufferStatusChanged, (status, kind) => {
22682
22767
  this.emit(RoomEvent.DCBufferStatusChanged, status, kind);
22683
22768
  });
22684
22769
  if (this.localParticipant) {
@@ -22895,8 +22980,8 @@ class Room extends eventsExports.EventEmitter {
22895
22980
  */
22896
22981
  switchActiveDevice(kind, deviceId) {
22897
22982
  let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
22898
- var _a, _b;
22899
- var _c;
22983
+ var _a, _b, _c;
22984
+ var _d;
22900
22985
  return __awaiter(this, void 0, void 0, function* () {
22901
22986
  let deviceHasChanged = false;
22902
22987
  let success = true;
@@ -22935,14 +23020,18 @@ class Room extends eventsExports.EventEmitter {
22935
23020
  if (!supportsSetSinkId() && !this.options.webAudioMix || this.options.webAudioMix && this.audioContext && !('setSinkId' in this.audioContext)) {
22936
23021
  throw new Error('cannot switch audio output, setSinkId not supported');
22937
23022
  }
22938
- (_a = (_c = this.options).audioOutput) !== null && _a !== void 0 ? _a : _c.audioOutput = {};
23023
+ if (this.options.webAudioMix) {
23024
+ // setting `default` for web audio output doesn't work, so we need to normalize the id before
23025
+ deviceId = (_a = yield DeviceManager.getInstance().normalizeDeviceId('audiooutput', deviceId)) !== null && _a !== void 0 ? _a : '';
23026
+ }
23027
+ (_b = (_d = this.options).audioOutput) !== null && _b !== void 0 ? _b : _d.audioOutput = {};
22939
23028
  const prevDeviceId = this.options.audioOutput.deviceId;
22940
23029
  this.options.audioOutput.deviceId = deviceId;
22941
23030
  deviceHasChanged = prevDeviceId !== deviceConstraint;
22942
23031
  try {
22943
23032
  if (this.options.webAudioMix) {
22944
23033
  // @ts-expect-error setSinkId is not yet in the typescript type of AudioContext
22945
- (_b = this.audioContext) === null || _b === void 0 ? void 0 : _b.setSinkId(deviceId);
23034
+ (_c = this.audioContext) === null || _c === void 0 ? void 0 : _c.setSinkId(deviceId);
22946
23035
  } else {
22947
23036
  yield Promise.all(Array.from(this.remoteParticipants.values()).map(p => p.setAudioOutput({
22948
23037
  deviceId
@@ -24065,5 +24154,5 @@ function isFacingModeValue(item) {
24065
24154
  return item === undefined || allowedValues.includes(item);
24066
24155
  }
24067
24156
 
24068
- 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 };
24157
+ 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 };
24069
24158
  //# sourceMappingURL=livekit-client.esm.mjs.map