livekit-client 0.18.5 → 1.0.1

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 (60) hide show
  1. package/README.md +1 -1
  2. package/dist/api/SignalClient.d.ts +2 -2
  3. package/dist/api/SignalClient.d.ts.map +1 -1
  4. package/dist/index.d.ts +3 -4
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/livekit-client.esm.mjs +257 -254
  7. package/dist/livekit-client.esm.mjs.map +1 -1
  8. package/dist/livekit-client.umd.js +1 -1
  9. package/dist/livekit-client.umd.js.map +1 -1
  10. package/dist/options.d.ts +1 -68
  11. package/dist/options.d.ts.map +1 -1
  12. package/dist/room/DeviceManager.d.ts.map +1 -1
  13. package/dist/room/RTCEngine.d.ts +3 -2
  14. package/dist/room/RTCEngine.d.ts.map +1 -1
  15. package/dist/room/Room.d.ts +11 -7
  16. package/dist/room/Room.d.ts.map +1 -1
  17. package/dist/room/events.d.ts +6 -12
  18. package/dist/room/events.d.ts.map +1 -1
  19. package/dist/room/participant/LocalParticipant.d.ts.map +1 -1
  20. package/dist/room/participant/Participant.d.ts +0 -4
  21. package/dist/room/participant/Participant.d.ts.map +1 -1
  22. package/dist/room/participant/RemoteParticipant.d.ts +3 -2
  23. package/dist/room/participant/RemoteParticipant.d.ts.map +1 -1
  24. package/dist/room/track/RemoteVideoTrack.d.ts +24 -1
  25. package/dist/room/track/RemoteVideoTrack.d.ts.map +1 -1
  26. package/dist/room/track/Track.d.ts +2 -1
  27. package/dist/room/track/Track.d.ts.map +1 -1
  28. package/dist/room/track/options.d.ts +0 -30
  29. package/dist/room/track/options.d.ts.map +1 -1
  30. package/dist/room/track/types.d.ts +5 -0
  31. package/dist/room/track/types.d.ts.map +1 -1
  32. package/dist/test/MockMediaStreamTrack.d.ts +26 -0
  33. package/dist/test/MockMediaStreamTrack.d.ts.map +1 -0
  34. package/dist/version.d.ts +1 -1
  35. package/dist/version.d.ts.map +1 -1
  36. package/package.json +4 -3
  37. package/src/api/SignalClient.ts +32 -7
  38. package/src/index.ts +4 -3
  39. package/src/options.ts +0 -82
  40. package/src/room/DeviceManager.ts +4 -1
  41. package/src/room/RTCEngine.ts +16 -7
  42. package/src/room/Room.ts +66 -42
  43. package/src/room/events.ts +7 -14
  44. package/src/room/participant/LocalParticipant.ts +4 -0
  45. package/src/room/participant/Participant.ts +0 -5
  46. package/src/room/participant/RemoteParticipant.ts +16 -5
  47. package/src/room/participant/publishUtils.test.ts +2 -2
  48. package/src/room/track/LocalVideoTrack.ts +1 -1
  49. package/src/room/track/RemoteVideoTrack.test.ts +149 -0
  50. package/src/room/track/RemoteVideoTrack.ts +118 -39
  51. package/src/room/track/Track.ts +18 -2
  52. package/src/room/track/create.ts +1 -1
  53. package/src/room/track/options.ts +1 -31
  54. package/src/room/track/types.ts +5 -0
  55. package/src/room/track/utils.test.ts +6 -6
  56. package/src/test/MockMediaStreamTrack.ts +83 -0
  57. package/src/version.ts +1 -1
  58. package/dist/connect.d.ts +0 -24
  59. package/dist/connect.d.ts.map +0 -1
  60. package/src/connect.ts +0 -98
@@ -9260,10 +9260,15 @@ var RoomEvent;
9260
9260
  /**
9261
9261
  * Whenever the connection state of the room changes
9262
9262
  *
9263
- * args: ([[RoomState]])
9263
+ * args: ([[ConnectionState]])
9264
9264
  */
9265
9265
 
9266
- RoomEvent["StateChanged"] = "stateChanged";
9266
+ RoomEvent["ConnectionStateChanged"] = "connectionStateChanged";
9267
+ /**
9268
+ * @deprecated StateChanged has been renamed to ConnectionStateChanged
9269
+ */
9270
+
9271
+ RoomEvent["StateChanged"] = "connectionStateChanged";
9267
9272
  /**
9268
9273
  * When input or output devices on the machine have changed.
9269
9274
  */
@@ -9370,12 +9375,6 @@ var RoomEvent;
9370
9375
  */
9371
9376
 
9372
9377
  RoomEvent["ActiveSpeakersChanged"] = "activeSpeakersChanged";
9373
- /**
9374
- * @deprecated Use ParticipantMetadataChanged instead
9375
- * @internal
9376
- */
9377
-
9378
- RoomEvent["MetadataChanged"] = "metadataChanged";
9379
9378
  /**
9380
9379
  * Participant metadata is a simple way for app-specific state to be pushed to
9381
9380
  * all users.
@@ -9541,12 +9540,6 @@ var ParticipantEvent;
9541
9540
  */
9542
9541
 
9543
9542
  ParticipantEvent["LocalTrackUnpublished"] = "localTrackUnpublished";
