livekit-client 2.10.0 → 2.11.0

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.
@@ -11027,6 +11027,7 @@ var EngineEvent;
11027
11027
  EngineEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
11028
11028
  EngineEvent["Offline"] = "offline";
11029
11029
  EngineEvent["SignalRequestResponse"] = "signalRequestResponse";
11030
+ EngineEvent["SignalConnected"] = "signalConnected";
11030
11031
  })(EngineEvent || (EngineEvent = {}));
11031
11032
  var TrackEvent;
11032
11033
  (function (TrackEvent) {
@@ -11185,7 +11186,7 @@ function getOSVersion(ua) {
11185
11186
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
11186
11187
  }
11187
11188
 
11188
- var version$1 = "2.10.0";
11189
+ var version$1 = "2.11.0";
11189
11190
 
11190
11191
  const version = version$1;
11191
11192
  const protocolVersion = 15;
@@ -12201,14 +12202,18 @@ function mergeDefaultOptions(options, audioDefaults, videoDefaults) {
12201
12202
  // use defaults
12202
12203
  if (clonedOptions.audio) {
12203
12204
  mergeObjectWithoutOverwriting(clonedOptions.audio, audioDefaults);
12204
- (_b = (_d = clonedOptions.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = 'default';
12205
+ (_b = (_d = clonedOptions.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
12206
+ ideal: 'default'
12207
+ };
12205
12208
  if (audioProcessor || defaultAudioProcessor) {
12206
12209
  clonedOptions.audio.processor = audioProcessor !== null && audioProcessor !== void 0 ? audioProcessor : defaultAudioProcessor;
12207
12210
  }
12208
12211
  }
12209
12212
  if (clonedOptions.video) {
12210
12213
  mergeObjectWithoutOverwriting(clonedOptions.video, videoDefaults);
12211
- (_c = (_e = clonedOptions.video).deviceId) !== null && _c !== void 0 ? _c : _e.deviceId = 'default';
12214
+ (_c = (_e = clonedOptions.video).deviceId) !== null && _c !== void 0 ? _c : _e.deviceId = {
12215
+ ideal: 'default'
12216
+ };
12212
12217
  if (videoProcessor || defaultVideoProcessor) {
12213
12218
  clonedOptions.video.processor = videoProcessor !== null && videoProcessor !== void 0 ? videoProcessor : defaultVideoProcessor;
12214
12219
  }
@@ -12242,10 +12247,14 @@ function constraintsForOptions(options) {
12242
12247
  }
12243
12248
  });
12244
12249
  constraints.video = videoOptions;
12245
- (_a = (_c = constraints.video).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId = 'default';
12250
+ (_a = (_c = constraints.video).deviceId) !== null && _a !== void 0 ? _a : _c.deviceId = {
12251
+ ideal: 'default'
12252
+ };
12246
12253
  } else {
12247
12254
  constraints.video = options.video ? {
12248
- deviceId: 'default'
12255
+ deviceId: {
12256
+ ideal: 'default'
12257
+ }
12249
12258
  } : false;
12250
12259
  }
12251
12260
  } else {
@@ -12254,10 +12263,14 @@ function constraintsForOptions(options) {
12254
12263
  if (options.audio) {
12255
12264
  if (typeof options.audio === 'object') {
12256
12265
  constraints.audio = options.audio;
12257
- (_b = (_d = constraints.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = 'default';
12266
+ (_b = (_d = constraints.audio).deviceId) !== null && _b !== void 0 ? _b : _d.deviceId = {
12267
+ ideal: 'default'
12268
+ };
12258
12269
  } else {
12259
12270
  constraints.audio = {
12260
- deviceId: 'default'
12271
+ deviceId: {
12272
+ ideal: 'default'
12273
+ }
12261
12274
  };
12262
12275
  }
12263
12276
  } else {
@@ -12862,7 +12875,9 @@ class DeviceManager {
12862
12875
  const permissionsToAcquire = {
12863
12876
  video: kind !== 'audioinput' && kind !== 'audiooutput',
12864
12877
  audio: kind !== 'videoinput' && {
12865
- deviceId: 'default'
12878
+ deviceId: {
12879
+ ideal: 'default'
12880
+ }
12866
12881
  }
12867
12882
  };
12868
12883
  const stream = yield navigator.mediaDevices.getUserMedia(permissionsToAcquire);
@@ -12961,15 +12976,12 @@ function createValidateUrl(rtcWsUrl) {
12961
12976
  const urlObj = new URL(toHttpUrl(rtcWsUrl));
12962
12977
  return appendUrlPath(urlObj, 'validate');
12963
12978
  }
12964
- function ensureTrailingSlash(url) {
12965
- return url.endsWith('/') ? url : "".concat(url, "/");
12979
+ function ensureTrailingSlash(path) {
12980
+ return path.endsWith('/') ? path : "".concat(path, "/");
12966
12981
  }
12967
12982
  function appendUrlPath(urlObj, path) {
12968
- const result = "".concat(urlObj.protocol, "//").concat(urlObj.host).concat(ensureTrailingSlash(urlObj.pathname)).concat(path);
12969
- if (urlObj.searchParams.size > 0) {
12970
- return "".concat(result, "?").concat(urlObj.searchParams.toString());
12971
- }
12972
- return result;
12983
+ urlObj.pathname = "".concat(ensureTrailingSlash(urlObj.pathname)).concat(path);
12984
+ return urlObj.toString();
12973
12985
  }
12974
12986
 
12975
12987
  const passThroughQueueSignals = ['syncState', 'trickle', 'offer', 'answer', 'simulate', 'leave'];
@@ -14959,14 +14971,18 @@ const publishDefaults = {
14959
14971
  backupCodec: true
14960
14972
  };
14961
14973
  const audioDefaults = {
14962
- deviceId: 'default',
14974
+ deviceId: {
14975
+ ideal: 'default'
14976
+ },
14963
14977
  autoGainControl: true,
14964
14978
  echoCancellation: true,
14965
14979
  noiseSuppression: true,
14966
14980
  voiceIsolation: true
14967
14981
  };
14968
14982
  const videoDefaults = {
14969
- deviceId: 'default',
14983
+ deviceId: {
14984
+ ideal: 'default'
14985
+ },
14970
14986
  resolution: VideoPresets.h720.resolution
14971
14987
  };
14972
14988
  const roomOptionDefaults = {
@@ -17360,6 +17376,10 @@ class RTCEngine extends eventsExports.EventEmitter {
17360
17376
  this.negotiate();
17361
17377
  }
17362
17378
  this.clientConfiguration = joinResponse.clientConfiguration;
17379
+ // emit signal connected event after a short delay to allow for join response to be processed on room
17380
+ setTimeout(() => {
17381
+ this.emit(EngineEvent.SignalConnected);
17382
+ }, 10);
17363
17383
  return joinResponse;
17364
17384
  } catch (e) {
17365
17385
  if (e instanceof ConnectionError) {
@@ -18553,6 +18573,7 @@ class BaseStreamWriter {
18553
18573
  }
18554
18574
  }
18555
18575
  class TextStreamWriter extends BaseStreamWriter {}
18576
+ class ByteStreamWriter extends BaseStreamWriter {}
18556
18577
 
18557
18578
  class RemoteTrack extends Track {
18558
18579
  constructor(mediaTrack, sid, kind, receiver, loggerOptions) {
@@ -20393,7 +20414,41 @@ class LocalParticipant extends Participant {
20393
20414
  if (opts.source) {
20394
20415
  track.source = opts.source;
20395
20416
  }
20396
- const publishPromise = _this2.publish(track, opts, isStereo);
20417
+ const publishPromise = new Promise((resolve, reject) => __awaiter(_this2, void 0, void 0, function* () {
20418
+ try {
20419
+ if (this.engine.client.currentState !== SignalConnectionState.CONNECTED) {
20420
+ this.log.debug('deferring track publication until signal is connected', Object.assign(Object.assign({}, this.logContext), {
20421
+ track: getLogContextFromTrack(track)
20422
+ }));
20423
+ const onSignalConnected = () => __awaiter(this, void 0, void 0, function* () {
20424
+ try {
20425
+ const publication = yield this.publish(track, opts, isStereo);
20426
+ resolve(publication);
20427
+ } catch (e) {
20428
+ reject(e);
20429
+ }
20430
+ });
20431
+ setTimeout(() => {
20432
+ this.engine.off(EngineEvent.SignalConnected, onSignalConnected);
20433
+ reject(new PublishTrackError('publishing rejected as engine not connected within timeout', 408));
20434
+ }, 15000);
20435
+ this.engine.once(EngineEvent.SignalConnected, onSignalConnected);
20436
+ this.engine.on(EngineEvent.Closing, () => {
20437
+ this.engine.off(EngineEvent.SignalConnected, onSignalConnected);
20438
+ reject(new PublishTrackError('publishing rejected as engine closed', 499));
20439
+ });
20440
+ } else {
20441
+ try {
20442
+ const publication = yield this.publish(track, opts, isStereo);
20443
+ resolve(publication);
20444
+ } catch (e) {
20445
+ reject(e);
20446
+ }
20447
+ }
20448
+ } catch (e) {
20449
+ reject(e);
20450
+ }
20451
+ }));
20397
20452
  _this2.pendingPublishPromises.set(track, publishPromise);
20398
20453
  try {
20399
20454
  const publication = yield publishPromise;
@@ -21090,23 +21145,57 @@ class LocalParticipant extends Participant {
21090
21145
  }
21091
21146
  _sendFile(streamId, file, options) {
21092
21147
  return __awaiter(this, void 0, void 0, function* () {
21093
- var _a, _b;
21094
- const totalLength = file.size;
21095
- const header = new DataStream_Header({
21096
- totalLength: numberToBigInt(totalLength),
21097
- mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
21148
+ var _a;
21149
+ const writer = yield this.streamBytes({
21098
21150
  streamId,
21151
+ totalSize: file.size,
21152
+ name: file.name,
21153
+ mimeType: (_a = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _a !== void 0 ? _a : file.type,
21099
21154
  topic: options === null || options === void 0 ? void 0 : options.topic,
21100
- encryptionType: options === null || options === void 0 ? void 0 : options.encryptionType,
21155
+ destinationIdentities: options === null || options === void 0 ? void 0 : options.destinationIdentities
21156
+ });
21157
+ const reader = file.stream().getReader();
21158
+ while (true) {
21159
+ const {
21160
+ done,
21161
+ value
21162
+ } = yield reader.read();
21163
+ if (done) {
21164
+ break;
21165
+ }
21166
+ yield writer.write(value);
21167
+ }
21168
+ yield writer.close();
21169
+ return writer.info;
21170
+ });
21171
+ }
21172
+ streamBytes(options) {
21173
+ return __awaiter(this, void 0, void 0, function* () {
21174
+ var _a, _b, _c, _d, _e;
21175
+ const streamId = (_a = options === null || options === void 0 ? void 0 : options.streamId) !== null && _a !== void 0 ? _a : crypto.randomUUID();
21176
+ const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
21177
+ const info = {
21178
+ id: streamId,
21179
+ mimeType: (_b = options === null || options === void 0 ? void 0 : options.mimeType) !== null && _b !== void 0 ? _b : 'application/octet-stream',
21180
+ topic: (_c = options === null || options === void 0 ? void 0 : options.topic) !== null && _c !== void 0 ? _c : '',
21181
+ timestamp: Date.now(),
21182
+ attributes: options === null || options === void 0 ? void 0 : options.attributes,
21183
+ size: options === null || options === void 0 ? void 0 : options.totalSize,
21184
+ name: (_d = options === null || options === void 0 ? void 0 : options.name) !== null && _d !== void 0 ? _d : 'unknown'
21185
+ };
21186
+ const header = new DataStream_Header({
21187
+ totalLength: numberToBigInt((_e = info.size) !== null && _e !== void 0 ? _e : 0),
21188
+ mimeType: info.mimeType,
21189
+ streamId,
21190
+ topic: info.topic,
21101
21191
  timestamp: numberToBigInt(Date.now()),
21102
21192
  contentHeader: {
21103
21193
  case: 'byteHeader',
21104
21194
  value: new DataStream_ByteHeader({
21105
- name: file.name
21195
+ name: info.name
21106
21196
  })
21107
21197
  }
21108
21198
  });
21109
- const destinationIdentities = options === null || options === void 0 ? void 0 : options.destinationIdentities;
21110
21199
  const packet = new DataPacket({
21111
21200
  destinationIdentities,
21112
21201
  value: {
@@ -21115,45 +21204,60 @@ class LocalParticipant extends Participant {
21115
21204
  }
21116
21205
  });
21117
21206
  yield this.engine.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
21118
- function read(b) {
21119
- return new Promise(resolve => {
21120
- const fr = new FileReader();
21121
- fr.onload = () => {
21122
- resolve(new Uint8Array(fr.result));
21123
- };
21124
- fr.readAsArrayBuffer(b);
21125
- });
21126
- }
21127
- const totalChunks = Math.ceil(totalLength / STREAM_CHUNK_SIZE);
21128
- for (let i = 0; i < totalChunks; i++) {
21129
- const chunkData = yield read(file.slice(i * STREAM_CHUNK_SIZE, Math.min((i + 1) * STREAM_CHUNK_SIZE, totalLength)));
21130
- yield this.engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
21131
- const chunk = new DataStream_Chunk({
21132
- content: chunkData,
21133
- streamId,
21134
- chunkIndex: numberToBigInt(i)
21135
- });
21136
- const chunkPacket = new DataPacket({
21137
- destinationIdentities,
21138
- value: {
21139
- case: 'streamChunk',
21140
- value: chunk
21141
- }
21142
- });
21143
- yield this.engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
21144
- (_b = options === null || options === void 0 ? void 0 : options.onProgress) === null || _b === void 0 ? void 0 : _b.call(options, (i + 1) / totalChunks);
21145
- }
21146
- const trailer = new DataStream_Trailer({
21147
- streamId
21148
- });
21149
- const trailerPacket = new DataPacket({
21150
- destinationIdentities,
21151
- value: {
21152
- case: 'streamTrailer',
21153
- value: trailer
21207
+ let chunkId = 0;
21208
+ const writeMutex = new _();
21209
+ const engine = this.engine;
21210
+ const log = this.log;
21211
+ const writableStream = new WritableStream({
21212
+ write(chunk) {
21213
+ return __awaiter(this, void 0, void 0, function* () {
21214
+ const unlock = yield writeMutex.lock();
21215
+ let byteOffset = 0;
21216
+ try {
21217
+ while (byteOffset < chunk.byteLength) {
21218
+ const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);
21219
+ yield engine.waitForBufferStatusLow(DataPacket_Kind.RELIABLE);
21220
+ const chunkPacket = new DataPacket({
21221
+ destinationIdentities,
21222
+ value: {
21223
+ case: 'streamChunk',
21224
+ value: new DataStream_Chunk({
21225
+ content: subChunk,
21226
+ streamId,
21227
+ chunkIndex: numberToBigInt(chunkId)
21228
+ })
21229
+ }
21230
+ });
21231
+ yield engine.sendDataPacket(chunkPacket, DataPacket_Kind.RELIABLE);
21232
+ chunkId += 1;
21233
+ byteOffset += subChunk.byteLength;
21234
+ }
21235
+ } finally {
21236
+ unlock();
21237
+ }
21238
+ });
21239
+ },
21240
+ close() {
21241
+ return __awaiter(this, void 0, void 0, function* () {
21242
+ const trailer = new DataStream_Trailer({
21243
+ streamId
21244
+ });
21245
+ const trailerPacket = new DataPacket({
21246
+ destinationIdentities,
21247
+ value: {
21248
+ case: 'streamTrailer',
21249
+ value: trailer
21250
+ }
21251
+ });
21252
+ yield engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
21253
+ });
21254
+ },
21255
+ abort(err) {
21256
+ log.error('Sink error:', err);
21154
21257
  }
21155
21258
  });
21156
- yield this.engine.sendDataPacket(trailerPacket, DataPacket_Kind.RELIABLE);
21259
+ const byteWriter = new ByteStreamWriter(writableStream, info);
21260
+ return byteWriter;
21157
21261
  });
21158
21262
  }
21159
21263
  /**
@@ -23169,7 +23273,7 @@ class Room extends eventsExports.EventEmitter {
23169
23273
  switchActiveDevice(kind_1, deviceId_1) {
23170
23274
  return __awaiter(this, arguments, void 0, function (kind, deviceId) {
23171
23275
  var _this3 = this;
23172
- let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
23276
+ let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
23173
23277
  return function* () {
23174
23278
  var _a, _b, _c, _d, _e, _f, _g;
23175
23279
  var _h;
@@ -24172,63 +24276,104 @@ function createLocalTracks(options) {
24172
24276
  return __awaiter(this, void 0, void 0, function* () {
24173
24277
  var _a, _b;
24174
24278
  // set default options to true
24175
- options !== null && options !== void 0 ? options : options = {};
24176
- (_a = options.audio) !== null && _a !== void 0 ? _a : options.audio = {
24279
+ const internalOptions = Object.assign({}, options !== null && options !== void 0 ? options : {});
24280
+ let attemptExactMatch = false;
24281
+ let retryAudioOptions = options === null || options === void 0 ? void 0 : options.audio;
24282
+ let retryVideoOptions = options === null || options === void 0 ? void 0 : options.video;
24283
+ // if the user passes a device id as a string, we default to exact match
24284
+ if (internalOptions.audio && typeof internalOptions.audio === 'object' && typeof internalOptions.audio.deviceId === 'string') {
24285
+ const deviceId = internalOptions.audio.deviceId;
24286
+ internalOptions.audio.deviceId = {
24287
+ exact: deviceId
24288
+ };
24289
+ attemptExactMatch = true;
24290
+ retryAudioOptions = Object.assign(Object.assign({}, internalOptions.audio), {
24291
+ deviceId: {
24292
+ ideal: deviceId
24293
+ }
24294
+ });
24295
+ }
24296
+ if (internalOptions.video && typeof internalOptions.video === 'object' && typeof internalOptions.video.deviceId === 'string') {
24297
+ const deviceId = internalOptions.video.deviceId;
24298
+ internalOptions.video.deviceId = {
24299
+ exact: deviceId
24300
+ };
24301
+ attemptExactMatch = true;
24302
+ retryVideoOptions = Object.assign(Object.assign({}, internalOptions.video), {
24303
+ deviceId: {
24304
+ ideal: deviceId
24305
+ }
24306
+ });
24307
+ }
24308
+ (_a = internalOptions.audio) !== null && _a !== void 0 ? _a : internalOptions.audio = {
24177
24309
  deviceId: 'default'
24178
24310
  };
24179
- (_b = options.video) !== null && _b !== void 0 ? _b : options.video = {
24311
+ (_b = internalOptions.video) !== null && _b !== void 0 ? _b : internalOptions.video = {
24180
24312
  deviceId: 'default'
24181
24313
  };
24182
24314
  const {
24183
24315
  audioProcessor,
24184
24316
  videoProcessor
24185
- } = extractProcessorsFromOptions(options);
24186
- const opts = mergeDefaultOptions(options, audioDefaults, videoDefaults);
24317
+ } = extractProcessorsFromOptions(internalOptions);
24318
+ const opts = mergeDefaultOptions(internalOptions, audioDefaults, videoDefaults);
24187
24319
  const constraints = constraintsForOptions(opts);
24188
24320
  // Keep a reference to the promise on DeviceManager and await it in getLocalDevices()
24189
24321
  // works around iOS Safari Bug https://bugs.webkit.org/show_bug.cgi?id=179363
24190
24322
  const mediaPromise = navigator.mediaDevices.getUserMedia(constraints);
24191
- if (options.audio) {
24323
+ if (internalOptions.audio) {
24192
24324
  DeviceManager.userMediaPromiseMap.set('audioinput', mediaPromise);
24193
24325
  mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('audioinput'));
24194
24326
  }
24195
- if (options.video) {
24327
+ if (internalOptions.video) {
24196
24328
  DeviceManager.userMediaPromiseMap.set('videoinput', mediaPromise);
24197
24329
  mediaPromise.catch(() => DeviceManager.userMediaPromiseMap.delete('videoinput'));
24198
24330
  }
24199
- const stream = yield mediaPromise;
24200
- return Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
24201
- const isAudio = mediaStreamTrack.kind === 'audio';
24202
- isAudio ? opts.audio : opts.video;
24203
- let trackConstraints;
24204
- const conOrBool = isAudio ? constraints.audio : constraints.video;
24205
- if (typeof conOrBool !== 'boolean') {
24206
- trackConstraints = conOrBool;
24207
- }
24208
- // update the constraints with the device id the user gave permissions to in the permission prompt
24209
- // otherwise each track restart (e.g. mute - unmute) will try to initialize the device again -> causing additional permission prompts
24210
- const newDeviceId = mediaStreamTrack.getSettings().deviceId;
24211
- if ((trackConstraints === null || trackConstraints === void 0 ? void 0 : trackConstraints.deviceId) && unwrapConstraint(trackConstraints.deviceId) !== newDeviceId) {
24212
- trackConstraints.deviceId = newDeviceId;
24213
- } else if (!trackConstraints) {
24214
- trackConstraints = {
24215
- deviceId: newDeviceId
24216
- };
24217
- }
24218
- const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints);
24219
- if (track.kind === Track.Kind.Video) {
24220
- track.source = Track.Source.Camera;
24221
- } else if (track.kind === Track.Kind.Audio) {
24222
- track.source = Track.Source.Microphone;
24223
- }
24224
- track.mediaStream = stream;
24225
- if (isAudioTrack(track) && audioProcessor) {
24226
- yield track.setProcessor(audioProcessor);
24227
- } else if (isVideoTrack(track) && videoProcessor) {
24228
- yield track.setProcessor(videoProcessor);
24331
+ try {
24332
+ const stream = yield mediaPromise;
24333
+ return yield Promise.all(stream.getTracks().map(mediaStreamTrack => __awaiter(this, void 0, void 0, function* () {
24334
+ const isAudio = mediaStreamTrack.kind === 'audio';
24335
+ let trackOptions = isAudio ? opts.audio : opts.video;
24336
+ if (typeof trackOptions === 'boolean' || !trackOptions) {
24337
+ trackOptions = {};
24338
+ }
24339
+ let trackConstraints;
24340
+ const conOrBool = isAudio ? constraints.audio : constraints.video;
24341
+ if (typeof conOrBool !== 'boolean') {
24342
+ trackConstraints = conOrBool;
24343
+ }
24344
+ // update the constraints with the device id the user gave permissions to in the permission prompt
24345
+ // otherwise each track restart (e.g. mute - unmute) will try to initialize the device again -> causing additional permission prompts
24346
+ const newDeviceId = mediaStreamTrack.getSettings().deviceId;
24347
+ if ((trackConstraints === null || trackConstraints === void 0 ? void 0 : trackConstraints.deviceId) && unwrapConstraint(trackConstraints.deviceId) !== newDeviceId) {
24348
+ trackConstraints.deviceId = newDeviceId;
24349
+ } else if (!trackConstraints) {
24350
+ trackConstraints = {
24351
+ deviceId: newDeviceId
24352
+ };
24353
+ }
24354
+ const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints);
24355
+ if (track.kind === Track.Kind.Video) {
24356
+ track.source = Track.Source.Camera;
24357
+ } else if (track.kind === Track.Kind.Audio) {
24358
+ track.source = Track.Source.Microphone;
24359
+ }
24360
+ track.mediaStream = stream;
24361
+ if (isAudioTrack(track) && audioProcessor) {
24362
+ yield track.setProcessor(audioProcessor);
24363
+ } else if (isVideoTrack(track) && videoProcessor) {
24364
+ yield track.setProcessor(videoProcessor);
24365
+ }
24366
+ return track;
24367
+ })));
24368
+ } catch (e) {
24369
+ if (!attemptExactMatch) {
24370
+ throw e;
24229
24371
  }
24230
- return track;
24231
- })));
24372
+ return createLocalTracks(Object.assign(Object.assign({}, options), {
24373
+ audio: retryAudioOptions,
24374
+ video: retryVideoOptions
24375
+ }));
24376
+ }
24232
24377
  });
24233
24378
  }
24234
24379
  /**