livekit-client 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) 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 +1 -0
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +90 -26
  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/types.d.ts +2 -0
  12. package/dist/src/e2ee/types.d.ts.map +1 -1
  13. package/dist/src/index.d.ts +2 -2
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/logger.d.ts +2 -0
  16. package/dist/src/logger.d.ts.map +1 -1
  17. package/dist/src/room/DeviceManager.d.ts.map +1 -1
  18. package/dist/src/room/RTCEngine.d.ts +1 -0
  19. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  20. package/dist/src/room/Room.d.ts.map +1 -1
  21. package/dist/src/room/events.d.ts +2 -1
  22. package/dist/src/room/events.d.ts.map +1 -1
  23. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  24. package/dist/src/room/track/LocalTrack.d.ts +3 -1
  25. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  27. package/dist/src/room/track/options.d.ts +10 -0
  28. package/dist/src/room/track/options.d.ts.map +1 -1
  29. package/dist/src/room/track/types.d.ts +4 -0
  30. package/dist/src/room/track/types.d.ts.map +1 -1
  31. package/dist/ts4.2/src/e2ee/types.d.ts +2 -0
  32. package/dist/ts4.2/src/index.d.ts +2 -2
  33. package/dist/ts4.2/src/logger.d.ts +2 -0
  34. package/dist/ts4.2/src/room/RTCEngine.d.ts +1 -0
  35. package/dist/ts4.2/src/room/events.d.ts +2 -1
  36. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -1
  37. package/dist/ts4.2/src/room/track/options.d.ts +10 -0
  38. package/dist/ts4.2/src/room/track/types.d.ts +4 -0
  39. package/package.json +1 -1
  40. package/src/api/SignalClient.ts +1 -0
  41. package/src/e2ee/E2eeManager.ts +2 -1
  42. package/src/e2ee/types.ts +2 -0
  43. package/src/e2ee/worker/e2ee.worker.ts +1 -0
  44. package/src/index.ts +2 -1
  45. package/src/logger.ts +2 -0
  46. package/src/room/DeviceManager.ts +10 -1
  47. package/src/room/RTCEngine.ts +14 -0
  48. package/src/room/Room.ts +11 -0
  49. package/src/room/events.ts +1 -0
  50. package/src/room/participant/LocalParticipant.ts +4 -4
  51. package/src/room/track/LocalAudioTrack.ts +10 -0
  52. package/src/room/track/LocalTrack.ts +20 -3
  53. package/src/room/track/LocalVideoTrack.ts +10 -0
  54. package/src/room/track/options.ts +41 -8
  55. 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
  //
@@ -10537,6 +10537,7 @@ var EngineEvent;
10537
10537
  EngineEvent["RemoteMute"] = "remoteMute";
10538
10538
  EngineEvent["SubscribedQualityUpdate"] = "subscribedQualityUpdate";
10539
10539
  EngineEvent["LocalTrackUnpublished"] = "localTrackUnpublished";
10540
+ EngineEvent["Offline"] = "offline";
10540
10541
  })(EngineEvent || (EngineEvent = {}));
10541
10542
  var TrackEvent;
10542
10543
  (function (TrackEvent) {
@@ -10710,7 +10711,7 @@ function getMatch(exp, ua) {
10710
10711
  return match && match.length >= id && match[id] || '';
10711
10712
  }
10712
10713
 
10713
- var version$1 = "2.0.3";
10714
+ var version$1 = "2.0.4";
10714
10715
 
10715
10716
  const version = version$1;
10716
10717
  const protocolVersion = 12;
@@ -10737,21 +10738,35 @@ CriticalTimers.clearInterval = function () {
10737
10738
  };
10738
10739
 
10739
10740
  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
- };
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
+ }
10748
10763
  }
10749
10764
  get resolution() {
10750
10765
  return {
10751
10766
  width: this.width,
10752
10767
  height: this.height,
10753
10768
  frameRate: this.encoding.maxFramerate,
10754
- aspectRatio: this.width / this.height
10769
+ aspectRatio: this.aspectRatio
10755
10770
  };
10756
10771
  }
10757
10772
  }
@@ -14164,7 +14179,16 @@ class DeviceManager {
14164
14179
  // resolve actual device id if it's 'default': Chrome returns it when no
14165
14180
  // device has been chosen
14166
14181
  const devices = yield this.getDevices(kind);
14167
- 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
+ });
14168
14192
  return device === null || device === void 0 ? void 0 : device.deviceId;
14169
14193
  });
