livekit-client 2.5.1 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -6236,7 +6236,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
6236
6236
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
6237
6237
  PERFORMANCE OF THIS SOFTWARE.
6238
6238
  ***************************************************************************** */
6239
- /* global Reflect, Promise, SuppressedError, Symbol */
6239
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
6240
6240
 
6241
6241
 
6242
6242
  function __awaiter(thisArg, _arguments, P, generator) {
@@ -10714,7 +10714,7 @@ function getOSVersion(ua) {
10714
10714
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
10715
10715
  }
10716
10716
 
10717
- var version$1 = "2.5.1";
10717
+ var version$1 = "2.5.2";
10718
10718
 
10719
10719
  const version = version$1;
10720
10720
  const protocolVersion = 15;
@@ -12139,17 +12139,21 @@ class LocalTrack extends Track {
12139
12139
  * @returns DeviceID of the device that is currently being used for this track
12140
12140
  */
12141
12141
  getDeviceId() {
12142
- return __awaiter(this, void 0, void 0, function* () {
12143
- // screen share doesn't have a usable device id
12144
- if (this.source === Track.Source.ScreenShare) {
12145
- return;
12146
- }
12147
- const {
12148
- deviceId,
12149
- groupId
12150
- } = this._mediaStreamTrack.getSettings();
12151
- const kind = this.kind === Track.Kind.Audio ? 'audioinput' : 'videoinput';
12152
- return DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId);
12142
+ return __awaiter(this, arguments, void 0, function () {
12143
+ var _this2 = this;
12144
+ let normalize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
12145
+ return function* () {
12146
+ // screen share doesn't have a usable device id
12147
+ if (_this2.source === Track.Source.ScreenShare) {
12148
+ return;
12149
+ }
12150
+ const {
12151
+ deviceId,
12152
+ groupId
12153
+ } = _this2._mediaStreamTrack.getSettings();
12154
+ const kind = _this2.kind === Track.Kind.Audio ? 'audioinput' : 'videoinput';
12155
+ return normalize ? DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId) : deviceId;
12156
+ }();
12153
12157
  });
12154
12158
  }
12155
12159
  mute() {
@@ -12353,45 +12357,45 @@ class LocalTrack extends Track {
12353
12357
  */
12354
12358
  setProcessor(processor_1) {
12355
12359
  return __awaiter(this, arguments, void 0, function (processor) {
12356
- var _this2 = this;
12360
+ var _this3 = this;
12357
12361
  let showProcessedStreamLocally = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
12358
12362
  return function* () {
12359
12363
  var _a;
12360
- const unlock = yield _this2.processorLock.lock();
12364
+ const unlock = yield _this3.processorLock.lock();
12361
12365
  try {
12362
- _this2.log.debug('setting up processor', _this2.logContext);
12363
- const processorElement = document.createElement(_this2.kind);
12366
+ _this3.log.debug('setting up processor', _this3.logContext);
12367
+ const processorElement = document.createElement(_this3.kind);
12364
12368
  const processorOptions = {
12365
- kind: _this2.kind,
12366
- track: _this2._mediaStreamTrack,
12369
+ kind: _this3.kind,
12370
+ track: _this3._mediaStreamTrack,
12367
12371
  element: processorElement,
12368
- audioContext: _this2.audioContext
12372
+ audioContext: _this3.audioContext
12369
12373
  };
12370
12374
  yield processor.init(processorOptions);
12371
- _this2.log.debug('processor initialized', _this2.logContext);
12372
- if (_this2.processor) {
12373
- yield _this2.stopProcessor();
12375
+ _this3.log.debug('processor initialized', _this3.logContext);
12376
+ if (_this3.processor) {
12377
+ yield _this3.stopProcessor();
12374
12378
  }
12375
- if (_this2.kind === 'unknown') {
12379
+ if (_this3.kind === 'unknown') {
12376
12380
  throw TypeError('cannot set processor on track of unknown kind');
12377
12381
  }
12378
- attachToElement(_this2._mediaStreamTrack, processorElement);
12382
+ attachToElement(_this3._mediaStreamTrack, processorElement);
12379
12383
  processorElement.muted = true;
12380
- processorElement.play().catch(error => _this2.log.error('failed to play processor element', Object.assign(Object.assign({}, _this2.logContext), {
12384
+ processorElement.play().catch(error => _this3.log.error('failed to play processor element', Object.assign(Object.assign({}, _this3.logContext), {
12381
12385
  error
12382
12386
  })));
12383
- _this2.processor = processor;
12384
- _this2.processorElement = processorElement;
12385
- if (_this2.processor.processedTrack) {
12386
- for (const el of _this2.attachedElements) {
12387
- if (el !== _this2.processorElement && showProcessedStreamLocally) {
12388
- detachTrack(_this2._mediaStreamTrack, el);
12389
- attachToElement(_this2.processor.processedTrack, el);
12387
+ _this3.processor = processor;
12388
+ _this3.processorElement = processorElement;
12389
+ if (_this3.processor.processedTrack) {
12390
+ for (const el of _this3.attachedElements) {
12391
+ if (el !== _this3.processorElement && showProcessedStreamLocally) {
12392
+ detachTrack(_this3._mediaStreamTrack, el);
12393
+ attachToElement(_this3.processor.processedTrack, el);
12390
12394
  }
12391
12395
  }
12392
- yield (_a = _this2.sender) === null || _a === void 0 ? void 0 : _a.replaceTrack(_this2.processor.processedTrack);
12396
+ yield (_a = _this3.sender) === null || _a === void 0 ? void 0 : _a.replaceTrack(_this3.processor.processedTrack);
12393
12397
  }
12394
- _this2.emit(TrackEvent.TrackProcessorUpdate, _this2.processor);
12398
+ _this3.emit(TrackEvent.TrackProcessorUpdate, _this3.processor);
12395
12399
  } finally {
12396
12400
  unlock();
12397
12401
  }
@@ -12410,24 +12414,24 @@ class LocalTrack extends Track {
12410
12414
  */
12411
12415
  stopProcessor() {
12412
12416
  return __awaiter(this, arguments, void 0, function () {
12413
- var _this3 = this;
12417
+ var _this4 = this;
12414
12418
  let keepElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
12415
12419
  return function* () {
12416
12420
  var _a, _b;
12417
- if (!_this3.processor) return;
12418
- _this3.log.debug('stopping processor', _this3.logContext);
12419
- (_a = _this3.processor.processedTrack) === null || _a === void 0 ? void 0 : _a.stop();
12420
- yield _this3.processor.destroy();
12421
- _this3.processor = undefined;
12421
+ if (!_this4.processor) return;
12422
+ _this4.log.debug('stopping processor', _this4.logContext);
12423
+ (_a = _this4.processor.processedTrack) === null || _a === void 0 ? void 0 : _a.stop();
12424
+ yield _this4.processor.destroy();
12425
+ _this4.processor = undefined;
12422
12426
  if (!keepElement) {
12423
- (_b = _this3.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
12424
- _this3.processorElement = undefined;
12427
+ (_b = _this4.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
12428
+ _this4.processorElement = undefined;
12425
12429
  }
12426
12430
  // apply original track constraints in case the processor changed them
12427
- yield _this3._mediaStreamTrack.applyConstraints(_this3._constraints);
12431
+ yield _this4._mediaStreamTrack.applyConstraints(_this4._constraints);
12428
12432
  // force re-setting of the mediaStreamTrack on the sender
12429
- yield _this3.setMediaStreamTrack(_this3._mediaStreamTrack, true);
12430
- _this3.emit(TrackEvent.TrackProcessorUpdate);
12433
+ yield _this4.setMediaStreamTrack(_this4._mediaStreamTrack, true);
12434
+ _this4.emit(TrackEvent.TrackProcessorUpdate);
12431
12435
  }();
12432
12436
  });
12433
12437
  }
@@ -14801,6 +14805,7 @@ class PCTransportManager {
14801
14805
  };
14802
14806
  this.state = PCTransportState.NEW;
14803
14807
  this.connectionLock = new Mutex();
14808
+ this.remoteOfferLock = new Mutex();
14804
14809
  }
14805
14810
  get logContext() {
14806
14811
  var _a, _b;
@@ -14873,10 +14878,15 @@ class PCTransportManager {
14873
14878
  sdp: sd.sdp,
14874
14879
  signalingState: this.subscriber.getSignallingState().toString()
14875
14880
  }));
14876
- yield this.subscriber.setRemoteDescription(sd);
14877
- // answer the offer
14878
- const answer = yield this.subscriber.createAndSetAnswer();
14879
- return answer;
14881
+ const unlock = yield this.remoteOfferLock.lock();
14882
+ try {
14883
+ yield this.subscriber.setRemoteDescription(sd);
14884
+ // answer the offer
14885
+ const answer = yield this.subscriber.createAndSetAnswer();
14886
+ return answer;
14887
+ } finally {
14888
+ unlock();
14889
+ }
14880
14890
  });
14881
14891
  }
14882
14892
  updateConfiguration(config, iceRestart) {
@@ -18209,6 +18219,141 @@ class LocalTrackPublication extends TrackPublication {
18209
18219
  }
18210
18220
  }
18211
18221
 
18222
+ /** @internal */
18223
+ function extractProcessorsFromOptions(options) {
18224
+ let audioProcessor;
18225
+ let videoProcessor;
18226
+ if (typeof options.audio === 'object' && options.audio.processor) {
18227
+ audioProcessor = options.audio.processor;
18228
+ }
18229
+ if (typeof options.video === 'object' && options.video.processor) {
18230
+ videoProcessor = options.video.processor;
18231
+ }
18232
+ return {
18233
+ audioProcessor,
18234
+ videoProcessor
18235
+ };
18236
+ }
18237
+ /**
18238
+ * Creates a local video and audio track at the same time. When acquiring both
18239
+ * audio and video tracks together, it'll display a single permission prompt to
18240
+ * the user instead of two separate ones.
18241
+ * @param options
18242
+ */
18243
+ function createLocalTracks(options) {
18244
+ return __awaiter(this, void 0, void 0, function* () {
18245
+ var _a, _b;
18246
+ // set default options to true
18247
+ options !== null && options !== void 0 ? options : options = {};
18248
+ (_a = options.audio) !== null && _a !== void 0 ? _a : options.audio = true;
18249
+ (_b = options.video) !== null && _b !== void 0 ? _b : options.video = true;
18250
+ const {
18251
+ audioProcessor,
18252
+ videoProcessor
18253
+ } = extractProcessorsFromOptions(options);
18254
+ const opts = mergeDefaultOptions(options, audioDefaults, videoDefaults);
18255
+ const constraints = constraintsForOptions(opts);
18256
+ // Keep a reference to the promise on DeviceManager and await it in getLocalDevices()
18257
+ // works around iOS Safari Bug https://bugs.webkit.org/show_bug.cgi?id=179363
18258
+ const mediaPromise = navigator.mediaDevices.getUserMedia(constraints);
18259
+ if (options.audio) {
18260
+ DeviceManager.userMediaPromiseMap.set('audioinput', mediaPromise);
18261
+ mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('audioinput'));
18262
+ }
18263
+ if (options.video) {
18264
+ DeviceManager.userMediaPromiseMap.set('videoinput', mediaPromise);
18265
+ mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('videoinput'));
18266
+ }
18267
+ const stream = yield mediaPromise;
18268
+ return Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
18269
+ const isAudio = mediaStreamTrack.kind === 'audio';
18270
+ isAudio ? opts.audio : opts.video;
18271
+ let trackConstraints;
18272
+ const conOrBool = isAudio ? constraints.audio : constraints.video;
18273
+ if (typeof conOrBool !== 'boolean') {
18274
+ trackConstraints = conOrBool;
18275
+ }
18276
+ // update the constraints with the device id the user gave permissions to in the permission prompt
18277
+ // otherwise each track restart (e.g. mute - unmute) will try to initialize the device again -> causing additional permission prompts
18278
+ if (trackConstraints) {
18279
+ trackConstraints.deviceId = mediaStreamTrack.getSettings().deviceId;
18280
+ } else {
18281
+ trackConstraints = {
18282
+ deviceId: mediaStreamTrack.getSettings().deviceId
18283
+ };
18284
+ }
18285
+ const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints);
18286
+ if (track.kind === Track.Kind.Video) {
18287
+ track.source = Track.Source.Camera;
18288
+ } else if (track.kind === Track.Kind.Audio) {
18289
+ track.source = Track.Source.Microphone;
18290
+ }
18291
+ track.mediaStream = stream;
18292
+ if (track instanceof LocalAudioTrack && audioProcessor) {
18293
+ yield track.setProcessor(audioProcessor);
18294
+ } else if (track instanceof LocalVideoTrack && videoProcessor) {
18295
+ yield track.setProcessor(videoProcessor);
18296
+ }
18297
+ return track;
18298
+ })));
18299
+ });
18300
+ }
18301
+ /**
18302
+ * Creates a [[LocalVideoTrack]] with getUserMedia()
18303
+ * @param options
18304
+ */
18305
+ function createLocalVideoTrack(options) {
18306
+ return __awaiter(this, void 0, void 0, function* () {
18307
+ const tracks = yield createLocalTracks({
18308
+ audio: false,
18309
+ video: options
18310
+ });
18311
+ return tracks[0];
18312
+ });
18313
+ }
18314
+ function createLocalAudioTrack(options) {
18315
+ return __awaiter(this, void 0, void 0, function* () {
18316
+ const tracks = yield createLocalTracks({
18317
+ audio: options,
18318
+ video: false
18319
+ });
18320
+ return tracks[0];
18321
+ });
18322
+ }
18323
+ /**
18324
+ * Creates a screen capture tracks with getDisplayMedia().
18325
+ * A LocalVideoTrack is always created and returned.
18326
+ * If { audio: true }, and the browser supports audio capture, a LocalAudioTrack is also created.
18327
+ */
18328
+ function createLocalScreenTracks(options) {
18329
+ return __awaiter(this, void 0, void 0, function* () {
18330
+ if (options === undefined) {
18331
+ options = {};
18332
+ }
18333
+ if (options.resolution === undefined && !isSafari17()) {
18334
+ options.resolution = ScreenSharePresets.h1080fps30.resolution;
18335
+ }
18336
+ if (navigator.mediaDevices.getDisplayMedia === undefined) {
18337
+ throw new DeviceUnsupportedError('getDisplayMedia not supported');
18338
+ }
18339
+ const constraints = screenCaptureToDisplayMediaStreamOptions(options);
18340
+ const stream = yield navigator.mediaDevices.getDisplayMedia(constraints);
18341
+ const tracks = stream.getVideoTracks();
18342
+ if (tracks.length === 0) {
18343
+ throw new TrackInvalidError('no video track found');
18344
+ }
18345
+ const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
18346
+ screenVideo.source = Track.Source.ScreenShare;
18347
+ const localTracks = [screenVideo];
18348
+ if (stream.getAudioTracks().length > 0) {
18349
+ const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
18350
+ screenAudio.source = Track.Source.ScreenShareAudio;
18351
+ localTracks.push(screenAudio);
18352
+ }
18353
+ return localTracks;
18354
+ });
18355
+ }
18356
+
18212
18357
  var ConnectionQuality;
18213
18358
  (function (ConnectionQuality) {
18214
18359
  ConnectionQuality["Excellent"] = "excellent";
@@ -18632,7 +18777,14 @@ class LocalParticipant extends Participant {
18632
18777
  }
18633
18778
  if (!track.isMuted) {
18634
18779
  this.log.debug('track ended, attempting to use a different device', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
18635
- yield track.restartTrack();
18780
+ if (track instanceof LocalAudioTrack) {
18781
+ // fall back to default device if available
18782
+ yield track.restartTrack({
18783
+ deviceId: 'default'
18784
+ });
18785
+ } else {
18786
+ yield track.restartTrack();
18787
+ }
18636
18788
  }
18637
18789
  } catch (e) {
18638
18790
  this.log.warn("could not restart track, muting instead", Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
@@ -18921,6 +19073,11 @@ class LocalParticipant extends Participant {
18921
19073
  createTracks(options) {
18922
19074
  return __awaiter(this, void 0, void 0, function* () {
18923
19075
  var _a, _b;
19076
+ options !== null && options !== void 0 ? options : options = {};
19077
+ const {
19078
+ audioProcessor,
19079
+ videoProcessor
19080
+ } = extractProcessorsFromOptions(options);
18924
19081
  const mergedOptions = mergeDefaultOptions(options, (_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.audioCaptureDefaults, (_b = this.roomOptions) === null || _b === void 0 ? void 0 : _b.videoCaptureDefaults);
18925
19082
  const constraints = constraintsForOptions(mergedOptions);
18926
19083
  let stream;
@@ -18946,10 +19103,7 @@ class LocalParticipant extends Participant {
18946
19103
  }
18947
19104
  return Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
18948
19105
  const isAudio = mediaStreamTrack.kind === 'audio';
18949
- let trackOptions = isAudio ? mergedOptions.audio : mergedOptions.video;
18950
- if (typeof trackOptions === 'boolean' || !trackOptions) {
18951
- trackOptions = {};
18952
- }
19106
+ isAudio ? mergedOptions.audio : mergedOptions.video;
18953
19107
  let trackConstraints;
18954
19108
  const conOrBool = isAudio ? constraints.audio : constraints.video;
18955
19109
  if (typeof conOrBool !== 'boolean') {
@@ -18966,12 +19120,10 @@ class LocalParticipant extends Participant {
18966
19120
  track.setAudioContext(this.audioContext);
18967
19121
  }
18968
19122
  track.mediaStream = stream;
18969
- if (trackOptions.processor) {
18970
- if (track instanceof LocalAudioTrack) {
18971
- yield track.setProcessor(trackOptions.processor);
18972
- } else {
18973
- yield track.setProcessor(trackOptions.processor);
18974
- }
19123
+ if (track instanceof LocalAudioTrack && audioProcessor) {
19124
+ yield track.setProcessor(audioProcessor);
19125
+ } else if (track instanceof LocalVideoTrack && videoProcessor) {
19126
+ yield track.setProcessor(videoProcessor);
18975
19127
  }
18976
19128
  return track;
18977
19129
  })));
@@ -20776,6 +20928,16 @@ class Room extends eventsExports.EventEmitter {
20776
20928
  }
20777
20929
  };
20778
20930
  this.handleDeviceChange = () => __awaiter(this, void 0, void 0, function* () {
20931
+ const availableDevices = yield DeviceManager.getInstance().getDevices();
20932
+ // inputs are automatically handled via TrackEvent.Ended causing a TrackEvent.Restarted. Here we only need to worry about audiooutputs changing
20933
+ const kinds = ['audiooutput'];
20934
+ for (let kind of kinds) {
20935
+ // switch to first available device if previously active device is not available any more
20936
+ const devicesOfKind = availableDevices.filter(d => d.kind === kind);
20937
+ if (devicesOfKind.length > 0 && !devicesOfKind.find(deviceInfo => deviceInfo.deviceId === this.getActiveDevice(kind))) {
20938
+ yield this.switchActiveDevice(kind, devicesOfKind[0].deviceId);
20939
+ }
20940
+ }
20779
20941
  this.emit(RoomEvent.MediaDevicesChanged);
20780
20942
  });
20781
20943
  this.handleRoomUpdate = room => {
@@ -20820,9 +20982,10 @@ class Room extends eventsExports.EventEmitter {
20820
20982
  (_a = processor === null || processor === void 0 ? void 0 : processor.onPublish) === null || _a === void 0 ? void 0 : _a.call(processor, this);
20821
20983
  };
20822
20984
  this.onLocalTrackPublished = pub => __awaiter(this, void 0, void 0, function* () {
20823
- var _a, _b, _c, _d, _e;
20985
+ var _a, _b, _c, _d, _e, _f;
20824
20986
  (_a = pub.track) === null || _a === void 0 ? void 0 : _a.on(TrackEvent.TrackProcessorUpdate, this.onTrackProcessorUpdate);
20825
- (_d = (_c = (_b = pub.track) === null || _b === void 0 ? void 0 : _b.getProcessor()) === null || _c === void 0 ? void 0 : _c.onPublish) === null || _d === void 0 ? void 0 : _d.call(_c, this);
20987
+ (_b = pub.track) === null || _b === void 0 ? void 0 : _b.on(TrackEvent.Restarted, this.onLocalTrackRestarted);
20988
+ (_e = (_d = (_c = pub.track) === null || _c === void 0 ? void 0 : _c.getProcessor()) === null || _d === void 0 ? void 0 : _d.onPublish) === null || _e === void 0 ? void 0 : _e.call(_d, this);
20826
20989
  this.emit(RoomEvent.LocalTrackPublished, pub, this.localParticipant);
20827
20990
  if (pub.track instanceof LocalAudioTrack) {
20828
20991
  const trackIsSilent = yield pub.track.checkForSilence();
@@ -20830,7 +20993,7 @@ class Room extends eventsExports.EventEmitter {
20830
20993
  this.emit(RoomEvent.LocalAudioSilenceDetected, pub);
20831
20994
  }
20832
20995
  }
20833
- const deviceId = yield (_e = pub.track) === null || _e === void 0 ? void 0 : _e.getDeviceId();
20996
+ const deviceId = yield (_f = pub.track) === null || _f === void 0 ? void 0 : _f.getDeviceId();
20834
20997
  const deviceKind = sourceToKind(pub.source);
20835
20998
  if (deviceKind && deviceId && deviceId !== this.localParticipant.activeDeviceMap.get(deviceKind)) {
20836
20999
  this.localParticipant.activeDeviceMap.set(deviceKind, deviceId);
@@ -20838,10 +21001,20 @@ class Room extends eventsExports.EventEmitter {
20838
21001
  }
20839
21002
  });
20840
21003
  this.onLocalTrackUnpublished = pub => {
20841
- var _a;
21004
+ var _a, _b;
20842
21005
  (_a = pub.track) === null || _a === void 0 ? void 0 : _a.off(TrackEvent.TrackProcessorUpdate, this.onTrackProcessorUpdate);
21006
+ (_b = pub.track) === null || _b === void 0 ? void 0 : _b.off(TrackEvent.Restarted, this.onLocalTrackRestarted);
20843
21007
  this.emit(RoomEvent.LocalTrackUnpublished, pub, this.localParticipant);
20844
21008
  };
21009
+ this.onLocalTrackRestarted = track => __awaiter(this, void 0, void 0, function* () {
21010
+ const deviceId = yield track.getDeviceId(false);
21011
+ const deviceKind = sourceToKind(track.source);
21012
+ if (deviceKind && deviceId && deviceId !== this.localParticipant.activeDeviceMap.get(deviceKind)) {
21013
+ this.log.debug("local track restarted, setting ".concat(deviceKind, " ").concat(deviceId, " active"), this.logContext);
21014
+ this.localParticipant.activeDeviceMap.set(deviceKind, deviceId);
21015
+ this.emit(RoomEvent.ActiveDeviceChanged, deviceKind, deviceId);
21016
+ }
21017
+ });
20845
21018
  this.onLocalConnectionQualityChanged = quality => {
20846
21019
  this.emit(RoomEvent.ConnectionQualityChanged, quality, this.localParticipant);
20847
21020
  };
@@ -21025,9 +21198,8 @@ class Room extends eventsExports.EventEmitter {
21025
21198
  }
21026
21199
  /**
21027
21200
  * getLocalDevices abstracts navigator.mediaDevices.enumerateDevices.
21028
- * In particular, it handles Chrome's unique behavior of creating `default`
21029
- * devices. When encountered, it'll be removed from the list of devices.
21030
- * The actual default device will be placed at top.
21201
+ * In particular, it requests device permissions by default if needed
21202
+ * and makes sure the returned device does not consist of dummy devices
21031
21203
  * @param kind
21032
21204
  * @returns a list of available local devices
21033
21205
  */
@@ -21240,15 +21412,15 @@ class Room extends eventsExports.EventEmitter {
21240
21412
  var _this3 = this;
21241
21413
  let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
21242
21414
  return function* () {
21243
- var _a, _b, _c;
21244
- var _d;
21415
+ var _a, _b, _c, _d, _e, _f;
21416
+ var _g;
21245
21417
  let deviceHasChanged = false;
21246
21418
  let success = true;
21247
21419
  const deviceConstraint = exact ? {
21248
21420
  exact: deviceId
21249
21421
  } : deviceId;
21250
21422
  if (kind === 'audioinput') {
21251
- const prevDeviceId = _this3.options.audioCaptureDefaults.deviceId;
21423
+ const prevDeviceId = (_a = _this3.getActiveDevice(kind)) !== null && _a !== void 0 ? _a : _this3.options.audioCaptureDefaults.deviceId;
21252
21424
  _this3.options.audioCaptureDefaults.deviceId = deviceConstraint;
21253
21425
  deviceHasChanged = prevDeviceId !== deviceConstraint;
21254
21426
  const tracks = Array.from(_this3.localParticipant.audioTrackPublications.values()).filter(track => track.source === Track.Source.Microphone);
@@ -21262,7 +21434,7 @@ class Room extends eventsExports.EventEmitter {
21262
21434
  throw e;
21263
21435
  }
21264
21436
  } else if (kind === 'videoinput') {
21265
- const prevDeviceId = _this3.options.videoCaptureDefaults.deviceId;
21437
+ const prevDeviceId = (_b = _this3.getActiveDevice(kind)) !== null && _b !== void 0 ? _b : _this3.options.videoCaptureDefaults.deviceId;
21266
21438
  _this3.options.videoCaptureDefaults.deviceId = deviceConstraint;
21267
21439
  deviceHasChanged = prevDeviceId !== deviceConstraint;
21268
21440
  const tracks = Array.from(_this3.localParticipant.videoTrackPublications.values()).filter(track => track.source === Track.Source.Camera);
@@ -21281,16 +21453,16 @@ class Room extends eventsExports.EventEmitter {
21281
21453
  }
21282
21454
  if (_this3.options.webAudioMix) {
21283
21455
  // setting `default` for web audio output doesn't work, so we need to normalize the id before
21284
- deviceId = (_a = yield DeviceManager.getInstance().normalizeDeviceId('audiooutput', deviceId)) !== null && _a !== void 0 ? _a : '';
21456
+ deviceId = (_c = yield DeviceManager.getInstance().normalizeDeviceId('audiooutput', deviceId)) !== null && _c !== void 0 ? _c : '';
21285
21457
  }
21286
- (_b = (_d = _this3.options).audioOutput) !== null && _b !== void 0 ? _b : _d.audioOutput = {};
21287
- const prevDeviceId = _this3.options.audioOutput.deviceId;
21458
+ (_d = (_g = _this3.options).audioOutput) !== null && _d !== void 0 ? _d : _g.audioOutput = {};
21459
+ const prevDeviceId = (_e = _this3.getActiveDevice(kind)) !== null && _e !== void 0 ? _e : _this3.options.audioOutput.deviceId;
21288
21460
  _this3.options.audioOutput.deviceId = deviceId;
21289
21461
  deviceHasChanged = prevDeviceId !== deviceConstraint;
21290
21462
  try {
21291
21463
  if (_this3.options.webAudioMix) {
21292
21464
  // @ts-expect-error setSinkId is not yet in the typescript type of AudioContext
21293
- (_c = _this3.audioContext) === null || _c === void 0 ? void 0 : _c.setSinkId(deviceId);
21465
+ (_f = _this3.audioContext) === null || _f === void 0 ? void 0 : _f.setSinkId(deviceId);
21294
21466
  }
21295
21467
  // also set audio output on all audio elements, even if webAudioMix is enabled in order to workaround echo cancellation not working on chrome with non-default output devices
21296
21468
  // see https://issues.chromium.org/issues/40252911#comment7
@@ -21851,7 +22023,7 @@ class Checker extends eventsExports.EventEmitter {
21851
22023
  if (this.room.state === ConnectionState.Connected) {
21852
22024
  return this.room;
21853
22025
  }
21854
- yield this.room.connect(this.url, this.token);
22026
+ yield this.room.connect(this.url, this.token, this.connectOptions);
21855
22027
  return this.room;
21856
22028
  });
21857
22029
  }
@@ -21906,127 +22078,6 @@ class Checker extends eventsExports.EventEmitter {
21906
22078
  }
21907
22079
  }
21908
22080
 
21909
- /**
21910
- * Creates a local video and audio track at the same time. When acquiring both
21911
- * audio and video tracks together, it'll display a single permission prompt to
21912
- * the user instead of two separate ones.
21913
- * @param options
21914
- */
21915
- function createLocalTracks(options) {
21916
- return __awaiter(this, void 0, void 0, function* () {
21917
- var _a, _b;
21918
- // set default options to true
21919
- options !== null && options !== void 0 ? options : options = {};
21920
- (_a = options.audio) !== null && _a !== void 0 ? _a : options.audio = true;
21921
- (_b = options.video) !== null && _b !== void 0 ? _b : options.video = true;
21922
- const opts = mergeDefaultOptions(options, audioDefaults, videoDefaults);
21923
- const constraints = constraintsForOptions(opts);
21924
- // Keep a reference to the promise on DeviceManager and await it in getLocalDevices()
21925
- // works around iOS Safari Bug https://bugs.webkit.org/show_bug.cgi?id=179363
21926
- const mediaPromise = navigator.mediaDevices.getUserMedia(constraints);
21927
- if (options.audio) {
21928
- DeviceManager.userMediaPromiseMap.set('audioinput', mediaPromise);
21929
- mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('audioinput'));
21930
- }
21931
- if (options.video) {
21932
- DeviceManager.userMediaPromiseMap.set('videoinput', mediaPromise);
21933
- mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('videoinput'));
21934
- }
21935
- const stream = yield mediaPromise;
21936
- return Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
21937
- const isAudio = mediaStreamTrack.kind === 'audio';
21938
- let trackOptions = isAudio ? options.audio : options.video;
21939
- if (typeof trackOptions === 'boolean' || !trackOptions) {
21940
- trackOptions = {};
21941
- }
21942
- let trackConstraints;
21943
- const conOrBool = isAudio ? constraints.audio : constraints.video;
21944
- if (typeof conOrBool !== 'boolean') {
21945
- trackConstraints = conOrBool;
21946
- }
21947
- // update the constraints with the device id the user gave permissions to in the permission prompt
21948
- // otherwise each track restart (e.g. mute - unmute) will try to initialize the device again -> causing additional permission prompts
21949
- if (trackConstraints) {
21950
- trackConstraints.deviceId = mediaStreamTrack.getSettings().deviceId;
21951
- } else {
21952
- trackConstraints = {
21953
- deviceId: mediaStreamTrack.getSettings().deviceId
21954
- };
21955
- }
21956
- const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints);
21957
- if (track.kind === Track.Kind.Video) {
21958
- track.source = Track.Source.Camera;
21959
- } else if (track.kind === Track.Kind.Audio) {
21960
- track.source = Track.Source.Microphone;
21961
- }
21962
- track.mediaStream = stream;
21963
- if (trackOptions.processor) {
21964
- if (track instanceof LocalAudioTrack) {
21965
- yield track.setProcessor(trackOptions.processor);
21966
- } else if (track instanceof LocalVideoTrack) {
21967
- yield track.setProcessor(trackOptions.processor);
21968
- }
21969
- }
21970
- return track;
21971
- })));
21972
- });
21973
- }
21974
- /**
21975
- * Creates a [[LocalVideoTrack]] with getUserMedia()
21976
- * @param options
21977
- */
21978
- function createLocalVideoTrack(options) {
21979
- return __awaiter(this, void 0, void 0, function* () {
21980
- const tracks = yield createLocalTracks({
21981
- audio: false,
21982
- video: options
21983
- });
21984
- return tracks[0];
21985
- });
21986
- }
21987
- function createLocalAudioTrack(options) {
21988
- return __awaiter(this, void 0, void 0, function* () {
21989
- const tracks = yield createLocalTracks({
21990
- audio: options,
21991
- video: false
21992
- });
21993
- return tracks[0];
21994
- });
21995
- }
21996
- /**
21997
- * Creates a screen capture tracks with getDisplayMedia().
21998
- * A LocalVideoTrack is always created and returned.
21999
- * If { audio: true }, and the browser supports audio capture, a LocalAudioTrack is also created.
22000
- */
22001
- function createLocalScreenTracks(options) {
22002
- return __awaiter(this, void 0, void 0, function* () {
22003
- if (options === undefined) {
22004
- options = {};
22005
- }
22006
- if (options.resolution === undefined && !isSafari17()) {
22007
- options.resolution = ScreenSharePresets.h1080fps30.resolution;
22008
- }
22009
- if (navigator.mediaDevices.getDisplayMedia === undefined) {
22010
- throw new DeviceUnsupportedError('getDisplayMedia not supported');
22011
- }
22012
- const constraints = screenCaptureToDisplayMediaStreamOptions(options);
22013
- const stream = yield navigator.mediaDevices.getDisplayMedia(constraints);
22014
- const tracks = stream.getVideoTracks();
22015
- if (tracks.length === 0) {
22016
- throw new TrackInvalidError('no video track found');
22017
- }
22018
- const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
22019
- screenVideo.source = Track.Source.ScreenShare;
22020
- const localTracks = [screenVideo];
22021
- if (stream.getAudioTracks().length > 0) {
22022
- const screenAudio = new LocalAudioTrack(stream.getAudioTracks()[0], undefined, false);
22023
- screenAudio.source = Track.Source.ScreenShareAudio;
22024
- localTracks.push(screenAudio);
22025
- }
22026
- return localTracks;
22027
- });
22028
- }
22029
-
22030
22081
  class PublishAudioCheck extends Checker {
22031
22082
  get description() {
22032
22083
  return 'Can publish audio';
@@ -22435,5 +22486,5 @@ function isFacingModeValue(item) {
22435
22486
  return item === undefined || allowedValues.includes(item);
22436
22487
  }
22437
22488
 
22438
- export { AudioPresets, BaseKeyProvider, CheckStatus, Checker, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorError, CryptorErrorReason, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, Mutex, NegotiationError, Participant, ParticipantEvent, ParticipantInfo_Kind as ParticipantKind, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, ScreenSharePresets, SignalRequestError, SubscriptionError, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getBrowser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, importKey, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isScriptTransformSupported, isVideoFrame, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
22489
+ export { AudioPresets, BaseKeyProvider, CheckStatus, Checker, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorError, CryptorErrorReason, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, Mutex, NegotiationError, Participant, ParticipantEvent, ParticipantInfo_Kind as ParticipantKind, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, ScreenSharePresets, SignalRequestError, SubscriptionError, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, extractProcessorsFromOptions, facingModeFromDeviceLabel, facingModeFromLocalTrack, getBrowser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, importKey, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isScriptTransformSupported, isVideoFrame, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
22439
22490
  //# sourceMappingURL=livekit-client.esm.mjs.map