livekit-client 2.0.6 → 2.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +27 -3
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +74 -35
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  10. package/dist/src/index.d.ts +7 -6
  11. package/dist/src/index.d.ts.map +1 -1
  12. package/dist/src/room/PCTransport.d.ts.map +1 -1
  13. package/dist/src/room/Room.d.ts.map +1 -1
  14. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  15. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  16. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  17. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  18. package/dist/src/room/track/options.d.ts +6 -0
  19. package/dist/src/room/track/options.d.ts.map +1 -1
  20. package/dist/src/room/track/utils.d.ts.map +1 -1
  21. package/dist/ts4.2/src/index.d.ts +7 -6
  22. package/dist/ts4.2/src/room/track/options.d.ts +6 -0
  23. package/package.json +1 -1
  24. package/src/e2ee/worker/FrameCryptor.ts +12 -0
  25. package/src/e2ee/worker/e2ee.worker.ts +24 -3
  26. package/src/index.ts +32 -29
  27. package/src/room/PCTransport.ts +6 -18
  28. package/src/room/Room.ts +1 -0
  29. package/src/room/participant/LocalParticipant.ts +31 -3
  30. package/src/room/participant/publishUtils.ts +38 -11
  31. package/src/room/track/LocalTrack.ts +11 -9
  32. package/src/room/track/RemoteAudioTrack.ts +1 -1
  33. package/src/room/track/options.ts +7 -0
  34. package/src/room/track/utils.ts +1 -0
@@ -13473,7 +13473,7 @@ function getMatch(exp, ua) {
13473
13473
  return match && match.length >= id && match[id] || '';
13474
13474
  }
13475
13475
 
13476
- var version$1 = "2.0.6";
13476
+ var version$1 = "2.0.8";
13477
13477
 
13478
13478
  const version = version$1;
13479
13479
  const protocolVersion = 12;
@@ -14118,7 +14118,8 @@ function screenCaptureToDisplayMediaStreamOptions(options) {
14118
14118
  controller: options.controller,
14119
14119
  selfBrowserSurface: options.selfBrowserSurface,
14120
14120
  surfaceSwitching: options.surfaceSwitching,
14121
- systemAudio: options.systemAudio
14121
+ systemAudio: options.systemAudio,
14122
+ preferCurrentTab: options.preferCurrentTab
14122
14123
  };
14123
14124
  }