9544
- /**
9545
- * @deprecated Use ParticipantMetadataChanged instead
9546
- * @internal
9547
- */
9548
-
9549
- ParticipantEvent["MetadataChanged"] = "metadataChanged";
9550
9543
  /**
9551
9544
  * Participant metadata is a simple way for app-specific state to be pushed to
9552
9545
  * all users.
@@ -9737,8 +9730,11 @@ class DeviceManager {
9737
9730
  video: kind !== 'audioinput' && kind !== 'audiooutput',
9738
9731
  audio: kind !== 'videoinput'
9739
9732
  };
9740
- await navigator.mediaDevices.getUserMedia(permissionsToAcquire);
9733
+ const stream = await navigator.mediaDevices.getUserMedia(permissionsToAcquire);
9741
9734
  devices = await navigator.mediaDevices.enumerateDevices();
9735
+ stream.getTracks().forEach(track => {
9736
+ track.stop();
9737
+ });
9742
9738
  }
9743
9739
  }
9744
9740
 
@@ -9783,7 +9779,7 @@ class DeviceManager {
9783
9779
  }
9784
9780
  DeviceManager.mediaDeviceKinds = ['audioinput', 'audiooutput', 'videoinput'];
9785
9781
 
9786
- const version = '0.18.5';
9782
+ const version = '1.0.1';
9787
9783
  const protocolVersion = 7;
9788
9784
 
9789
9785
  const separator = '|';
@@ -10336,6 +10332,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
10336
10332
  }
10337
10333
  }
10338
10334
 
10335
+ const BACKGROUND_REACTION_DELAY = 5000; // keep old audio elements when detached, we would re-use them since on iOS
10339
10336
  // Safari tracks which audio elements have been "blessed" by the user.
10340
10337
 
10341
10338
  const recycledElements = [];
@@ -10347,7 +10344,17 @@ class Track extends events.exports.EventEmitter {
10347
10344
  this._currentBitrate = 0;
10348
10345
 
10349
10346
  this.appVisibilityChangedListener = () => {
10350
- this.handleAppVisibilityChanged();
10347
+ if (this.backgroundTimeout) {
10348
+ clearTimeout(this.backgroundTimeout);
10349
+ } // delay app visibility update if it goes to hidden
10350
+ // update immediately if it comes back to focus
10351
+
10352
+
10353
+ if (document.visibilityState === 'hidden') {
10354
+ this.backgroundTimeout = setTimeout(() => this.handleAppVisibilityChanged(), BACKGROUND_REACTION_DELAY);
10355
+ } else {
10356
+ this.handleAppVisibilityChanged();
10357
+ }
10351
10358
  };
10352
10359
 
10353
10360
  this.kind = kind;
@@ -11256,7 +11263,7 @@ class LocalVideoTrack extends LocalTrack {
11256
11263
  bytesSent: v.bytesSent,
11257
11264
  framesSent: v.framesSent,
11258
11265
  timestamp: v.timestamp,
11259
- rid: (_a = v.rid) !== null && _a !== void 0 ? _a : '',
11266
+ rid: (_a = v.rid) !== null && _a !== void 0 ? _a : v.id,
11260
11267
  retransmittedPacketsSent: v.retransmittedPacketsSent,
11261
11268
  qualityLimitationReason: v.qualityLimitationReason,
11262
11269
  qualityLimitationResolutionChanges: v.qualityLimitationResolutionChanges
@@ -11641,6 +11648,7 @@ class RemoteVideoTrack extends RemoteTrack {
11641
11648
  constructor(mediaTrack, sid, receiver, adaptiveStreamSettings) {
11642
11649
  super(mediaTrack, sid, Track.Kind.Video, receiver);
11643
11650
  this.elementInfos = [];
11651
+ this.hasUsedAttach = false;
11644
11652
 
11645
11653
  this.monitorReceiver = async () => {
11646
11654
  if (!this.receiver) {
@@ -11660,21 +11668,6 @@ class RemoteVideoTrack extends RemoteTrack {
11660
11668
  }, monitorFrequency);
11661
11669
  };
11662
11670
 
11663
- this.handleVisibilityChanged = entry => {
11664
- const {
11665
- target,
11666
- isIntersecting
11667
- } = entry;
11668
- const elementInfo = this.elementInfos.find(info => info.element === target);
11669
-
11670
- if (elementInfo) {
11671
- elementInfo.visible = isIntersecting;
11672
- elementInfo.visibilityChangedAt = Date.now();
11673
- }
11674
-
11675
- this.updateVisibility();
11676
- };
11677
-
11678
11671
  this.debouncedHandleResize = r(() => {
11679
11672
  this.updateDimensions();
11680
11673
  }, REACTION_DELAY);
@@ -11690,8 +11683,8 @@ class RemoteVideoTrack extends RemoteTrack {
11690
11683
  }
11691
11684
 
11692
11685
  get mediaStreamTrack() {
11693
- if (this.isAdaptiveStream && this.attachedElements.length === 0) {
11694
- throw Error('When using adaptiveStream, you need to use remoteVideoTrack.attach() to add the track to a HTMLVideoElement, direct usage of mediaStreamTrack is unsupported in this case');
11686
+ if (this.isAdaptiveStream && !this.hasUsedAttach) {
11687
+ livekitLogger.warn('When using adaptiveStream, you need to use remoteVideoTrack.attach() to add the track to a HTMLVideoElement, otherwise your video tracks might never start');
11695
11688
  }
11696
11689
 
11697
11690
  return this._mediaStreamTrack;
@@ -11721,22 +11714,55 @@ class RemoteVideoTrack extends RemoteTrack {
11721
11714
 
11722
11715
 
11723
11716
  if (this.adaptiveStreamSettings && this.elementInfos.find(info => info.element === element) === undefined) {
11724
- this.elementInfos.push({
11725
- element,
11726
- visible: true // default visible
11717
+ const elementInfo = new HTMLElementInfo(element);
11718
+ this.observeElementInfo(elementInfo);
11719
+ }
11727
11720
 
11728
- });
11729
- element.handleResize = this.debouncedHandleResize;
11730
- element.handleVisibilityChanged = this.handleVisibilityChanged;
11731
- getIntersectionObserver().observe(element);
11732
- getResizeObserver().observe(element); // trigger the first resize update cycle
11721
+ this.hasUsedAttach = true;
11722
+ return element;
11723
+ }
11724
+ /**
11725
+ * Observe an ElementInfo for changes when adaptive streaming.
11726
+ * @param elementInfo
11727
+ * @internal
11728
+ */
11729
+
11730
+
11731
+ observeElementInfo(elementInfo) {
11732
+ if (this.adaptiveStreamSettings && this.elementInfos.find(info => info === elementInfo) === undefined) {
11733
+ elementInfo.handleResize = () => {
11734
+ this.debouncedHandleResize();
11735
+ };
11736
+
11737
+ elementInfo.handleVisibilityChanged = () => {
11738
+ this.updateVisibility();
11739
+ };
11740
+
11741
+ this.elementInfos.push(elementInfo);
11742
+ elementInfo.observe(); // trigger the first resize update cycle
11733
11743
  // if the tab is backgrounded, the initial resize event does not fire until
11734
11744
  // the tab comes into focus for the first time.
11735
11745
 
11736
11746
  this.debouncedHandleResize();
11747
+ this.updateVisibility();
11737
11748
  }
11749
+ }
11750
+ /**
11751
+ * Stop observing an ElementInfo for changes.
11752
+ * @param elementInfo
11753
+ * @internal
11754
+ */
11738
11755
 
