livekit-client 1.1.0 → 1.1.3

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.
@@ -7049,7 +7049,8 @@ function createBaseAddTrackRequest() {
7049
7049
  disableDtx: false,
7050
7050
  source: 0,
7051
7051
  layers: [],
7052
- simulcastCodecs: []
7052
+ simulcastCodecs: [],
7053
+ sid: ''
7053
7054
  };
7054
7055
  }
7055
7056
 
@@ -7097,6 +7098,10 @@ const AddTrackRequest = {
7097
7098
  SimulcastCodec.encode(v, writer.uint32(82).fork()).ldelim();
7098
7099
  }
7099
7100
 
7101
+ if (message.sid !== '') {
7102
+ writer.uint32(90).string(message.sid);
7103
+ }
7104
+
7100
7105
  return writer;
7101
7106
  },
7102
7107
 
@@ -7149,6 +7154,10 @@ const AddTrackRequest = {
7149
7154
  message.simulcastCodecs.push(SimulcastCodec.decode(reader, reader.uint32()));
7150
7155
  break;
7151
7156
 
7157
+ case 11:
7158
+ message.sid = reader.string();
7159
+ break;
7160
+
7152
7161
  default:
7153
7162
  reader.skipType(tag & 7);
7154
7163
  break;
@@ -7169,7 +7178,8 @@ const AddTrackRequest = {
7169
7178
  disableDtx: isSet(object.disableDtx) ? Boolean(object.disableDtx) : false,
7170
7179
  source: isSet(object.source) ? trackSourceFromJSON(object.source) : 0,
7171
7180
  layers: Array.isArray(object === null || object === void 0 ? void 0 : object.layers) ? object.layers.map(e => VideoLayer.fromJSON(e)) : [],
7172
- simulcastCodecs: Array.isArray(object === null || object === void 0 ? void 0 : object.simulcastCodecs) ? object.simulcastCodecs.map(e => SimulcastCodec.fromJSON(e)) : []
7181
+ simulcastCodecs: Array.isArray(object === null || object === void 0 ? void 0 : object.simulcastCodecs) ? object.simulcastCodecs.map(e => SimulcastCodec.fromJSON(e)) : [],
7182
+ sid: isSet(object.sid) ? String(object.sid) : ''
7173
7183
  };
7174
7184
  },
7175
7185
 
@@ -7196,11 +7206,12 @@ const AddTrackRequest = {
7196
7206
  obj.simulcastCodecs = [];
7197
7207
  }
7198
7208
 
7209
+ message.sid !== undefined && (obj.sid = message.sid);
7199
7210
  return obj;
7200
7211
  },
7201
7212
 