14124
14125
  function mimeTypeToVideoCodecString(mimeType) {
@@ -15036,6 +15037,13 @@ class LocalTrack extends Track {
15036
15037
  const unlock = yield this.processorLock.lock();
15037
15038
  try {
15038
15039
  this.log.debug('setting up processor', this.logContext);
15040
+ const processorOptions = {
15041
+ kind: this.kind,
15042
+ track: this._mediaStreamTrack,
15043
+ element: this.processorElement,
15044
+ audioContext: this.audioContext
15045
+ };
15046
+ yield processor.init(processorOptions);
15039
15047
  if (this.processor) {
15040
15048
  yield this.stopProcessor();
15041
15049
  }
@@ -15048,13 +15056,6 @@ class LocalTrack extends Track {
15048
15056
  this.processorElement.play().catch(error => this.log.error('failed to play processor element', Object.assign(Object.assign({}, this.logContext), {
15049
15057
  error
15050
15058
  })));
15051
- const processorOptions = {
15052
- kind: this.kind,
15053
- track: this._mediaStreamTrack,
15054
- element: this.processorElement,
15055
- audioContext: this.audioContext
15056
- };
15057
- yield processor.init(processorOptions);
15058
15059
  this.processor = processor;
15059
15060
  if (this.processor.processedTrack) {
15060
15061
  for (const el of this.attachedElements) {
@@ -15091,7 +15092,10 @@ class LocalTrack extends Track {
15091
15092
  this.processor = undefined;
15092
15093
  (_b = this.processorElement) === null || _b === void 0 ? void 0 : _b.remove();
15093
15094
  this.processorElement = undefined;
15094
- yield this.restart();
15095
+ // apply original track constraints in case the processor changed them
15096
+ yield this._mediaStreamTrack.applyConstraints(this._constraints);
15097
+ // force re-setting of the mediaStreamTrack on the sender
15098
+ yield this.setMediaStreamTrack(this._mediaStreamTrack, true);
15095
15099
  this.emit(TrackEvent.TrackProcessorUpdate);
15096
15100
  });
15097
15101
  }
@@ -17031,25 +17035,18 @@ class PCTransport extends eventsExports.EventEmitter {
17031
17035
  if (codecPayload === 0) {
17032
17036
  return true;
17033
17037
  }
17034
- let fmtpFound = false;
17038
+ const startBitrate = Math.round(trackbr.maxbr * startBitrateForSVC);
17035
17039
  for (const fmtp of media.fmtp) {
17036
17040
  if (fmtp.payload === codecPayload) {
17041
+ // if another track's fmtp already is set, we cannot override the bitrate
17042
+ // this has the unfortunate consequence of being forced to use the
17043
+ // initial track's bitrate for all tracks
17037
17044
  if (!fmtp.config.includes('x-google-start-bitrate')) {
17038
- fmtp.config += ";x-google-start-bitrate=".concat(Math.round(trackbr.maxbr * startBitrateForSVC));
17045
+ fmtp.config += ";x-google-start-bitrate=".concat(startBitrate);
17039
17046
  }
17040
- if (!fmtp.config.includes('x-google-max-bitrate')) {
17041
- fmtp.config += ";x-google-max-bitrate=".concat(trackbr.maxbr);
17042
- }
17043
- fmtpFound = true;
17044
17047
  break;
17045
17048
  }
17046
17049
  }
17047
- if (!fmtpFound) {
17048
- media.fmtp.push({
17049
- payload: codecPayload,
17050
- config: "x-google-start-bitrate=".concat(Math.round(trackbr.maxbr * startBitrateForSVC), ";x-google-max-bitrate=").concat(trackbr.maxbr)
17051
- });
17052
- }
17053
17050
  return true;
17054
17051
  });
17055
17052
  }
@@ -19085,23 +19082,40 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
19085
19082
  }
19086
19083
  const original = new VideoPreset(width, height, videoEncoding.maxBitrate, videoEncoding.maxFramerate, videoEncoding.priority);
19087
19084
  if (scalabilityMode && isSVCCodec(videoCodec)) {
19088
- livekitLogger.debug("using svc with scalabilityMode ".concat(scalabilityMode));
19089
19085
  const sm = new ScalabilityMode(scalabilityMode);
19090
19086
  const encodings = [];
19091
19087
  if (sm.spatial > 3) {
19092
19088
  throw new Error("unsupported scalabilityMode: ".concat(scalabilityMode));
19093
19089
  }
19094
- for (let i = 0; i < sm.spatial; i += 1) {
19090
+ // Before M113 in Chrome, defining multiple encodings with an SVC codec indicated
19091
+ // that SVC mode should be used. Safari still works this way.
19092
+ // This is a bit confusing but is due to how libwebrtc interpreted the encodings field
19093
+ // before M113.
19094
+ // Announced here: https://groups.google.com/g/discuss-webrtc/c/-QQ3pxrl-fw?pli=1
19095
+ const browser = getBrowser();
19096
+ if (isSafari() || (browser === null || browser === void 0 ? void 0 : browser.name) === 'Chrome' && compareVersions(browser === null || browser === void 0 ? void 0 : browser.version, '113') < 0) {
19097
+ for (let i = 0; i < sm.spatial; i += 1) {
19098
+ // in legacy SVC, scaleResolutionDownBy cannot be set
19099
+ encodings.push({
19100
+ rid: videoRids[2 - i],
19101
+ maxBitrate: videoEncoding.maxBitrate / Math.pow(3, i),
19102
+ maxFramerate: original.encoding.maxFramerate
19103
+ });
19104
+ }
19105
+ // legacy SVC, scalabilityMode is set only on the first encoding
19106
+ /* @ts-ignore */
19107
+ encodings[0].scalabilityMode = scalabilityMode;
19108
+ } else {
19095
19109
  encodings.push({
19096
- rid: videoRids[2 - i],
19097
- maxBitrate: videoEncoding.maxBitrate / Math.pow(3, i),
19110
+ maxBitrate: videoEncoding.maxBitrate,
19111
+ maxFramerate: original.encoding.maxFramerate,
19098
19112
  /* @ts-ignore */
19099
- maxFramerate: original.encoding.maxFramerate
19113
+ scalabilityMode: scalabilityMode
19100
19114
  });
19101
19115
  }
19102
- /* @ts-ignore */
19103
- encodings[0].scalabilityMode = scalabilityMode;
19104
- livekitLogger.debug('encodings', encodings);
19116
+ livekitLogger.debug("using svc encoding", {
19117
+ encodings
19118
+ });
19105
19119
  return encodings;
19106
19120
  }
19107
19121
  if (!useSimulcast) {
@@ -19125,7 +19139,7 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
19125
19139
  // to disable when CPU constrained.
19126
19140
  // So encodings should be ordered in increasing spatial
19127
19141
  // resolution order.
19128
- // 2. ion-sfu translates rids into layers. So, all encodings
19142
+ // 2. livekit-server translates rids into layers. So, all encodings
19129
19143
  // should have the base layer `q` and then more added
19130
19144
  // based on other conditions.
19131
19145
  const size = Math.max(width, height);
@@ -21520,9 +21534,19 @@ class LocalParticipant extends Participant {
21520
21534
  // for svc codecs, disable simulcast and use vp8 for backup codec
21521
21535
  if (track instanceof LocalVideoTrack) {
21522
21536
  if (isSVCCodec(videoCodec)) {
21523
- // vp9 svc with screenshare has problem to encode, always use L1T3 here
21524
- if (track.source === Track.Source.ScreenShare && videoCodec === 'vp9') {
21537
+ if (track.source === Track.Source.ScreenShare) {
21538
+ // vp9 svc with screenshare cannot encode multiple spatial layers
21539
+ // doing so reduces publish resolution to minimal resolution
21525
21540
  opts.scalabilityMode = 'L1T3';
21541
+ // Chrome does not allow more than 5 fps with L1T3, and it has encoding bugs with L3T3
21542
+ // It has a different path for screenshare handling and it seems to be untested/buggy
21543
+ // As a workaround, we are setting contentHint to force it to go through the same
21544
+ // path as regular camera video. While this is not optimal, it delivers the performance
21545
+ // that we need
21546
+ if ('contentHint' in track.mediaStreamTrack) {
21547
+ track.mediaStreamTrack.contentHint = 'motion';
21548
+ this.log.info('forcing contentHint to motion for screenshare with SVC codecs', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
21549
+ }
21526
21550
  }
21527
21551
  // set scalabilityMode to 'L3T3_KEY' by default
21528
21552
  opts.scalabilityMode = (_e = opts.scalabilityMode) !== null && _e !== void 0 ? _e : 'L3T3_KEY';
@@ -21621,7 +21645,8 @@ class LocalParticipant extends Participant {
21621
21645
  maxbr: ((_l = encodings[0]) === null || _l === void 0 ? void 0 : _l.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
21622
21646
  });
21623
21647
  }
21624
- } else if (track.codec && isSVCCodec(track.codec) && ((_m = encodings[0]) === null || _m === void 0 ? void 0 : _m.maxBitrate)) {
21648
+ } else if (track.codec && track.codec == 'av1' && ((_m = encodings[0]) === null || _m === void 0 ? void 0 : _m.maxBitrate)) {
21649
+ // AV1 requires setting x-start-bitrate in SDP
21625
21650
  this.engine.pcManager.publisher.setTrackCodecBitrate({
21626
21651
  cid: req.cid,
21627
21652
  codec: track.codec,
@@ -21629,6 +21654,19 @@ class LocalParticipant extends Participant {
21629
21654
  });
21630
21655
  }
21631
21656
  }
21657
+ if (track.kind === Track.Kind.Video && track.source === Track.Source.ScreenShare) {
21658
+ // a few of reasons we are forcing this setting without allowing overrides:
21659
+ // 1. without this, Chrome seems to aggressively resize the SVC video stating `quality-limitation: bandwidth` even when BW isn't an issue
21660
+ // 2. since we are overriding contentHint to motion (to workaround L1T3 publishing), it overrides the default degradationPreference to `balanced`
21661
+ try {
21662
+ this.log.debug("setting degradationPreference to maintain-resolution");
21663
+ const params = track.sender.getParameters();
21664
+ params.degradationPreference = 'maintain-resolution';
21665
+ yield track.sender.setParameters(params);
21666
+ } catch (e) {
21667
+ this.log.warn("failed to set degradationPreference: ".concat(e));
21668
+ }
21669
+ }
21632
21670
  yield this.engine.negotiate();
21633
21671
  if (track instanceof LocalVideoTrack) {
21634
21672
  track.startMonitor(this.engine.client);
@@ -22524,6 +22562,7 @@ class Room extends eventsExports.EventEmitter {
22524
22562
  }
22525
22563
  if (nextUrl) {
22526
22564
  this.log.info("Initial connection failed with ConnectionError: ".concat(e.message, ". Retrying with another region: ").concat(nextUrl), this.logContext);
22565
+ this.recreateEngine();
22527
22566
  yield connectFn(resolve, reject, nextUrl);
22528
22567
  } else {
22529
22568
  this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
@@ -24600,5 +24639,5 @@ function isFacingModeValue(item) {
24600
24639
  return item === undefined || allowedValues.includes(item);
24601
24640
  }
24602
24641
 
24603
- export { AudioPresets, BaseKeyProvider, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, NegotiationError, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, importKey, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isScriptTransformSupported, isVideoFrame, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
24642
+ export { AudioPresets, BaseKeyProvider, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, MediaDeviceFailure, NegotiationError, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, ScreenSharePresets, 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 };
24604
24643
  //# sourceMappingURL=livekit-client.esm.mjs.map