livekit-client 2.1.3 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/livekit-client.esm.mjs +92 -29
  2. package/dist/livekit-client.esm.mjs.map +1 -1
  3. package/dist/livekit-client.umd.js +1 -1
  4. package/dist/livekit-client.umd.js.map +1 -1
  5. package/dist/src/room/PCTransport.d.ts.map +1 -1
  6. package/dist/src/room/Room.d.ts.map +1 -1
  7. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  8. package/dist/src/room/participant/publishUtils.d.ts +1 -0
  9. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  10. package/dist/src/room/track/LocalTrack.d.ts +5 -1
  11. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  12. package/dist/src/room/track/LocalVideoTrack.d.ts +3 -0
  13. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  14. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  15. package/dist/src/room/track/options.d.ts +4 -0
  16. package/dist/src/room/track/options.d.ts.map +1 -1
  17. package/dist/src/room/track/utils.d.ts +1 -0
  18. package/dist/src/room/track/utils.d.ts.map +1 -1
  19. package/dist/src/room/types.d.ts +1 -1
  20. package/dist/src/room/types.d.ts.map +1 -1
  21. package/dist/src/room/utils.d.ts +1 -0
  22. package/dist/src/room/utils.d.ts.map +1 -1
  23. package/dist/ts4.2/src/room/participant/publishUtils.d.ts +1 -0
  24. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +5 -1
  25. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +3 -0
  26. package/dist/ts4.2/src/room/track/options.d.ts +4 -0
  27. package/dist/ts4.2/src/room/track/utils.d.ts +1 -0
  28. package/dist/ts4.2/src/room/types.d.ts +1 -1
  29. package/dist/ts4.2/src/room/utils.d.ts +1 -0
  30. package/package.json +2 -2
  31. package/src/room/PCTransport.ts +10 -7
  32. package/src/room/Room.ts +7 -1
  33. package/src/room/participant/LocalParticipant.ts +7 -16
  34. package/src/room/participant/publishUtils.ts +20 -0
  35. package/src/room/track/LocalTrack.ts +21 -2
  36. package/src/room/track/LocalVideoTrack.ts +23 -0
  37. package/src/room/track/RemoteTrack.ts +4 -1
  38. package/src/room/track/options.ts +5 -0
  39. package/src/room/track/utils.ts +4 -0
  40. package/src/room/types.ts +3 -1
  41. package/src/room/utils.ts +4 -2
@@ -5494,6 +5494,12 @@ const SimulateScenario = /*@__PURE__*/proto3.makeMessageType("livekit.SimulateSc
5494
5494
  kind: "scalar",
5495
5495
  T: 8 /* ScalarType.BOOL */,
5496
5496
  oneof: "scenario"
5497
+ }, {
5498
+ no: 9,
5499
+ name: "leave_request_full_reconnect",
5500
+ kind: "scalar",
5501
+ T: 8 /* ScalarType.BOOL */,
5502
+ oneof: "scenario"
5497
5503
  }]);
5498
5504
 
5499
5505
  /**
@@ -10499,7 +10505,7 @@ function getOSVersion(ua) {
10499
10505
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
10500
10506
  }
10501
10507
 
10502
- var version$1 = "2.1.3";
10508
+ var version$1 = "2.1.4";
10503
10509
 
10504
10510
  const version = version$1;
10505
10511
  const protocolVersion = 13;
@@ -11203,6 +11209,9 @@ function getLogContextFromTrack(track) {
11203
11209
  };
11204
11210
  }
11205
11211
  }
11212
+ function supportsSynchronizationSources() {
11213
+ return typeof RTCRtpReceiver !== 'undefined' && 'getSynchronizationSources' in RTCRtpReceiver;
11214
+ }
11206
11215
 
11207
11216
  const separator = '|';
11208
11217
  const ddExtensionURI = 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension';
@@ -11575,7 +11584,7 @@ function isVideoCodec(maybeCodec) {
11575
11584
  return videoCodecs.includes(maybeCodec);
11576
11585
  }
11577
11586
  function unwrapConstraint(constraint) {
11578
- if (typeof constraint === 'string') {
11587
+ if (typeof constraint === 'string' || typeof constraint === 'number') {
11579
11588
  return constraint;
11580
11589
  }
11581
11590
  if (Array.isArray(constraint)) {
@@ -11712,6 +11721,14 @@ DeviceManager.userMediaPromiseMap = new Map();
11712
11721
 
11713
11722
  const defaultDimensionsTimeout = 1000;
11714
11723
  class LocalTrack extends Track {
11724
+ /** @internal */
11725
+ get sender() {
11726
+ return this._sender;
11727
+ }
11728
+ /** @internal */
11729
+ set sender(sender) {
11730
+ this._sender = sender;
11731
+ }
11715
11732
  get constraints() {
11716
11733
  return this._constraints;
11717
11734
  }