7202
7213
  fromPartial(object) {
7203
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
7214
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
7204
7215
 
7205
7216
  const message = createBaseAddTrackRequest();
7206
7217
  message.cid = (_a = object.cid) !== null && _a !== void 0 ? _a : '';
@@ -7213,6 +7224,7 @@ const AddTrackRequest = {
7213
7224
  message.source = (_h = object.source) !== null && _h !== void 0 ? _h : 0;
7214
7225
  message.layers = ((_j = object.layers) === null || _j === void 0 ? void 0 : _j.map(e => VideoLayer.fromPartial(e))) || [];
7215
7226
  message.simulcastCodecs = ((_k = object.simulcastCodecs) === null || _k === void 0 ? void 0 : _k.map(e => SimulcastCodec.fromPartial(e))) || [];
7227
+ message.sid = (_l = object.sid) !== null && _l !== void 0 ? _l : '';
7216
7228
  return message;
7217
7229
  }
7218
7230
 
@@ -10058,7 +10070,7 @@ function computeBitrate(currentStats, prevStats) {
10058
10070
  return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
10059
10071
  }
10060
10072
 
10061
- var version$1 = "1.1.0";
10073
+ var version$1 = "1.1.3";
10062
10074
 
10063
10075
  const version = version$1;
10064
10076
  const protocolVersion = 8;
@@ -10130,9 +10142,10 @@ function getEmptyVideoStreamTrack() {
10130
10142
  var _a;
10131
10143
 
10132
10144
  if (!emptyVideoStreamTrack) {
10133
- const canvas = document.createElement('canvas');
10134
- canvas.width = 2;
10135
- canvas.height = 2;
10145
+ const canvas = document.createElement('canvas'); // the canvas size is set to 16, because electron apps seem to fail with smaller values
10146
+
10147
+ canvas.width = 16;
10148
+ canvas.height = 16;
10136
10149
  (_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.fillRect(0, 0, canvas.width, canvas.height); // @ts-ignore
10137
10150
 
10138
10151
  const emptyStream = canvas.captureStream();
@@ -11514,6 +11527,7 @@ class LocalAudioTrack extends LocalTrack {
11514
11527
 
11515
11528
  }
11516
11529
 
11530
+ const refreshSubscribedCodecAfterNewCodec = 5000;
11517
11531
  class LocalVideoTrack extends LocalTrack {
11518
11532
  constructor(mediaTrack, constraints) {
11519
11533
  super(mediaTrack, Track.Kind.Video, constraints);
@@ -11730,7 +11744,14 @@ class LocalVideoTrack extends LocalTrack {
11730
11744
  return;
11731
11745
  }
11732
11746
 
11733
- simulcastCodecInfo.sender = sender;
11747
+ simulcastCodecInfo.sender = sender; // browser will reenable disabled codec/layers after new codec has been published,
11748
+ // so refresh subscribedCodecs after publish a new codec
11749
+
11750
+ setTimeout(() => {
11751
+ if (this.subscribedCodecs) {
11752
+ this.setPublishingCodecs(this.subscribedCodecs);
11753
+ }
11754
+ }, refreshSubscribedCodecAfterNewCodec);
11734
11755
  }
11735
11756
  /**
11736
11757
  * @internal
@@ -11739,25 +11760,41 @@ class LocalVideoTrack extends LocalTrack {
11739
11760
 
11740
11761
 
11741
11762
  async setPublishingCodecs(codecs) {
11742
- livekitLogger.debug('setting publishing codecs', codecs);
11763
+ livekitLogger.debug('setting publishing codecs', {
11764
+ codecs,
11765
+ currentCodec: this.codec
11766
+ }); // only enable simulcast codec for preference codec setted
11767
+
11768
+ if (!this.codec && codecs.length > 0) {
11769
+ await this.setPublishingLayers(codecs[0].qualities);
11770
+ return [];
11771
+ }
11772
+
11773
+ this.subscribedCodecs = codecs;
11774
+ const newCodecs = [];
11743
11775
 
11744
11776
  for await (const codec of codecs) {
11745
- if (this.codec === codec.codec) {
11777
+ if (!this.codec || this.codec === codec.codec) {
11746
11778
  await this.setPublishingLayers(codec.qualities);
11747
11779
  } else {
11748
11780
  const simulcastCodecInfo = this.simulcastCodecs.get(codec.codec);
11749
11781
  livekitLogger.debug("try setPublishingCodec for ".concat(codec.codec), simulcastCodecInfo);
11750
11782
 
11751
11783
  if (!simulcastCodecInfo || !simulcastCodecInfo.sender) {
11752
- return;
11753
- }
11754
-
11755
- if (simulcastCodecInfo.encodings) {
11784
+ for (const q of codec.qualities) {
11785
+ if (q.enabled) {
11786
+ newCodecs.push(codec.codec);
11787
+ break;
11788
+ }
11789
+ }
11790
+ } else if (simulcastCodecInfo.encodings) {
11756
11791
  livekitLogger.debug("try setPublishingLayersForSender ".concat(codec.codec));
11757
11792
  await setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities);
11758
11793
  }
11759
11794
  }
11760
11795
  }
11796
+
11797
+ return newCodecs;
11761
11798
  }
11762
11799
  /**
11763
11800
  * @internal
@@ -12188,6 +12225,8 @@ class RemoteVideoTrack extends RemoteTrack {
12188
12225
 
12189
12226
  this.debouncedHandleResize();
12190
12227
  this.updateVisibility();
12228
+ } else {
12229
+ livekitLogger.warn('visibility resize observer not triggered');
12191
12230
  }
12192
12231
  }
12193
12232
  /**
@@ -12336,9 +12375,7 @@ class RemoteVideoTrack extends RemoteTrack {
12336
12375
  }
12337
12376
 
12338
12377
  class HTMLElementInfo {
12339
- constructor(element) {
12340
- let visible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
12341
-
12378
+ constructor(element, visible) {
12342
12379
  this.onVisibilityChanged = entry => {
12343
12380
  var _a;
12344
12381
 
@@ -12355,7 +12392,7 @@ class HTMLElementInfo {
12355
12392
  };
12356
12393
 
12357
12394
  this.element = element;
12358
- this.visible = visible;
12395
+ this.visible = visible !== null && visible !== void 0 ? visible : isElementInViewport(element);
12359
12396
  this.visibilityChangedAt = 0;
12360
12397
  }
12361
12398
 
@@ -12364,7 +12401,7 @@ class HTMLElementInfo {
12364
12401
  }
12365
12402
 
12366
12403
  height() {
12367
- return this.element.clientWidth;
12404
+ return this.element.clientHeight;
12368
12405
  }
12369
12406
 
12370
12407
  observe() {
@@ -12386,6 +12423,29 @@ class HTMLElementInfo {
12386
12423
  (_b = getResizeObserver()) === null || _b === void 0 ? void 0 : _b.unobserve(this.element);
12387
12424
  }
12388
12425
 
12426
+ } // does not account for occlusion by other elements
12427
+
12428
+
12429
+ function isElementInViewport(el) {
12430
+ let top = el.offsetTop;
12431
+ let left = el.offsetLeft;
12432
+ const width = el.offsetWidth;
12433
+ const height = el.offsetHeight;
12434
+ const {
12435
+ hidden
12436
+ } = el;
12437
+ const {
12438
+ opacity,
12439
+ display
12440
+ } = getComputedStyle(el);
12441
+
12442
+ while (el.offsetParent) {
12443
+ el = el.offsetParent;
12444
+ top += el.offsetTop;
12445
+ left += el.offsetLeft;
12446
+ }
12447
+
12448
+ return top < window.pageYOffset + window.innerHeight && left < window.pageXOffset + window.innerWidth && top + height > window.pageYOffset && left + width > window.pageXOffset && !hidden && (opacity !== '' ? parseFloat(opacity) > 0 : true) && display !== 'none';
12389
12449
  }
12390
12450
 
12391
12451
  class TrackPublication extends events.exports.EventEmitter {
@@ -13358,9 +13418,7 @@ class RemoteParticipant extends Participant {
13358
13418
 
13359
13419
 
13360
13420
  static fromParticipantInfo(signalClient, pi) {
13361
- const rp = new RemoteParticipant(signalClient, pi.sid, pi.identity);
13362
- rp.updateInfo(pi);
13363
- return rp;
13421
+ return new RemoteParticipant(signalClient, pi.sid, pi.identity);
13364
13422
  }
13365
13423
 
13366
13424
  addTrackPublication(publication) {
@@ -13501,7 +13559,6 @@ class RemoteParticipant extends Participant {
13501
13559
 
13502
13560
 
13503
13561
  updateInfo(info) {
13504
- const alreadyHasMetadata = this.hasMetadata;
13505
13562
  super.updateInfo(info); // we are getting a list of all available tracks, reconcile in here
13506
13563
  // and send out events for changes
13507
13564
  // reconcile track publications, publish events only if metadata is already there
@@ -13529,14 +13586,11 @@ class RemoteParticipant extends Participant {
13529
13586
  }
13530
13587
 
13531
13588
  validTracks.set(ti.sid, publication);
13532
- }); // send new tracks
13533
-
13534
- if (alreadyHasMetadata) {
13535
- newTracks.forEach(publication => {
13536
- this.emit(ParticipantEvent.TrackPublished, publication);
13537
- });
13538
- } // detect removed tracks
13589
+ }); // always emit events for new publications, Room will not forward them unless it's ready
13539
13590
 
13591
+ newTracks.forEach(publication => {
13592
+ this.emit(ParticipantEvent.TrackPublished, publication);
13593
+ }); // detect removed tracks
13540
13594
 
13541
13595
  this.tracks.forEach(publication => {
13542
13596
  if (!validTracks.has(publication.trackSid)) {
@@ -13605,7 +13659,7 @@ class RemoteParticipant extends Participant {
13605
13659
 
13606
13660
  }
13607
13661
 
13608
- const compatibleCodecForSVC = 'vp8';
13662
+ const compatibleCodec = 'vp8';
13609
13663
  class LocalParticipant extends Participant {
13610
13664
  /** @internal */
13611
13665
  constructor(sid, identity, engine, options) {
@@ -13654,8 +13708,8 @@ class LocalParticipant extends Participant {
13654
13708
  this.onTrackMuted(track, track.isMuted);
13655
13709
  };
13656
13710
 
13657
- this.handleSubscribedQualityUpdate = update => {
13658
- var _a, _b, _c;
13711
+ this.handleSubscribedQualityUpdate = async update => {
13712
+ var _a, _b;
13659
13713
 
13660
13714
  if (!((_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.dynacast)) {
13661
13715
  return;
@@ -13672,9 +13726,18 @@ class LocalParticipant extends Participant {
13672
13726
  }
13673
13727
 
13674
13728
  if (update.subscribedCodecs.length > 0) {
13675
- (_b = pub.videoTrack) === null || _b === void 0 ? void 0 : _b.setPublishingCodecs(update.subscribedCodecs);
13729
+ if (!pub.videoTrack) {
13730
+ return;
13731
+ }
13732
+
13733
+ const newCodecs = await pub.videoTrack.setPublishingCodecs(update.subscribedCodecs);
13734
+
13735
+ for await (const codec of newCodecs) {
13736
+ livekitLogger.debug("publish ".concat(codec, " for ").concat(pub.videoTrack.sid));
13737
+ await this.publishAdditionalCodecForTrack(pub.videoTrack, codec, pub.options);
13738
+ }
13676
13739
  } else if (update.subscribedQualities.length > 0) {
13677
- (_c = pub.videoTrack) === null || _c === void 0 ? void 0 : _c.setPublishingLayers(update.subscribedQualities);
13740
+ (_b = pub.videoTrack) === null || _b === void 0 ? void 0 : _b.setPublishingLayers(update.subscribedQualities);
13678
13741
  }
13679
13742
  };
13680
13743
 
@@ -14088,7 +14151,6 @@ class LocalParticipant extends Participant {
14088
14151
 
14089
14152
  let encodings;
14090
14153
  let simEncodings;
14091
- let simulcastTracks;
14092
14154
 
14093
14155
  if (track.kind === Track.Kind.Video) {
14094
14156
  // TODO: support react native, which doesn't expose getSettings
@@ -14099,26 +14161,30 @@ class LocalParticipant extends Participant {
14099
14161
  req.width = width !== null && width !== void 0 ? width : 0;
14100
14162
  req.height = height !== null && height !== void 0 ? height : 0; // for svc codecs, disable simulcast and use vp8 for backup codec
14101
14163
 
14102
- if (track instanceof LocalVideoTrack && ((opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'vp9' || (opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'av1')) {
14103
- // set scalabilityMode to 'L3T3' by default
14104
- opts.scalabilityMode = (_g = opts.scalabilityMode) !== null && _g !== void 0 ? _g : 'L3T3'; // add backup codec track
14105
-
14106
- const simOpts = _objectSpread2({}, opts);
14107
-
14108
- simOpts.simulcast = true;
14109
- simOpts.scalabilityMode = undefined;
14110
- simEncodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, simOpts);
14111
- const simulcastTrack = track.addSimulcastTrack(compatibleCodecForSVC, simEncodings);
14112
- simulcastTracks = [simulcastTrack];
14113
- req.simulcastCodecs = [{
14114
- codec: opts.videoCodec,
14115
- cid: track.mediaStreamTrack.id,
14116
- enableSimulcastLayers: true
14117
- }, {
14118
- codec: simulcastTrack.codec,
14119
- cid: simulcastTrack.mediaStreamTrack.id,
14120
- enableSimulcastLayers: true
14121
- }];
14164
+ if (track instanceof LocalVideoTrack) {
14165
+ if ((opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'vp9' || (opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'av1') {
14166
+ // set scalabilityMode to 'L3T3' by default
14167
+ opts.scalabilityMode = (_g = opts.scalabilityMode) !== null && _g !== void 0 ? _g : 'L3T3'; // add backup codec track
14168
+
14169
+ const simOpts = _objectSpread2({}, opts);
14170
+
14171
+ simOpts.simulcast = true;
14172
+ simOpts.scalabilityMode = undefined;
14173
+ simEncodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, simOpts);
14174
+ } // set vp8 codec as backup for any other codecs
14175
+
14176
+
14177
+ if (opts.videoCodec && opts.videoCodec !== 'vp8') {
14178
+ req.simulcastCodecs = [{
14179
+ codec: opts.videoCodec,
14180
+ cid: track.mediaStreamTrack.id,
14181
+ enableSimulcastLayers: true
14182
+ }, {
14183
+ codec: compatibleCodec,
14184
+ cid: '',
14185
+ enableSimulcastLayers: true
14186
+ }];
14187
+ }
14122
14188
  }
14123
14189
 
14124
14190
  encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, opts);
@@ -14163,24 +14229,6 @@ class LocalParticipant extends Participant {
14163
14229
  track.codec = opts.videoCodec;
14164
14230
  }
14165
14231
 
14166
- const localTrack = track;
14167
-
14168
- if (simulcastTracks) {
14169
- for await (const simulcastTrack of simulcastTracks) {
14170
- const simTransceiverInit = {
14171
- direction: 'sendonly'
14172
- };
14173
-
14174
- if (simulcastTrack.encodings) {
14175
- simTransceiverInit.sendEncodings = simulcastTrack.encodings;
14176
- }
14177
-
14178
- const simTransceiver = await this.engine.publisher.pc.addTransceiver(simulcastTrack.mediaStreamTrack, simTransceiverInit);
14179
- this.setPreferredCodec(simTransceiver, localTrack.kind, simulcastTrack.codec);
14180
- localTrack.setSimulcastTrackSender(simulcastTrack.codec, simTransceiver.sender);
14181
- }
14182
- }
14183
-
14184
14232
  this.engine.negotiate(); // store RTPSender
14185
14233
 
14186
14234
  track.sender = transceiver.sender;
@@ -14196,6 +14244,86 @@ class LocalParticipant extends Participant {
14196
14244
  this.emit(ParticipantEvent.LocalTrackPublished, publication);
14197
14245
  return publication;
14198
14246
  }
14247
+ /** @internal
14248
+ * publish additional codec to existing track
14249
+ */
14250
+
14251
+
14252
+ async publishAdditionalCodecForTrack(track, videoCodec, options) {
14253
+ var _a, _b, _c, _d, _e;
14254
+
14255
+ const opts = _objectSpread2(_objectSpread2({}, (_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.publishDefaults), options); // clear scalabilityMode setting for backup codec
14256
+
14257
+
14258
+ opts.scalabilityMode = undefined;
14259
+ opts.videoCodec = videoCodec; // is it not published? if so skip
14260
+
14261
+ let existingPublication;
14262
+ this.tracks.forEach(publication => {
14263
+ if (!publication.track) {
14264
+ return;
14265
+ }
14266
+
14267
+ if (publication.track === track) {
14268
+ existingPublication = publication;
14269
+ }
14270
+ });
14271
+
14272
+ if (!existingPublication) {
14273
+ throw new TrackInvalidError('track is not published');
14274
+ }
14275
+
14276
+ if (!(track instanceof LocalVideoTrack)) {
14277
+ throw new TrackInvalidError('track is not a video track');
14278
+ }
14279
+
14280
+ const settings = track.mediaStreamTrack.getSettings();
14281
+ const width = (_b = settings.width) !== null && _b !== void 0 ? _b : (_c = track.dimensions) === null || _c === void 0 ? void 0 : _c.width;
14282
+ const height = (_d = settings.height) !== null && _d !== void 0 ? _d : (_e = track.dimensions) === null || _e === void 0 ? void 0 : _e.height;
14283
+ const encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, opts);
14284
+ const simulcastTrack = track.addSimulcastTrack(opts.videoCodec, encodings);
14285
+ const req = AddTrackRequest.fromPartial({
14286
+ cid: simulcastTrack.mediaStreamTrack.id,
14287
+ type: Track.kindToProto(track.kind),
14288
+ muted: track.isMuted,
14289
+ source: Track.sourceToProto(track.source),
14290
+ sid: track.sid,
14291
+ simulcastCodecs: [{
14292
+ codec: opts.videoCodec,
14293
+ cid: simulcastTrack.mediaStreamTrack.id,
14294
+ enableSimulcastLayers: opts.simulcast
14295
+ }]
14296
+ });
14297
+ req.layers = videoLayersFromEncodings(req.width, req.height, encodings);
14298
+
14299
+ if (!this.engine || this.engine.isClosed) {
14300
+ throw new UnexpectedConnectionState('cannot publish track when not connected');
14301
+ }
14302
+
14303
+ const ti = await this.engine.addTrack(req);
14304
+
14305
+ if (!this.engine.publisher) {
14306
+ throw new UnexpectedConnectionState('publisher is closed');
14307
+ }
14308
+
14309
+ const transceiverInit = {
14310
+ direction: 'sendonly'
14311
+ };
14312
+
14313
+ if (encodings) {
14314
+ transceiverInit.sendEncodings = encodings;
14315
+ } // addTransceiver for react-native is async. web is synchronous, but await won't effect it.
14316
+
14317
+
14318
+ const transceiver = await this.engine.publisher.pc.addTransceiver(simulcastTrack.mediaStreamTrack, transceiverInit);
14319
+ this.setPreferredCodec(transceiver, track.kind, opts.videoCodec);
14320
+ track.setSimulcastTrackSender(opts.videoCodec, transceiver.sender);
14321
+ this.engine.negotiate();
14322
+ livekitLogger.debug("published ".concat(opts.videoCodec, " for track ").concat(track.sid), {
14323
+ encodings,
14324
+ trackInfo: ti
14325
+ });
14326
+ }
14199
14327
 
14200
14328
  unpublishTrack(track, stopOnUnpublish) {
14201
14329
  var _a, _b; // look through all published tracks to find the right ones
@@ -19266,8 +19394,6 @@ class Room extends events.exports.EventEmitter {
19266
19394
  constructor(options) {
19267
19395
  var _this;
19268
19396
 
19269
- var _a, _b;
19270
-
19271
19397
  super();
19272
19398
  _this = this;
19273
19399
  this.state = ConnectionState.Disconnected;
@@ -19692,14 +19818,6 @@ class Room extends events.exports.EventEmitter {
19692
19818
  this.participants = new Map();
19693
19819
  this.identityToSid = new Map();
19694
19820
  this.options = options || {};
19695
-
19696
- switch ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.publishDefaults) === null || _b === void 0 ? void 0 : _b.videoCodec) {
19697
- case 'av1':
19698
- case 'vp9':
19699
- this.options.publishDefaults.simulcast = undefined;
19700
- break;
19701
- }
19702
-
19703
19821
  this.options.audioCaptureDefaults = _objectSpread2(_objectSpread2({}, audioDefaults), options === null || options === void 0 ? void 0 : options.audioCaptureDefaults);
19704
19822
  this.options.videoCaptureDefaults = _objectSpread2(_objectSpread2({}, videoDefaults), options === null || options === void 0 ? void 0 : options.videoCaptureDefaults);
19705
19823
  this.options.publishDefaults = _objectSpread2(_objectSpread2({}, publishDefaults), options === null || options === void 0 ? void 0 : options.publishDefaults);
@@ -19914,6 +20032,22 @@ class Room extends events.exports.EventEmitter {
19914
20032
  }
19915
20033
 
19916
20034
  onTrackAdded(mediaTrack, stream, receiver) {
20035
+ // don't fire onSubscribed when connecting
20036
+ // WebRTC fires onTrack as soon as setRemoteDescription is called on the offer
20037
+ // at that time, ICE connectivity has not been established so the track is not
20038
+ // technically subscribed.
20039
+ // We'll defer these events until when the room is connected or eventually disconnected.
20040
+ if (this.state === ConnectionState.Connecting || this.state === ConnectionState.Reconnecting) {
20041
+ setTimeout(() => {
20042
+ this.onTrackAdded(mediaTrack, stream, receiver);
20043
+ }, 10);
20044
+ return;
20045
+ }
20046
+
20047
+ if (this.state === ConnectionState.Disconnected) {
20048
+ livekitLogger.warn('skipping incoming track after Room disconnected');
20049
+ }
20050
+
19917
20051
  const parts = unpackStreamId(stream.id);
19918
20052
  const participantId = parts[0];
19919
20053
  let trackId = parts[1];
@@ -20030,7 +20164,7 @@ class Room extends events.exports.EventEmitter {
20030
20164
 
20031
20165
 
20032
20166
  participant.on(ParticipantEvent.TrackPublished, trackPublication => {
20033
- this.emit(RoomEvent.TrackPublished, trackPublication, participant);
20167
+ this.emitWhenConnected(RoomEvent.TrackPublished, trackPublication, participant);
20034
20168
  }).on(ParticipantEvent.TrackSubscribed, (track, publication) => {
20035
20169
  // monitor playback status
20036
20170
  if (track.kind === Track.Kind.Audio) {
@@ -20040,22 +20174,27 @@ class Room extends events.exports.EventEmitter {
20040
20174
 
20041
20175
  this.emit(RoomEvent.TrackSubscribed, track, publication, participant);
20042
20176
  }).on(ParticipantEvent.TrackUnpublished, publication => {
20043
- this.emit(RoomEvent.TrackUnpublished, publication, participant);
20177
+ this.emitWhenConnected(RoomEvent.TrackUnpublished, publication, participant);
20044
20178
  }).on(ParticipantEvent.TrackUnsubscribed, (track, publication) => {
20045
20179
  this.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);
20046
20180
  }).on(ParticipantEvent.TrackSubscriptionFailed, sid => {
20047
20181
  this.emit(RoomEvent.TrackSubscriptionFailed, sid, participant);
20048
20182
  }).on(ParticipantEvent.TrackMuted, pub => {
20049
- this.emit(RoomEvent.TrackMuted, pub, participant);
20183
+ this.emitWhenConnected(RoomEvent.TrackMuted, pub, participant);
20050
20184
  }).on(ParticipantEvent.TrackUnmuted, pub => {
20051
- this.emit(RoomEvent.TrackUnmuted, pub, participant);
20185
+ this.emitWhenConnected(RoomEvent.TrackUnmuted, pub, participant);
20052
20186
  }).on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
20053
- this.emit(RoomEvent.ParticipantMetadataChanged, metadata, participant);
20187
+ this.emitWhenConnected(RoomEvent.ParticipantMetadataChanged, metadata, participant);
20054
20188
  }).on(ParticipantEvent.ConnectionQualityChanged, quality => {
20055
- this.emit(RoomEvent.ConnectionQualityChanged, quality, participant);
20189
+ this.emitWhenConnected(RoomEvent.ConnectionQualityChanged, quality, participant);
20056
20190
  }).on(ParticipantEvent.ParticipantPermissionsChanged, prevPermissions => {
20057
- this.emit(RoomEvent.ParticipantPermissionsChanged, prevPermissions, participant);
20058
- });
20191
+ this.emitWhenConnected(RoomEvent.ParticipantPermissionsChanged, prevPermissions, participant);
20192
+ }); // update info at the end after callbacks have been set up
20193
+
20194
+ if (info) {
20195
+ participant.updateInfo(info);
20196
+ }
20197
+
20059
20198
  return participant;
20060
20199
  }
20061
20200
 
@@ -20121,12 +20260,24 @@ class Room extends events.exports.EventEmitter {
20121
20260
  this.state = state;
20122
20261
  this.emit(RoomEvent.ConnectionStateChanged, this.state);
20123
20262
  return true;
20263
+ }
20264
+
20265
+ emitWhenConnected(event) {
20266
+ if (this.state === ConnectionState.Connected) {
20267
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
20268
+ args[_key - 1] = arguments[_key];
20269
+ }
20270
+
20271
+ return this.emit(event, ...args);
20272
+ }
20273
+
20274
+ return false;
20124
20275
  } // /** @internal */
20125
20276
 
20126
20277
 
20127
20278
  emit(event) {
20128
- for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
20129
- args[_key - 1] = arguments[_key];
20279
+ for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
20280
+ args[_key2 - 1] = arguments[_key2];
20130
20281
  }
20131
20282
 
20132
20283
  livekitLogger.debug('room event', {