11739
- return element;
11756
+
11757
+ stopObservingElementInfo(elementInfo) {
11758
+ const stopElementInfos = this.elementInfos.filter(info => info === elementInfo);
11759
+
11760
+ for (const info of stopElementInfos) {
11761
+ info.stopObserving();
11762
+ }
11763
+
11764
+ this.elementInfos = this.elementInfos.filter(info => info !== elementInfo);
11765
+ this.updateVisibility();
11740
11766
  }
11741
11767
 
11742
11768
  detach(element) {
@@ -11787,24 +11813,28 @@ class RemoteVideoTrack extends RemoteTrack {
11787
11813
  }
11788
11814
 
11789
11815
  stopObservingElement(element) {
11790
- var _a, _b;
11816
+ const stopElementInfos = this.elementInfos.filter(info => info.element === element);
11817
+
11818
+ for (const info of stopElementInfos) {
11819
+ info.stopObserving();
11820
+ }
11791
11821
 
11792
- (_a = getIntersectionObserver()) === null || _a === void 0 ? void 0 : _a.unobserve(element);
11793
- (_b = getResizeObserver()) === null || _b === void 0 ? void 0 : _b.unobserve(element);
11794
11822
  this.elementInfos = this.elementInfos.filter(info => info.element !== element);
11795
11823
  }
11796
11824
 
11797
11825
  async handleAppVisibilityChanged() {
11798
11826
  await super.handleAppVisibilityChanged();
11799
- if (!this.isAdaptiveStream) return; // on desktop don't pause when tab is backgrounded
11800
-
11801
- if (!isMobile()) return;
11827
+ if (!this.isAdaptiveStream) return;
11802
11828
  this.updateVisibility();
11803
11829
  }
11804
11830
 
11805
11831
  updateVisibility() {
11832
+ var _a, _b;
11833
+
11806
11834
  const lastVisibilityChange = this.elementInfos.reduce((prev, info) => Math.max(prev, info.visibilityChangedAt || 0), 0);
11807
- const isVisible = this.elementInfos.some(info => info.visible) && !this.isInBackground;
11835
+ const backgroundPause = ((_b = (_a = this.adaptiveStreamSettings) === null || _a === void 0 ? void 0 : _a.pauseVideoInBackground) !== null && _b !== void 0 ? _b : true // default to true
11836
+ ) ? this.isInBackground : false;
11837
+ const isVisible = this.elementInfos.some(info => info.visible) && !backgroundPause;
11808
11838
 
11809
11839
  if (this.lastVisible === isVisible) {
11810
11840
  return;
@@ -11831,8 +11861,8 @@ class RemoteVideoTrack extends RemoteTrack {
11831
11861
  for (const info of this.elementInfos) {
11832
11862
  const pixelDensity = (_b = (_a = this.adaptiveStreamSettings) === null || _a === void 0 ? void 0 : _a.pixelDensity) !== null && _b !== void 0 ? _b : 1;
11833
11863
  const pixelDensityValue = pixelDensity === 'screen' ? window.devicePixelRatio : pixelDensity;
11834
- const currentElementWidth = info.element.clientWidth * pixelDensityValue;
11835
- const currentElementHeight = info.element.clientHeight * pixelDensityValue;
11864
+ const currentElementWidth = info.width() * pixelDensityValue;
11865
+ const currentElementHeight = info.height() * pixelDensityValue;
11836
11866
 
11837
11867
  if (currentElementWidth + currentElementHeight > maxWidth + maxHeight) {
11838
11868
  maxWidth = currentElementWidth;
@@ -11853,6 +11883,59 @@ class RemoteVideoTrack extends RemoteTrack {
11853
11883
 
11854
11884
  }
11855
11885
 
11886
+ class HTMLElementInfo {
11887
+ constructor(element) {
11888
+ let visible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
11889
+
11890
+ this.onVisibilityChanged = entry => {
11891
+ var _a;
11892
+
11893
+ const {
11894
+ target,
11895
+ isIntersecting
11896
+ } = entry;
11897
+
11898
+ if (target === this.element) {
11899
+ this.visible = isIntersecting;
11900
+ this.visibilityChangedAt = Date.now();
11901
+ (_a = this.handleVisibilityChanged) === null || _a === void 0 ? void 0 : _a.call(this);
11902
+ }
11903
+ };
11904
+
11905
+ this.element = element;
11906
+ this.visible = visible;
11907
+ this.visibilityChangedAt = 0;
11908
+ }
11909
+
11910
+ width() {
11911
+ return this.element.clientWidth;
11912
+ }
11913
+
11914
+ height() {
11915
+ return this.element.clientWidth;
11916
+ }
11917
+
11918
+ observe() {
11919
+ this.element.handleResize = () => {
11920
+ var _a;
11921
+
11922
+ (_a = this.handleResize) === null || _a === void 0 ? void 0 : _a.call(this);
11923
+ };
11924
+
11925
+ this.element.handleVisibilityChanged = this.onVisibilityChanged;
11926
+ getIntersectionObserver().observe(this.element);
11927
+ getResizeObserver().observe(this.element);
11928
+ }
11929
+
11930
+ stopObserving() {
11931
+ var _a, _b;
11932
+
11933
+ (_a = getIntersectionObserver()) === null || _a === void 0 ? void 0 : _a.unobserve(this.element);
11934
+ (_b = getResizeObserver()) === null || _b === void 0 ? void 0 : _b.unobserve(this.element);
11935
+ }
11936
+
11937
+ }
11938
+
11856
11939
  class TrackPublication extends events.exports.EventEmitter {
11857
11940
  constructor(kind, id, name) {
11858
11941
  super();
@@ -12087,25 +12170,10 @@ const VideoPresets = {
12087
12170
  h216: new VideoPreset(384, 216, 180000, 15),
12088
12171
  h360: new VideoPreset(640, 360, 300000, 20),
12089
12172
  h540: new VideoPreset(960, 540, 600000, 25),
12090
- h720: new VideoPreset(1280, 720, 2000000, 30),
12173
+ h720: new VideoPreset(1280, 720, 1700000, 30),
12091
12174
  h1080: new VideoPreset(1920, 1080, 3000000, 30),
12092
12175
  h1440: new VideoPreset(2560, 1440, 5000000, 30),
12093
- h2160: new VideoPreset(3840, 2160, 8000000, 30),
12094
-
12095
- /** @deprecated */
12096
- qvga: new VideoPreset(320, 180, 120000, 10),
12097
-
12098
- /** @deprecated */
12099
- vga: new VideoPreset(640, 360, 300000, 20),
12100
-
12101
- /** @deprecated */
12102
- qhd: new VideoPreset(960, 540, 600000, 25),
12103
-
12104
- /** @deprecated */
12105
- hd: new VideoPreset(1280, 720, 2000000, 30),
12106
-
12107
- /** @deprecated */
12108
- fhd: new VideoPreset(1920, 1080, 3000000, 30)
12176
+ h2160: new VideoPreset(3840, 2160, 8000000, 30)
12109
12177
  };
12110
12178
  /**
12111
12179
  * Four by three presets
@@ -12120,44 +12188,14 @@ const VideoPresets43 = {
12120
12188
  h540: new VideoPreset(720, 540, 450000, 25),
12121
12189
  h720: new VideoPreset(960, 720, 1500000, 30),
12122
12190
  h1080: new VideoPreset(1440, 1080, 2500000, 30),
12123
- h1440: new VideoPreset(1920, 1440, 3500000, 30),
12124
-
12125
- /** @deprecated */
12126
- qvga: new VideoPreset(240, 180, 90000, 10),
12127
-
12128
- /** @deprecated */
12129
- vga: new VideoPreset(480, 360, 225000, 20),
12130
-
12131
- /** @deprecated */
12132
- qhd: new VideoPreset(720, 540, 450000, 25),
12133
-
12134
- /** @deprecated */
12135
- hd: new VideoPreset(960, 720, 1500000, 30),
12136
-
12137
- /** @deprecated */
12138
- fhd: new VideoPreset(1440, 1080, 2800000, 30)
12191
+ h1440: new VideoPreset(1920, 1440, 3500000, 30)
12139
12192
  };
12140
12193
  const ScreenSharePresets = {
12141
12194
  h360fps3: new VideoPreset(640, 360, 200000, 3),
12142
12195
  h720fps5: new VideoPreset(1280, 720, 400000, 5),
12143
12196
  h720fps15: new VideoPreset(1280, 720, 1000000, 15),
12144
12197
  h1080fps15: new VideoPreset(1920, 1080, 1500000, 15),
12145
- h1080fps30: new VideoPreset(1920, 1080, 3000000, 30),
12146
-
12147
- /** @deprecated */
12148
- vga: new VideoPreset(640, 360, 200000, 3),
12149
-
12150
- /** @deprecated */
12151
- hd_8: new VideoPreset(1280, 720, 400000, 5),
12152
-
12153
- /** @deprecated */
12154
- hd_15: new VideoPreset(1280, 720, 1000000, 15),
12155
-
12156
- /** @deprecated */
12157
- fhd_15: new VideoPreset(1920, 1080, 1500000, 15),
12158
-
12159
- /** @deprecated */
12160
- fhd_30: new VideoPreset(1920, 1080, 3000000, 30)
12198
+ h1080fps30: new VideoPreset(1920, 1080, 3000000, 30)
12161
12199
  };
12162
12200
 
12163
12201
  var ConnectionQuality;
@@ -12315,7 +12353,6 @@ class Participant extends events.exports.EventEmitter {
12315
12353
  this.metadata = md;
12316
12354
 
12317
12355
  if (changed) {
12318
- this.emit(ParticipantEvent.MetadataChanged, prevMetadata);
12319
12356
  this.emit(ParticipantEvent.ParticipantMetadataChanged, prevMetadata);
12320
12357
  }
12321
12358
  }
@@ -12907,29 +12944,32 @@ class RemoteParticipant extends Participant {
12907
12944
  }
12908
12945
  }
12909
12946
  /**
12910
- * sets the volume on the participant's microphone track if it exists.
12947
+ * sets the volume on the participant's microphone track
12948
+ * if no track exists the volume will be applied when the microphone track is added
12911
12949
  */
12912
12950
 
12913
12951
 
12914
12952
  setVolume(volume) {
12953
+ this.volume = volume;
12915
12954
  const audioPublication = this.getTrack(Track.Source.Microphone);
12916
12955
 
12917
- if (audioPublication) {
12956
+ if (audioPublication && audioPublication.track) {
12918
12957
  audioPublication.track.setVolume(volume);
12919
12958
  }
12920
12959
  }
12921
12960
  /**
12922
12961
  * gets the volume on the participant's microphone track
12923
- * returns undefined if no microphone track exists
12924
12962
  */
12925
12963
 
12926
12964
 
12927
12965
  getVolume() {
12928
12966
  const audioPublication = this.getTrack(Track.Source.Microphone);
12929
12967
 
12930
- if (audioPublication) {
12968
+ if (audioPublication && audioPublication.track) {
12931
12969
  return audioPublication.track.getVolume();
12932
12970
  }
12971
+
12972
+ return this.volume;
12933
12973
  }
12934
12974
  /** @internal */
12935
12975
 
@@ -12985,7 +13025,12 @@ class RemoteParticipant extends Participant {
12985
13025
  track.isMuted = publication.isMuted;
12986
13026
  track.setMediaStream(mediaStream);
12987
13027
  track.start();
12988
- publication.setTrack(track);
13028
+ publication.setTrack(track); // set participant volume on new microphone tracks
13029
+
13030
+ if (this.volume !== undefined && track instanceof RemoteAudioTrack && track.source === Track.Source.Microphone) {
13031
+ track.setVolume(this.volume);
13032
+ }
13033
+
12989
13034
  this.emit(ParticipantEvent.TrackSubscribed, track, publication);
12990
13035
  return publication;
12991
13036
  }
@@ -13590,6 +13635,10 @@ class LocalParticipant extends Participant {
13590
13635
  }];
13591
13636
  }
13592
13637
 
13638
+ if (!this.engine || this.engine.isClosed) {
13639
+ throw new UnexpectedConnectionState('cannot publish track when not connected');
13640
+ }
13641
+
13593
13642
  const ti = await this.engine.addTrack(req);
13594
13643
  const publication = new LocalTrackPublication(track.kind, ti, track);
13595
13644
  track.sid = ti.sid;
@@ -17439,7 +17488,7 @@ class SignalClient {
17439
17488
  this.requestQueue = new Queue();
17440
17489
  }
17441
17490
 
17442
- async join(url, token, opts) {
17491
+ async join(url, token, opts, abortSignal) {
17443
17492
  // during a full reconnect, we'd want to start the sequence even if currently
17444
17493
  // connected
17445
17494
  this.isConnected = false;
@@ -17447,7 +17496,7 @@ class SignalClient {
17447
17496
  autoSubscribe: opts === null || opts === void 0 ? void 0 : opts.autoSubscribe,
17448
17497
  publishOnly: opts === null || opts === void 0 ? void 0 : opts.publishOnly,
17449
17498
  adaptiveStream: opts === null || opts === void 0 ? void 0 : opts.adaptiveStream
17450
- });
17499
+ }, abortSignal);
17451
17500
  return res;
17452
17501
  }
17453
17502
 
@@ -17458,7 +17507,7 @@ class SignalClient {
17458
17507
  });
17459
17508
  }
17460
17509
 
17461
- connect(url, token, opts) {
17510
+ connect(url, token, opts, abortSignal) {
17462
17511
  if (url.startsWith('http')) {
17463
17512
  url = url.replace('http', 'ws');
17464
17513
  } // strip trailing slash
@@ -17469,6 +17518,17 @@ class SignalClient {
17469
17518
  const clientInfo = getClientInfo();
17470
17519
  const params = createConnectionParams(token, clientInfo, opts);
17471
17520
  return new Promise((resolve, reject) => {
17521
+ const abortHandler = () => {
17522
+ ws.close();
17523
+ this.close();
17524
+ reject(new ConnectionError('room connection has been cancelled'));
17525
+ };
17526
+
17527
+ if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) {
17528
+ abortHandler();
17529
+ }
17530
+
17531
+ abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.addEventListener('abort', abortHandler);
17472
17532
  livekitLogger.debug("connecting to ".concat(url + params));
17473
17533
  this.ws = undefined;
17474
17534
  const ws = new WebSocket(url + params);
@@ -17524,6 +17584,7 @@ class SignalClient {
17524
17584
  // handle join message only
17525
17585
  if (msg.join) {
17526
17586
  this.isConnected = true;
17587
+ abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', abortHandler);
17527
17588
  resolve(msg.join);
17528
17589
  } else {
17529
17590
  reject(new ConnectionError('did not receive join response'));
@@ -17946,7 +18007,7 @@ class RTCEngine extends events.exports.EventEmitter {
17946
18007
  this.rtcConfig = {};
17947
18008
  this.subscriberPrimary = false;
17948
18009
  this.pcState = PCState.New;
17949
- this.isClosed = true;
18010
+ this._isClosed = true;
17950
18011
  this.pendingTrackResolvers = {}; // true if publisher connection has already been established.
17951
18012
  // this is helpful to know if we need to restart ICE on the publisher connection
17952
18013
 
@@ -18017,7 +18078,7 @@ class RTCEngine extends events.exports.EventEmitter {
18017
18078
 
18018
18079
 
18019
18080
  this.handleDisconnect = connection => {
18020
- if (this.isClosed) {
18081
+ if (this._isClosed) {
18021
18082
  return;
18022
18083
  }
18023
18084
 
@@ -18032,7 +18093,7 @@ class RTCEngine extends events.exports.EventEmitter {
18032
18093
  setTimeout(async () => {
18033
18094
  var _a;
18034
18095
 
18035
- if (this.isClosed) {
18096
+ if (this._isClosed) {
18036
18097
  return;
18037
18098
  }
18038
18099
 
@@ -18085,12 +18146,16 @@ class RTCEngine extends events.exports.EventEmitter {
18085
18146
  this.client = new SignalClient();
18086
18147
  }
18087
18148
 
18088
- async join(url, token, opts) {
18149
+ get isClosed() {
18150
+ return this._isClosed;
18151
+ }
18152
+
18153
+ async join(url, token, opts, abortSignal) {
18089
18154
  this.url = url;
18090
18155
  this.token = token;
18091
18156
  this.signalOpts = opts;
18092
- const joinResponse = await this.client.join(url, token, opts);
18093
- this.isClosed = false;
18157
+ const joinResponse = await this.client.join(url, token, opts, abortSignal);
18158
+ this._isClosed = false;
18094
18159
  this.subscriberPrimary = joinResponse.subscriberPrimary;
18095
18160
 
18096
18161
  if (!this.publisher) {
@@ -18107,7 +18172,7 @@ class RTCEngine extends events.exports.EventEmitter {
18107
18172
  }
18108
18173
 
18109
18174
  close() {
18110
- this.isClosed = true;
18175
+ this._isClosed = true;
18111
18176
  this.removeAllListeners();
18112
18177
 
18113
18178
  if (this.publisher && this.publisher.pc.signalingState !== 'closed') {
@@ -18617,13 +18682,18 @@ const videoDefaults = {
18617
18682
  resolution: VideoPresets.h720.resolution
18618
18683
  };
18619
18684
 
18620
- var RoomState;
18685
+ var ConnectionState;
18686
+
18687
+ (function (ConnectionState) {
18688
+ ConnectionState["Disconnected"] = "disconnected";
18689
+ ConnectionState["Connecting"] = "connecting";
18690
+ ConnectionState["Connected"] = "connected";
18691
+ ConnectionState["Reconnecting"] = "reconnecting";
18692
+ })(ConnectionState || (ConnectionState = {}));
18693
+ /** @deprecated RoomState has been renamed to [[ConnectionState]] */
18621
18694
 
18622
- (function (RoomState) {
18623
- RoomState["Disconnected"] = "disconnected";
18624
- RoomState["Connected"] = "connected";
18625
- RoomState["Reconnecting"] = "reconnecting";
18626
- })(RoomState || (RoomState = {}));
18695
+
18696
+ const RoomState = ConnectionState;
18627
18697
  /**
18628
18698
  * In LiveKit, a room is the logical grouping for a list of participants.
18629
18699
  * Participants in a room can publish tracks, and subscribe to others' tracks.
@@ -18633,7 +18703,6 @@ var RoomState;
18633
18703
  * @noInheritDoc
18634
18704
  */
18635
18705
 
18636
-
18637
18706
  class Room extends events.exports.EventEmitter {
18638
18707
  /**
18639
18708
  * Creates a new Room, the primary construct for a LiveKit session.
@@ -18646,7 +18715,7 @@ class Room extends events.exports.EventEmitter {
18646
18715
 
18647
18716
  super();
18648
18717
  _this = this;
18649
- this.state = RoomState.Disconnected;
18718
+ this.state = ConnectionState.Disconnected;
18650
18719
  /**
18651
18720
  * list of participants that are actively speaking. when this changes
18652
18721
  * a [[RoomEvent.ActiveSpeakersChanged]] event is fired
@@ -18669,9 +18738,15 @@ class Room extends events.exports.EventEmitter {
18669
18738
  var _a, _b; // guard against calling connect
18670
18739
 
18671
18740
 
18672
- if (this.state !== RoomState.Disconnected) {
18741
+ if (this.state !== ConnectionState.Disconnected) {
18673
18742
  livekitLogger.warn("already connected to room ".concat(this.name));
18674
18743
  return;
18744
+ }
18745
+
18746
+ this.setAndEmitConnectionState(ConnectionState.Connecting);
18747
+
18748
+ if (!this.abortController || this.abortController.signal.aborted) {
18749
+ this.abortController = new AbortController();
18675
18750
  } // recreate engine if previously disconnected
18676
18751
 
18677
18752
 
@@ -18689,7 +18764,7 @@ class Room extends events.exports.EventEmitter {
18689
18764
  autoSubscribe: opts === null || opts === void 0 ? void 0 : opts.autoSubscribe,
18690
18765
  publishOnly: opts === null || opts === void 0 ? void 0 : opts.publishOnly,
18691
18766
  adaptiveStream: typeof ((_a = this.options) === null || _a === void 0 ? void 0 : _a.adaptiveStream) === 'object' ? true : (_b = this.options) === null || _b === void 0 ? void 0 : _b.adaptiveStream
18692
- });
18767
+ }, this.abortController.signal);
18693
18768
  livekitLogger.debug("connected to Livekit Server version: ".concat(joinResponse.serverVersion, ", region: ").concat(joinResponse.serverRegion));
18694
18769
 
18695
18770
  if (!joinResponse.serverVersion) {
@@ -18702,15 +18777,12 @@ class Room extends events.exports.EventEmitter {
18702
18777
  this.options.dynacast = false;
18703
18778
  }
18704
18779
 
18705
- this.state = RoomState.Connected;
18706
18780
  const pi = joinResponse.participant;
18707
18781
  this.localParticipant.sid = pi.sid;
18708
18782
  this.localParticipant.identity = pi.identity;
18709
18783
  this.localParticipant.updateInfo(pi); // forward metadata changed for the local participant
18710
18784
 
18711
- this.localParticipant.on(ParticipantEvent.MetadataChanged, metadata => {
18712
- this.emit(RoomEvent.MetadataChanged, metadata, this.localParticipant);
18713
- }).on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
18785
+ this.localParticipant.on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
18714
18786
  this.emit(RoomEvent.ParticipantMetadataChanged, metadata, this.localParticipant);
18715
18787
  }).on(ParticipantEvent.TrackMuted, pub => {
18716
18788
  this.emit(RoomEvent.TrackMuted, pub, this.localParticipant);
@@ -18734,29 +18806,48 @@ class Room extends events.exports.EventEmitter {
18734
18806
  this.name = joinResponse.room.name;
18735
18807
  this.sid = joinResponse.room.sid;
18736
18808
  this.metadata = joinResponse.room.metadata;
18737
- this.emit(RoomEvent.StateChanged, this.state);
18738
18809
  } catch (err) {
18739
18810
  this.engine.close();
18811
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
18740
18812
  throw err;
18741
18813
  } // don't return until ICE connected
18742
18814
 
18743
18815
 
18744
18816
  return new Promise((resolve, reject) => {
18817
+ var _a, _b;
18818
+
18745
18819
  const connectTimeout = setTimeout(() => {
18746
18820
  // timeout
18747
18821
  this.engine.close();
18822
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
18748
18823
  reject(new ConnectionError('could not connect after timeout'));
18749
18824
  }, maxICEConnectTimeout);
18825
+
18826
+ const abortHandler = () => {
18827
+ livekitLogger.warn('closing engine');
18828
+ clearTimeout(connectTimeout);
18829
+ this.engine.close();
18830
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
18831
+ reject(new ConnectionError('room connection has been cancelled'));
18832
+ };
18833
+
18834
+ if ((_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
18835
+ abortHandler();
18836
+ }
18837
+
18838
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.signal.addEventListener('abort', abortHandler);
18750
18839
  this.engine.once(EngineEvent.Connected, () => {
18751
- var _a;
18840
+ var _a, _b;
18752
18841
 
18753
- clearTimeout(connectTimeout); // also hook unload event
18842
+ clearTimeout(connectTimeout);
18843
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.removeEventListener('abort', abortHandler); // also hook unload event
18754
18844
 
18755
18845
  if (isWeb()) {
18756
18846
  window.addEventListener('beforeunload', this.onBeforeUnload);
18757
- (_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.addEventListener('devicechange', this.handleDeviceChange);
18847
+ (_b = navigator.mediaDevices) === null || _b === void 0 ? void 0 : _b.addEventListener('devicechange', this.handleDeviceChange);
18758
18848
  }
18759
18849
 
18850
+ this.setAndEmitConnectionState(ConnectionState.Connected);
18760
18851
  resolve(this);
18761
18852
  });
18762
18853
  });
@@ -18769,7 +18860,16 @@ class Room extends events.exports.EventEmitter {
18769
18860
  this.disconnect = function () {
18770
18861
  let stopTracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
18771
18862
 
18772
- // send leave
18863
+ var _a;
18864
+
18865
+ if (_this.state === ConnectionState.Connecting) {
18866
+ // try aborting pending connection attempt
18867
+ livekitLogger.warn('abort connection attempt');
18868
+ (_a = _this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
18869
+ return;
18870
+ } // send leave
18871
+
18872
+
18773
18873
  if (_this.engine) {
18774
18874
  _this.engine.client.sendLeave();
18775
18875
 
@@ -18788,9 +18888,8 @@ class Room extends events.exports.EventEmitter {
18788
18888
  };
18789
18889
 
18790
18890
  this.handleRestarting = () => {
18791
- this.state = RoomState.Reconnecting;
18792
- this.emit(RoomEvent.Reconnecting);
18793
- this.emit(RoomEvent.StateChanged, this.state); // also unwind existing participants & existing subscriptions
18891
+ this.setAndEmitConnectionState(ConnectionState.Reconnecting);
18892
+ this.emit(RoomEvent.Reconnecting); // also unwind existing participants & existing subscriptions
18794
18893
 
18795
18894
  for (const p of this.participants.values()) {
18796
18895
  this.handleParticipantDisconnected(p.sid, p);
@@ -18799,9 +18898,8 @@ class Room extends events.exports.EventEmitter {
18799
18898
 
18800
18899
  this.handleRestarted = async joinResponse => {
18801
18900
  livekitLogger.debug("reconnected to server region ".concat(joinResponse.serverRegion));
18802
- this.state = RoomState.Connected;
18803
- this.emit(RoomEvent.Reconnected);
18804
- this.emit(RoomEvent.StateChanged, this.state); // rehydrate participants
18901
+ this.setAndEmitConnectionState(ConnectionState.Connected);
18902
+ this.emit(RoomEvent.Reconnected); // rehydrate participants
18805
18903
 
18806
18904
  if (joinResponse.participant) {
18807
18905
  // with a restart, the sid will have changed, we'll map our understanding to it
@@ -19043,16 +19141,14 @@ class Room extends events.exports.EventEmitter {
19043
19141
  }).on(EngineEvent.Disconnected, () => {
19044
19142
  this.handleDisconnect();
19045
19143
  }).on(EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate).on(EngineEvent.DataPacketReceived, this.handleDataPacket).on(EngineEvent.Resuming, () => {
19046
- this.state = RoomState.Reconnecting;
19144
+ this.setAndEmitConnectionState(ConnectionState.Reconnecting);
19047
19145
  this.emit(RoomEvent.Reconnecting);
19048
- this.emit(RoomEvent.StateChanged, this.state);
19049
19146
  }).on(EngineEvent.Resumed, () => {
19050
- this.state = RoomState.Connected;
19147
+ this.setAndEmitConnectionState(ConnectionState.Connected);
19051
19148
  this.emit(RoomEvent.Reconnected);
19052
- this.emit(RoomEvent.StateChanged, this.state);
19053
19149
  this.updateSubscriptions();
19054
19150
  }).on(EngineEvent.SignalResumed, () => {
19055
- if (this.state === RoomState.Reconnecting) {
19151
+ if (this.state === ConnectionState.Reconnecting) {
19056
19152
  this.sendSyncState();
19057
19153
  }
19058
19154
  }).on(EngineEvent.Restarting, this.handleRestarting).on(EngineEvent.Restarted, this.handleRestarted);
@@ -19238,10 +19334,6 @@ class Room extends events.exports.EventEmitter {
19238
19334
 
19239
19335
  var _a;
19240
19336
 
19241
- if (this.state === RoomState.Disconnected) {
19242
- return;
19243
- }
19244
-
19245
19337
  this.participants.forEach(p => {
19246
19338
  p.tracks.forEach(pub => {
19247
19339
  p.unpublishTrack(pub.trackSid);
@@ -19251,7 +19343,7 @@ class Room extends events.exports.EventEmitter {
19251
19343
  var _a, _b;
19252
19344
 
19253
19345
  if (pub.track) {
19254
- this.localParticipant.unpublishTrack(pub.track);
19346
+ this.localParticipant.unpublishTrack(pub.track, shouldStopTracks);
19255
19347
  }
19256
19348
 
19257
19349
  if (shouldStopTracks) {
@@ -19272,9 +19364,8 @@ class Room extends events.exports.EventEmitter {
19272
19364
  (_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.removeEventListener('devicechange', this.handleDeviceChange);
19273
19365
  }
19274
19366
 
19275
- this.state = RoomState.Disconnected;
19367
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
19276
19368
  this.emit(RoomEvent.Disconnected);
19277
- this.emit(RoomEvent.StateChanged, this.state);
19278
19369
  }
19279
19370
 
19280
19371
  handleParticipantDisconnected(sid, participant) {
@@ -19349,8 +19440,6 @@ class Room extends events.exports.EventEmitter {
19349
19440
  this.emit(RoomEvent.TrackMuted, pub, participant);
19350
19441
  }).on(ParticipantEvent.TrackUnmuted, pub => {
19351
19442
  this.emit(RoomEvent.TrackUnmuted, pub, participant);
19352
- }).on(ParticipantEvent.MetadataChanged, metadata => {
19353
- this.emit(RoomEvent.MetadataChanged, metadata, participant);
19354
19443
  }).on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
19355
19444
  this.emit(RoomEvent.ParticipantMetadataChanged, metadata, participant);
19356
19445
  }).on(ParticipantEvent.ConnectionQualityChanged, quality => {
@@ -19412,6 +19501,15 @@ class Room extends events.exports.EventEmitter {
19412
19501
  }
19413
19502
  }
19414
19503
  }
19504
+ }
19505
+
19506
+ setAndEmitConnectionState(state) {
19507
+ if (state === this.state) {
19508
+ return;
19509
+ }
19510
+
19511
+ this.state = state;
19512
+ this.emit(RoomEvent.ConnectionStateChanged, this.state);
19415
19513
  } // /** @internal */
19416
19514
 
19417
19515
 
@@ -19429,101 +19527,6 @@ class Room extends events.exports.EventEmitter {
19429
19527
 
19430
19528
  }
19431
19529
 
19432
- /**
19433
- * @deprecated Use room.connect() instead
19434
- *
19435
- * Connects to a LiveKit room, shorthand for `new Room()` and [[Room.connect]]
19436
- *
19437
- * ```typescript
19438
- * connect('wss://myhost.livekit.io', token, {
19439
- * // publish audio and video tracks on joining
19440
- * audio: true,
19441
- * video: true,
19442
- * captureDefaults: {
19443
- * facingMode: 'user',
19444
- * },
19445
- * })
19446
- * ```
19447
- * @param url URL to LiveKit server
19448
- * @param token AccessToken, a JWT token that includes authentication and room details
19449
- * @param options
19450
- */
19451
-
19452
- async function connect(url, token, options) {
19453
- var _a, _b, _c, _d;
19454
-
19455
- options !== null && options !== void 0 ? options : options = {};
19456
-
19457
- if (options.adaptiveStream === undefined) {
19458
- options.adaptiveStream = options.autoManageVideo === true ? {} : undefined;
19459
- }
19460
-
19461
- setLogLevel((_a = options.logLevel) !== null && _a !== void 0 ? _a : LogLevel.warn);
19462
- const config = (_b = options.rtcConfig) !== null && _b !== void 0 ? _b : {};
19463
-
19464
- if (options.iceServers) {
19465
- config.iceServers = options.iceServers;
19466
- }
19467
-
19468
- const room = new Room(options); // connect to room
19469
-
19470
- await room.connect(url, token, options);
19471
- const publishAudio = (_c = options.audio) !== null && _c !== void 0 ? _c : false;
19472
- const publishVideo = (_d = options.video) !== null && _d !== void 0 ? _d : false;
19473
-
19474
- if (publishAudio || publishVideo) {
19475
- setTimeout(async () => {
19476
- // if publishing both
19477
- let err;
19478
-
19479
- if (publishAudio && publishVideo) {
19480
- try {
19481
- await room.localParticipant.enableCameraAndMicrophone();
19482
- } catch (e) {
19483
- const errKind = MediaDeviceFailure.getFailure(e);
19484
- livekitLogger.warn('received error while creating media', {
19485
- error: errKind
19486
- });
19487
-
19488
- if (e instanceof Error) {
19489
- livekitLogger.warn(e.message);
19490
- } // when it's a device issue, try to publish the other kind
19491
-
19492
-
19493
- if (errKind === MediaDeviceFailure.NotFound || errKind === MediaDeviceFailure.DeviceInUse) {
19494
- try {
19495
- await room.localParticipant.setMicrophoneEnabled(true);
19496
- } catch (audioErr) {
19497
- err = audioErr;
19498
- }
19499
- } else {
19500
- err = e;
19501
- }
19502
- }
19503
- } else if (publishAudio) {
19504
- try {
19505
- await room.localParticipant.setMicrophoneEnabled(true);
19506
- } catch (e) {
19507
- err = e;
19508
- }
19509
- } else if (publishVideo) {
19510
- try {
19511
- await room.localParticipant.setCameraEnabled(true);
19512
- } catch (e) {
19513
- err = e;
19514
- }
19515
- }
19516
-
19517
- if (err) {
19518
- room.emit(RoomEvent.MediaDevicesError, err);
19519
- livekitLogger.error('could not create media', err);
19520
- }
19521
- });
19522
- }
19523
-
19524
- return room;
19525
- }
19526
-
19527
19530
  /**
19528
19531
  * Creates a local video and audio track at the same time. When acquiring both
19529
19532
  * audio and video tracks together, it'll display a single permission prompt to
@@ -19597,7 +19600,7 @@ async function createLocalScreenTracks(options) {
19597
19600
  }
19598
19601
 
19599
19602
  if (options.resolution === undefined) {
19600
- options.resolution = VideoPresets.fhd.resolution;
19603
+ options.resolution = VideoPresets.h1080.resolution;
19601
19604
  }
19602
19605
 
19603
19606
  let videoConstraints = true;
@@ -19634,5 +19637,5 @@ async function createLocalScreenTracks(options) {
19634
19637
  return localTracks;
19635
19638
  }
19636
19639
 
19637
- export { AudioPresets, ConnectionError, ConnectionQuality, DataPacket_Kind, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, connect, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, protocolVersion, setLogExtension, setLogLevel, version };
19640
+ export { AudioPresets, ConnectionError, ConnectionQuality, ConnectionState, DataPacket_Kind, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, protocolVersion, setLogExtension, setLogLevel, version };
19638
19641
  //# sourceMappingURL=livekit-client.esm.mjs.map