@@ -11726,6 +11743,7 @@ class LocalTrack extends Track {
11726
11743
  let userProvidedTrack = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
11727
11744
  let loggerOptions = arguments.length > 4 ? arguments[4] : undefined;
11728
11745
  super(mediaTrack, kind, loggerOptions);
11746
+ this.manuallyStopped = false;
11729
11747
  this._isUpstreamPaused = false;
11730
11748
  this.handleTrackMuteEvent = () => this.debouncedTrackMuteHandler().catch(() => this.log.debug('track mute bounce got cancelled by an unmute event', this.logContext));
11731
11749
  this.debouncedTrackMuteHandler = r(() => __awaiter(this, void 0, void 0, function* () {
@@ -11936,6 +11954,7 @@ class LocalTrack extends Track {
11936
11954
  }
11937
11955
  restart(constraints) {
11938
11956
  return __awaiter(this, void 0, void 0, function* () {
11957
+ this.manuallyStopped = false;
11939
11958
  const unlock = yield this.restartLock.lock();
11940
11959
  try {
11941
11960
  if (!constraints) {
@@ -11971,6 +11990,10 @@ class LocalTrack extends Track {
11971
11990
  yield this.setMediaStreamTrack(newTrack);
11972
11991
  this._constraints = constraints;
11973
11992
  this.emit(TrackEvent.Restarted, this);
11993
+ if (this.manuallyStopped) {
11994
+ this.log.warn('track was stopped during a restart, stopping restarted track', this.logContext);
11995
+ this.stop();
11996
+ }
11974
11997
  return this;
11975
11998
  } finally {
11976
11999
  unlock();
@@ -12008,6 +12031,7 @@ class LocalTrack extends Track {
12008
12031
  }
12009
12032
  stop() {
12010
12033
  var _a;
12034
+ this.manuallyStopped = true;
12011
12035
  super.stop();
12012
12036
  this._mediaStreamTrack.removeEventListener('ended', this.handleEnded);
12013
12037
  this._mediaStreamTrack.removeEventListener('mute', this.handleTrackMuteEvent);
@@ -14098,8 +14122,6 @@ class PCTransport extends eventsExports.EventEmitter {
14098
14122
  if (media.type === 'audio') {
14099
14123
  ensureAudioNackAndStereo(media, [], []);
14100
14124
  } else if (media.type === 'video') {
14101
- ensureVideoDDExtensionForSVC(media);
14102
- // mung sdp for codec bitrate setting that can't apply by sendEncoding
14103
14125
  this.trackBitrates.some(trackbr => {
14104
14126
  if (!media.msid || !trackbr.cid || !media.msid.includes(trackbr.cid)) {
14105
14127
  return false;
@@ -14115,6 +14137,14 @@ class PCTransport extends eventsExports.EventEmitter {
14115
14137
  if (codecPayload === 0) {
14116
14138
  return true;
14117
14139
  }
14140
+ if (isSVCCodec(trackbr.codec)) {
14141
+ ensureVideoDDExtensionForSVC(media);
14142
+ }
14143
+ // TODO: av1 slow starting issue already fixed in chrome 124, clean this after some versions
14144
+ // mung sdp for av1 bitrate setting that can't apply by sendEncoding
14145
+ if (trackbr.codec !== 'av1') {
14146
+ return true;
14147
+ }
14118
14148
  const startBitrate = Math.round(trackbr.maxbr * startBitrateForSVC);
14119
14149
  for (const fmtp of media.fmtp) {
14120
14150
  if (fmtp.payload === codecPayload) {
@@ -14331,13 +14361,9 @@ function ensureAudioNackAndStereo(media, stereoMids, nackMids) {
14331
14361
  }
14332
14362
  }
14333
14363
  function ensureVideoDDExtensionForSVC(media) {
14334
- var _a, _b, _c, _d;
14335
- const codec = (_b = (_a = media.rtp[0]) === null || _a === void 0 ? void 0 : _a.codec) === null || _b === void 0 ? void 0 : _b.toLowerCase();
14336
- if (!isSVCCodec(codec)) {
14337
- return;
14338
- }
14364
+ var _a, _b;
14339
14365
  let maxID = 0;
14340
- const ddFound = (_c = media.ext) === null || _c === void 0 ? void 0 : _c.some(ext => {
14366
+ const ddFound = (_a = media.ext) === null || _a === void 0 ? void 0 : _a.some(ext => {
14341
14367
  if (ext.uri === ddExtensionURI) {
14342
14368
  return true;
14343
14369
  }
@@ -14347,7 +14373,7 @@ function ensureVideoDDExtensionForSVC(media) {
14347
14373
  return false;
14348
14374
  });
14349
14375
  if (!ddFound) {
14350
- (_d = media.ext) === null || _d === void 0 ? void 0 : _d.push({
14376
+ (_b = media.ext) === null || _b === void 0 ? void 0 : _b.push({
14351
14377
  value: maxID + 1,
14352
14378
  uri: ddExtensionURI
14353
14379
  });
@@ -15055,6 +15081,10 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
15055
15081
  scalabilityMode: scalabilityMode
15056
15082
  });
15057
15083
  }
15084
+ if (original.encoding.priority) {
15085
+ encodings[0].priority = original.encoding.priority;
15086
+ encodings[0].networkPriority = original.encoding.priority;
15087
+ }
15058
15088
  livekitLogger.debug("using svc encoding", {
15059
15089
  encodings
15060
15090
  });
@@ -15268,9 +15298,25 @@ class ScalabilityMode {
15268
15298
  return "L".concat(this.spatial, "T").concat(this.temporal).concat((_a = this.suffix) !== null && _a !== void 0 ? _a : '');
15269
15299
  }
15270
15300
  }
15301
+ function getDefaultDegradationPreference(track) {
15302
+ // a few of reasons we have different default paths:
15303
+ // 1. without this, Chrome seems to aggressively resize the SVC video stating `quality-limitation: bandwidth` even when BW isn't an issue
15304
+ // 2. since we are overriding contentHint to motion (to workaround L1T3 publishing), it overrides the default degradationPreference to `balanced`
15305
+ if (track.source === Track.Source.ScreenShare || track.constraints.height && unwrapConstraint(track.constraints.height) >= 1080) {
15306
+ return 'maintain-resolution';
15307
+ } else {
15308
+ return 'balanced';
15309
+ }
15310
+ }
15271
15311
 
15272
15312
  const refreshSubscribedCodecAfterNewCodec = 5000;
15273
15313
  class LocalVideoTrack extends LocalTrack {
15314
+ set sender(sender) {
15315
+ this._sender = sender;
15316
+ if (this.degradationPreference) {
15317
+ this.setDegradationPreference(this.degradationPreference);
15318
+ }
15319
+ }
15274
15320
  /**
15275
15321
  *
15276
15322
  * @param mediaTrack
@@ -15283,6 +15329,7 @@ class LocalVideoTrack extends LocalTrack {
15283
15329
  super(mediaTrack, Track.Kind.Video, constraints, userProvidedTrack, loggerOptions);
15284
15330
  /* @internal */
15285
15331
  this.simulcastCodecs = new Map();
15332
+ this.degradationPreference = 'balanced';
15286
15333
  this.monitorSender = () => __awaiter(this, void 0, void 0, function* () {
15287
15334
  if (!this.sender) {
15288
15335
  this._currentBitrate = 0;
@@ -15605,6 +15652,23 @@ class LocalVideoTrack extends LocalTrack {
15605
15652
  }();
15606
15653
  });
15607
15654
  }
15655
+ setDegradationPreference(preference) {
15656
+ return __awaiter(this, void 0, void 0, function* () {
15657
+ this.degradationPreference = preference;
15658
+ if (this.sender) {
15659
+ try {
15660
+ this.log.debug("setting degradationPreference to ".concat(preference), this.logContext);
15661
+ const params = this.sender.getParameters();
15662
+ params.degradationPreference = preference;
15663
+ this.sender.setParameters(params);
15664
+ } catch (e) {
15665
+ this.log.warn("failed to set degradationPreference", Object.assign({
15666
+ error: e
15667
+ }, this.logContext));
15668
+ }
15669
+ }
15670
+ });
15671
+ }
15608
15672
  addSimulcastTrack(codec, encodings) {
15609
15673
  if (this.simulcastCodecs.has(codec)) {
15610
15674
  this.log.error("".concat(codec, " already added, skipping adding simulcast codec"), this.logContext);
@@ -17076,7 +17140,9 @@ class RemoteTrack extends Track {
17076
17140
  if (!this.monitorInterval) {
17077
17141
  this.monitorInterval = setInterval(() => this.monitorReceiver(), monitorFrequency);
17078
17142
  }
17079
- this.registerTimeSyncUpdate();
17143
+ if (supportsSynchronizationSources()) {
17144
+ this.registerTimeSyncUpdate();
17145
+ }
17080
17146
  }
17081
17147
  registerTimeSyncUpdate() {
17082
17148
  const loop = () => {
@@ -18634,7 +18700,7 @@ class LocalParticipant extends Participant {
18634
18700
  }
18635
18701
  publish(track, opts, isStereo) {
18636
18702
  return __awaiter(this, void 0, void 0, function* () {
18637
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
18703
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
18638
18704
  const existingTrackOfSource = Array.from(this.trackPublications.values()).find(publishedTrack => track instanceof LocalTrack && publishedTrack.source === track.source);
18639
18705
  if (existingTrackOfSource && track.source !== Track.Source.Unknown) {
18640
18706
  this.log.info("publishing a second track with the same source: ".concat(track.source), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
@@ -18794,6 +18860,10 @@ class LocalParticipant extends Participant {
18794
18860
  trackInfo: ti
18795
18861
  }));
18796
18862
  track.sender = yield this.engine.createSender(track, opts, encodings);
18863
+ if (track instanceof LocalVideoTrack) {
18864
+ (_l = opts.degradationPreference) !== null && _l !== void 0 ? _l : opts.degradationPreference = getDefaultDegradationPreference(track);
18865
+ track.setDegradationPreference(opts.degradationPreference);
18866
+ }
18797
18867
  if (encodings) {
18798
18868
  if (isFireFox() && track.kind === Track.Kind.Audio) {
18799
18869
  /* Refer to RFC https://datatracker.ietf.org/doc/html/rfc7587#section-6.1,
@@ -18814,11 +18884,10 @@ class LocalParticipant extends Participant {
18814
18884
  this.engine.pcManager.publisher.setTrackCodecBitrate({
18815
18885
  transceiver: trackTransceiver,
18816
18886
  codec: 'opus',
18817
- maxbr: ((_l = encodings[0]) === null || _l === void 0 ? void 0 : _l.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
18887
+ maxbr: ((_m = encodings[0]) === null || _m === void 0 ? void 0 : _m.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
18818
18888
  });
18819
18889
  }
18820
- } else if (track.codec && track.codec == 'av1' && ((_m = encodings[0]) === null || _m === void 0 ? void 0 : _m.maxBitrate)) {
18821
- // AV1 requires setting x-start-bitrate in SDP
18890
+ } else if (track.codec && isSVCCodec(track.codec) && ((_o = encodings[0]) === null || _o === void 0 ? void 0 : _o.maxBitrate)) {
18822
18891
  this.engine.pcManager.publisher.setTrackCodecBitrate({
18823
18892
  cid: req.cid,
18824
18893
  codec: track.codec,
@@ -18826,19 +18895,6 @@ class LocalParticipant extends Participant {
18826
18895
  });
18827
18896
  }
18828
18897
  }
18829
- if (track.kind === Track.Kind.Video && track.source === Track.Source.ScreenShare) {
18830
- // a few of reasons we are forcing this setting without allowing overrides:
18831
- // 1. without this, Chrome seems to aggressively resize the SVC video stating `quality-limitation: bandwidth` even when BW isn't an issue
18832
- // 2. since we are overriding contentHint to motion (to workaround L1T3 publishing), it overrides the default degradationPreference to `balanced`
18833
- try {
18834
- this.log.debug("setting degradationPreference to maintain-resolution");
18835
- const params = track.sender.getParameters();
18836
- params.degradationPreference = 'maintain-resolution';
18837
- yield track.sender.setParameters(params);
18838
- } catch (e) {
18839
- this.log.warn("failed to set degradationPreference: ".concat(e));
18840
- }
18841
- }
18842
18898
  yield this.engine.negotiate();
18843
18899
  if (track instanceof LocalVideoTrack) {
18844
18900
  track.startMonitor(this.engine.client);
@@ -20626,6 +20682,13 @@ class Room extends eventsExports.EventEmitter {
20626
20682
  }
20627
20683
  });
20628
20684
  break;
20685
+ case 'leave-full-reconnect':
20686
+ req = new SimulateScenario({
20687
+ scenario: {
20688
+ case: 'leaveRequestFullReconnect',
20689
+ value: true
20690
+ }
20691
+ });
20629
20692
  }
20630
20693
  if (req) {
20631
20694
  yield this.engine.client.sendSimulateScenario(req);