14170
14194
  }
@@ -14372,18 +14396,25 @@ class LocalTrack extends Track {
14372
14396
  return this;
14373
14397
  });
14374
14398
  }
14375
- replaceTrack(track) {
14376
- let userProvidedTrack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
14399
+ replaceTrack(track, userProvidedOrOptions) {
14377
14400
  return __awaiter(this, void 0, void 0, function* () {
14378
14401
  if (!this.sender) {
14379
14402
  throw new TrackInvalidError('unable to replace an unpublished track');
14380
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;
14381
14413
  this.log.debug('replace MediaStreamTrack', this.logContext);
14382
14414
  yield this.setMediaStreamTrack(track);
14383
14415
  // this must be synced *after* setting mediaStreamTrack above, since it relies
14384
14416
  // on the previous state in order to cleanup
14385
- this.providedByUser = userProvidedTrack;
14386
- if (this.processor) {
14417
+ if (stopProcessor && this.processor) {
14387
14418
  yield this.stopProcessor();
14388
14419
  }
14389
14420
  return this;
@@ -14685,7 +14716,8 @@ class E2EEManager extends eventsExports.EventEmitter {
14685
14716
  const msg = {
14686
14717
  kind: 'init',
14687
14718
  data: {
14688
- keyProviderOptions: this.keyProvider.getOptions()
14719
+ keyProviderOptions: this.keyProvider.getOptions(),
14720
+ loglevel: workerLogger.getLevel()
14689
14721
  }
14690
14722
  };
14691
14723
  if (this.worker) {
@@ -15123,6 +15155,7 @@ class SignalClient {
15123
15155
  };
15124
15156
  this.ws.onerror = ev => __awaiter(this, void 0, void 0, function* () {
15125
15157
  if (this.state !== SignalConnectionState.CONNECTED) {
15158
+ this.state = SignalConnectionState.DISCONNECTED;
15126
15159
  clearTimeout(wsTimeout);
15127
15160
  try {
15128
15161
  const resp = yield fetch("http".concat(url.substring(2), "/validate").concat(params));
@@ -17532,6 +17565,12 @@ class RTCEngine extends eventsExports.EventEmitter {
17532
17565
  this.handleDisconnect('peerconnection failed', subscriberState === 'failed' ? ReconnectReason.RR_SUBSCRIBER_FAILED : ReconnectReason.RR_PUBLISHER_FAILED);
17533
17566
  }
17534
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
+ }
17535
17574
  });
17536
17575
  this.pcManager.onTrack = ev => {
17537
17576
  this.emit(EngineEvent.MediaTrackAdded, ev.track, ev.streams[0], ev.receiver);
@@ -18362,6 +18401,10 @@ class LocalAudioTrack extends LocalTrack {
18362
18401
  return __awaiter(this, void 0, void 0, function* () {
18363
18402
  const unlock = yield this.muteLock.lock();
18364
18403
  try {
18404
+ if (this.isMuted) {
18405
+ this.log.debug('Track already muted', this.logContext);
18406
+ return this;
18407
+ }
18365
18408
  // disabled special handling as it will cause BT headsets to switch communication modes
18366
18409
  if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
18367
18410
  this.log.debug('stopping mic track', this.logContext);
@@ -18384,6 +18427,10 @@ class LocalAudioTrack extends LocalTrack {
18384
18427
  return __awaiter(this, void 0, void 0, function* () {
18385
18428
  const unlock = yield this.muteLock.lock();
18386
18429
  try {
18430
+ if (!this.isMuted) {
18431
+ this.log.debug('Track already unmuted', this.logContext);
18432
+ return this;
18433
+ }
18387
18434
  const deviceHasChanged = this._constraints.deviceId && this._mediaStreamTrack.getSettings().deviceId !== unwrapConstraint(this._constraints.deviceId);
18388
18435
  if (this.source === Track.Source.Microphone && (this.stopOnMute || this._mediaStreamTrack.readyState === 'ended' || deviceHasChanged) && !this.isUserProvided) {
18389
18436
  this.log.debug('reacquiring mic track', this.logContext);
@@ -18953,6 +19000,10 @@ class LocalVideoTrack extends LocalTrack {
18953
19000
  return __awaiter(this, void 0, void 0, function* () {
18954
19001
  const unlock = yield this.muteLock.lock();
18955
19002
  try {
19003
+ if (this.isMuted) {
19004
+ this.log.debug('Track already muted', this.logContext);
19005
+ return this;
19006
+ }
18956
19007
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
18957
19008
  this.log.debug('stopping camera track', this.logContext);
18958
19009
  // also stop the track, so that camera indicator is turned off
@@ -18974,6 +19025,10 @@ class LocalVideoTrack extends LocalTrack {
18974
19025
  return __awaiter(this, void 0, void 0, function* () {
18975
19026
  const unlock = yield this.muteLock.lock();
18976
19027
  try {
19028
+ if (!this.isMuted) {
19029
+ this.log.debug('Track already unmuted', this.logContext);
19030
+ return this;
19031
+ }
18977
19032
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
18978
19033
  this.log.debug('reacquiring camera track', this.logContext);
18979
19034
  yield this.restartTrack();
@@ -20829,6 +20884,9 @@ class LocalParticipant extends Participant {
20829
20884
  publishTrack(track, options) {
20830
20885
  var _a, _b, _c, _d;
20831
20886
  return __awaiter(this, void 0, void 0, function* () {
20887
+ if (track instanceof LocalAudioTrack) {
20888
+ track.setAudioContext(this.audioContext);
20889
+ }
20832
20890
  yield (_a = this.reconnectFuture) === null || _a === void 0 ? void 0 : _a.promise;
20833
20891
  if (track instanceof LocalTrack && this.pendingPublishPromises.has(track)) {
20834
20892
  yield this.pendingPublishPromises.get(track);
@@ -20878,9 +20936,6 @@ class LocalParticipant extends Participant {
20878
20936
  loggerContextCb: () => this.logContext
20879
20937
  });
20880
20938
  }
20881
- if (track instanceof LocalAudioTrack) {
20882
- track.setAudioContext(this.audioContext);
20883
- }
20884
20939
  // is it already published? if so skip
20885
20940
  let existingPublication;
20886
20941
  this.trackPublications.forEach(publication => {
@@ -22180,6 +22235,7 @@ class Room extends eventsExports.EventEmitter {
22180
22235
  });
22181
22236
  };
22182
22237
  this.onPageLeave = () => __awaiter(this, void 0, void 0, function* () {
22238
+ this.log.info('Page leave detected, disconnecting', this.logContext);
22183
22239
  yield this.disconnect();
22184
22240
  });
22185
22241
  /**
@@ -22678,7 +22734,11 @@ class Room extends eventsExports.EventEmitter {
22678
22734
  if (this.state === ConnectionState.Reconnecting || this.isResuming) {
22679
22735
  this.sendSyncState();
22680
22736
  }
22681
- }).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) => {
22682
22742
  this.emit(RoomEvent.DCBufferStatusChanged, status, kind);
22683
22743
  });
22684
22744
  if (this.localParticipant) {
@@ -22895,8 +22955,8 @@ class Room extends eventsExports.EventEmitter {
22895
22955
  */
22896
22956
  switchActiveDevice(kind, deviceId) {
22897
22957
  let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
22898
- var _a, _b;
22899
- var _c;
22958
+ var _a, _b, _c;
22959
+ var _d;
22900
22960
  return __awaiter(this, void 0, void 0, function* () {
22901
22961
  let deviceHasChanged = false;
22902
22962
  let success = true;
@@ -22935,14 +22995,18 @@ class Room extends eventsExports.EventEmitter {
22935
22995
  if (!supportsSetSinkId() && !this.options.webAudioMix || this.options.webAudioMix && this.audioContext && !('setSinkId' in this.audioContext)) {
22936
22996
  throw new Error('cannot switch audio output, setSinkId not supported');
22937
22997
  }
22938
- (_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 = {};
22939
23003
  const prevDeviceId = this.options.audioOutput.deviceId;
22940
23004
  this.options.audioOutput.deviceId = deviceId;
22941
23005
  deviceHasChanged = prevDeviceId !== deviceConstraint;
22942
23006
  try {
22943
23007
  if (this.options.webAudioMix) {
22944
23008
  // @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);
23009
+ (_c = this.audioContext) === null || _c === void 0 ? void 0 : _c.setSinkId(deviceId);
22946
23010
  } else {
22947
23011
  yield Promise.all(Array.from(this.remoteParticipants.values()).map(p => p.setAudioOutput({
22948
23012
  deviceId
@@ -24065,5 +24129,5 @@ function isFacingModeValue(item) {
24065
24129
  return item === undefined || allowedValues.includes(item);
24066
24130
  }
24067
24131
 
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 };
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 };
24069
24133
  //# sourceMappingURL=livekit-client.esm.mjs.map