@stream-io/video-client 0.4.4 → 0.4.6

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
4
 
5
+ ### [0.4.6](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.4.5...@stream-io/video-client-0.4.6) (2023-11-13)
6
+
7
+
8
+ ### Features
9
+
10
+ * handle device disconnection ([#1174](https://github.com/GetStream/stream-video-js/issues/1174)) ([ae3779f](https://github.com/GetStream/stream-video-js/commit/ae3779fbfd820d8ef85ad58dafb698e06c00a3e3))
11
+
12
+ ### [0.4.5](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.4.4...@stream-io/video-client-0.4.5) (2023-11-07)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * lift the debug helpers from the SDK to Pronto ([#1182](https://github.com/GetStream/stream-video-js/issues/1182)) ([8f31efc](https://github.com/GetStream/stream-video-js/commit/8f31efc71d9f85ef147d21b42f23876599c36072))
18
+
5
19
  ### [0.4.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-0.4.3...@stream-io/video-client-0.4.4) (2023-11-02)
6
20
 
7
21
 
@@ -4,7 +4,7 @@ import { ServiceType, stackIntercept } from '@protobuf-ts/runtime-rpc';
4
4
  import axios, { AxiosHeaders } from 'axios';
5
5
  export { AxiosError } from 'axios';
6
6
  import { TwirpFetchTransport } from '@protobuf-ts/twirp-transport';
7
- import { ReplaySubject, combineLatest, BehaviorSubject, map as map$1, shareReplay, distinctUntilChanged, takeWhile, distinctUntilKeyChanged, filter, pairwise, merge, Observable, debounceTime, concatMap, from, of, tap, debounce, timer } from 'rxjs';
7
+ import { ReplaySubject, combineLatest, BehaviorSubject, map as map$1, shareReplay, distinctUntilChanged, takeWhile, distinctUntilKeyChanged, merge, from, Observable, debounceTime, concatMap, pairwise, of, filter, tap, debounce, timer } from 'rxjs';
8
8
  import * as SDP from 'sdp-transform';
9
9
  import { UAParser } from 'ua-parser-js';
10
10
  import WebSocket from 'isomorphic-ws';
@@ -9137,19 +9137,6 @@ const doJoin = async (httpClient, type, id, data) => {
9137
9137
  ...data,
9138
9138
  location,
9139
9139
  };
9140
- // FIXME OL: remove this once cascading is enabled by default
9141
- const cascadingModeParams = getCascadingModeParams();
9142
- if (cascadingModeParams) {
9143
- // FIXME OL: remove after SFU migration is done
9144
- if (data?.migrating_from && cascadingModeParams['next_sfu_id']) {
9145
- cascadingModeParams['sfu_id'] = cascadingModeParams['next_sfu_id'];
9146
- }
9147
- return httpClient.doAxiosRequest('post', `/call/${type}/${id}/join`, request, {
9148
- params: {
9149
- ...cascadingModeParams,
9150
- },
9151
- });
9152
- }
9153
9140
  return httpClient.post(`/call/${type}/${id}/join`, request);
9154
9141
  };
9155
9142
  const toRtcConfiguration = (config) => {
@@ -9164,20 +9151,6 @@ const toRtcConfiguration = (config) => {
9164
9151
  };
9165
9152
  return rtcConfig;
9166
9153
  };
9167
- const getCascadingModeParams = () => {
9168
- if (typeof window === 'undefined')
9169
- return null;
9170
- const params = new URLSearchParams(window.location?.search);
9171
- const cascadingEnabled = params.get('cascading') !== null;
9172
- if (cascadingEnabled) {
9173
- const rawParams = {};
9174
- params.forEach((value, key) => {
9175
- rawParams[key] = value;
9176
- });
9177
- return rawParams;
9178
- }
9179
- return null;
9180
- };
9181
9154
  /**
9182
9155
  * Reconciles the local state of the source participant into the target participant.
9183
9156
  *
@@ -10005,8 +9978,7 @@ const getDevices = (constraints, kind) => {
10005
9978
  /**
10006
9979
  * [Tells if the browser supports audio output change on 'audio' elements](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId).
10007
9980
  *
10008
- * @angular It's recommended to use the [`DeviceManagerService`](./DeviceManagerService.md) for a higher level API, use this low-level method only if the `DeviceManagerService` doesn't suit your requirements.
10009
- */
9981
+ * */
10010
9982
  const checkIfAudioOutputChangeSupported = () => {
10011
9983
  if (typeof document === 'undefined')
10012
9984
  return false;
@@ -10166,90 +10138,10 @@ const getScreenShareStream = async (options) => {
10166
10138
  throw e;
10167
10139
  }
10168
10140
  };
10169
- const watchForDisconnectedDevice = (kind, deviceId$) => {
10170
- let devices$;
10171
- switch (kind) {
10172
- case 'audioinput':
10173
- devices$ = getAudioDevices();
10174
- break;
10175
- case 'videoinput':
10176
- devices$ = getVideoDevices();
10177
- break;
10178
- case 'audiooutput':
10179
- devices$ = getAudioOutputDevices();
10180
- break;
10181
- }
10182
- return combineLatest([devices$, deviceId$]).pipe(filter(([devices, deviceId]) => !!deviceId && !devices.find((d) => d.deviceId === deviceId)), map$1(() => true));
10183
- };
10184
- /**
10185
- * Notifies the subscriber if a given 'audioinput' device is disconnected
10186
- *
10187
- * @angular It's recommended to use the [`DeviceManagerService`](./DeviceManagerService.md) for a higher level API, use this low-level method only if the `DeviceManagerService` doesn't suit your requirements.
10188
- * @param deviceId$ an Observable that specifies which device to watch for
10189
- * @returns
10190
- */
10191
- const watchForDisconnectedAudioDevice = (deviceId$) => {
10192
- return watchForDisconnectedDevice('audioinput', deviceId$);
10193
- };
10194
- /**
10195
- * Notifies the subscriber if a given 'videoinput' device is disconnected
10196
- *
10197
- * @angular It's recommended to use the [`DeviceManagerService`](./DeviceManagerService.md) for a higher level API, use this low-level method only if the `DeviceManagerService` doesn't suit your requirements.
10198
- * @param deviceId$ an Observable that specifies which device to watch for
10199
- * @returns
10200
- */
10201
- const watchForDisconnectedVideoDevice = (deviceId$) => {
10202
- return watchForDisconnectedDevice('videoinput', deviceId$);
10203
- };
10204
- /**
10205
- * Notifies the subscriber if a given 'audiooutput' device is disconnected
10206
- *
10207
- * @angular It's recommended to use the [`DeviceManagerService`](./DeviceManagerService.md) for a higher level API, use this low-level method only if the `DeviceManagerService` doesn't suit your requirements.
10208
- * @param deviceId$ an Observable that specifies which device to watch for
10209
- * @returns
10210
- */
10211
- const watchForDisconnectedAudioOutputDevice = (deviceId$) => {
10212
- return watchForDisconnectedDevice('audiooutput', deviceId$);
10213
- };
10214
- const watchForAddedDefaultDevice = (kind) => {
10215
- let devices$;
10216
- switch (kind) {
10217
- case 'audioinput':
10218
- devices$ = getAudioDevices();
10219
- break;
10220
- case 'videoinput':
10221
- devices$ = getVideoDevices();
10222
- break;
10223
- case 'audiooutput':
10224
- devices$ = getAudioOutputDevices();
10225
- break;
10226
- default:
10227
- throw new Error('Unknown MediaDeviceKind', kind);
10228
- }
10229
- return devices$.pipe(pairwise(), filter(([prev, current]) => {
10230
- const prevDefault = prev.find((device) => device.deviceId === 'default');
10231
- const currentDefault = current.find((device) => device.deviceId === 'default');
10232
- return !!(current.length > prev.length &&
10233
- prevDefault &&
10234
- currentDefault &&
10235
- prevDefault.groupId !== currentDefault.groupId);
10236
- }), map$1(() => true));
10237
- };
10238
- /**
10239
- * Notifies the subscriber about newly added default audio input device.
10240
- * @returns Observable<boolean>
10241
- */
10242
- const watchForAddedDefaultAudioDevice = () => watchForAddedDefaultDevice('audioinput');
10243
- /**
10244
- * Notifies the subscriber about newly added default audio output device.
10245
- * @returns Observable<boolean>
10246
- */
10247
- const watchForAddedDefaultAudioOutputDevice = () => watchForAddedDefaultDevice('audiooutput');
10248
- /**
10249
- * Notifies the subscriber about newly added default video input device.
10250
- * @returns Observable<boolean>
10251
- */
10252
- const watchForAddedDefaultVideoDevice = () => watchForAddedDefaultDevice('videoinput');
10141
+ const deviceIds$ = typeof navigator !== 'undefined' &&
10142
+ typeof navigator.mediaDevices !== 'undefined'
10143
+ ? memoizedObservable(() => merge(from(navigator.mediaDevices.enumerateDevices()), getDeviceChangeObserver()).pipe(shareReplay(1)))()
10144
+ : undefined;
10253
10145
  /**
10254
10146
  * Deactivates MediaStream (stops and removes tracks) to be later garbage collected
10255
10147
  *
@@ -10275,7 +10167,17 @@ class InputMediaDeviceManager {
10275
10167
  this.call = call;
10276
10168
  this.state = state;
10277
10169
  this.trackType = trackType;
10170
+ this.subscriptions = [];
10171
+ this.isTrackStoppedDueToTrackEnd = false;
10172
+ this.removeSubscriptions = () => {
10173
+ this.subscriptions.forEach((s) => s.unsubscribe());
10174
+ };
10278
10175
  this.logger = getLogger([`${TrackType[trackType].toLowerCase()} manager`]);
10176
+ if (deviceIds$ &&
10177
+ !isReactNative() &&
10178
+ (this.trackType === TrackType.AUDIO || this.trackType === TrackType.VIDEO)) {
10179
+ this.handleDisconnectedOrReplacedDevices();
10180
+ }
10279
10181
  }
10280
10182
  /**
10281
10183
  * Lists the available audio/video devices
@@ -10435,9 +10337,6 @@ class InputMediaDeviceManager {
10435
10337
  this.unmuteTracks();
10436
10338
  }
10437
10339
  else {
10438
- if (this.state.mediaStream) {
10439
- this.stopTracks();
10440
- }
10441
10340
  const defaultConstraints = this.state.defaultConstraints;
10442
10341
  const constraints = {
10443
10342
  ...defaultConstraints,
@@ -10450,7 +10349,79 @@ class InputMediaDeviceManager {
10450
10349
  }
10451
10350
  if (this.state.mediaStream !== stream) {
10452
10351
  this.state.setMediaStream(stream);
10352
+ this.getTracks().forEach((track) => {
10353
+ track.addEventListener('ended', async () => {
10354
+ if (this.enablePromise) {
10355
+ await this.enablePromise;
10356
+ }
10357
+ if (this.disablePromise) {
10358
+ await this.disablePromise;
10359
+ }
10360
+ if (this.state.status === 'enabled') {
10361
+ this.isTrackStoppedDueToTrackEnd = true;
10362
+ setTimeout(() => {
10363
+ this.isTrackStoppedDueToTrackEnd = false;
10364
+ }, 2000);
10365
+ await this.disable();
10366
+ }
10367
+ });
10368
+ });
10369
+ }
10370
+ }
10371
+ get mediaDeviceKind() {
10372
+ if (this.trackType === TrackType.AUDIO) {
10373
+ return 'audioinput';
10374
+ }
10375
+ if (this.trackType === TrackType.VIDEO) {
10376
+ return 'videoinput';
10453
10377
  }
10378
+ return '';
10379
+ }
10380
+ handleDisconnectedOrReplacedDevices() {
10381
+ this.subscriptions.push(combineLatest([
10382
+ deviceIds$.pipe(pairwise()),
10383
+ this.state.selectedDevice$,
10384
+ ]).subscribe(async ([[prevDevices, currentDevices], deviceId]) => {
10385
+ if (!deviceId) {
10386
+ return;
10387
+ }
10388
+ if (this.enablePromise) {
10389
+ await this.enablePromise;
10390
+ }
10391
+ if (this.disablePromise) {
10392
+ await this.disablePromise;
10393
+ }
10394
+ let isDeviceDisconnected = false;
10395
+ let isDeviceReplaced = false;
10396
+ const currentDevice = this.findDeviceInList(currentDevices, deviceId);
10397
+ const prevDevice = this.findDeviceInList(prevDevices, deviceId);
10398
+ if (!currentDevice && prevDevice) {
10399
+ isDeviceDisconnected = true;
10400
+ }
10401
+ else if (currentDevice &&
10402
+ prevDevice &&
10403
+ currentDevice.deviceId === prevDevice.deviceId &&
10404
+ currentDevice.groupId !== prevDevice.groupId) {
10405
+ isDeviceReplaced = true;
10406
+ }
10407
+ if (isDeviceDisconnected) {
10408
+ await this.disable();
10409
+ this.select(undefined);
10410
+ }
10411
+ if (isDeviceReplaced) {
10412
+ if (this.isTrackStoppedDueToTrackEnd &&
10413
+ this.state.status === 'disabled') {
10414
+ await this.enable();
10415
+ this.isTrackStoppedDueToTrackEnd = false;
10416
+ }
10417
+ else {
10418
+ await this.applySettingsToStream();
10419
+ }
10420
+ }
10421
+ }));
10422
+ }
10423
+ findDeviceInList(devices, deviceId) {
10424
+ return devices.find((d) => d.deviceId === deviceId && d.kind === this.mediaDeviceKind);
10454
10425
  }
10455
10426
  }
10456
10427
 
@@ -10610,8 +10581,9 @@ class CameraManager extends InputMediaDeviceManager {
10610
10581
  };
10611
10582
  }
10612
10583
  /**
10613
- * Select the camera direaction
10614
- * @param direction
10584
+ * Select the camera direction.
10585
+ *
10586
+ * @param direction the direction of the camera to select.
10615
10587
  */
10616
10588
  async selectDirection(direction) {
10617
10589
  this.state.setDirection(direction);
@@ -10641,6 +10613,7 @@ class CameraManager extends InputMediaDeviceManager {
10641
10613
  }
10642
10614
  catch (error) {
10643
10615
  // couldn't enable device, target resolution will be applied the next time user attempts to start the device
10616
+ this.logger('warn', 'could not apply target resolution', error);
10644
10617
  }
10645
10618
  }
10646
10619
  if (this.state.status === 'enabled') {
@@ -10648,11 +10621,21 @@ class CameraManager extends InputMediaDeviceManager {
10648
10621
  .mediaStream.getVideoTracks()[0]
10649
10622
  ?.getSettings();
10650
10623
  if (width !== this.targetResolution.width ||
10651
- height !== this.targetResolution.height)
10624
+ height !== this.targetResolution.height) {
10652
10625
  await this.applySettingsToStream();
10653
- this.logger('debug', `${width}x${height} target resolution applied to media stream`);
10626
+ this.logger('debug', `${width}x${height} target resolution applied to media stream`);
10627
+ }
10654
10628
  }
10655
10629
  }
10630
+ /**
10631
+ * Sets the preferred codec for encoding the video.
10632
+ *
10633
+ * @internal internal use only, not part of the public API.
10634
+ * @param codec the codec to use for encoding the video.
10635
+ */
10636
+ setPreferredCodec(codec) {
10637
+ this.preferredCodec = codec;
10638
+ }
10656
10639
  getDevices() {
10657
10640
  return getVideoDevices();
10658
10641
  }
@@ -10668,7 +10651,9 @@ class CameraManager extends InputMediaDeviceManager {
10668
10651
  return getVideoStream(constraints);
10669
10652
  }
10670
10653
  publishStream(stream) {
10671
- return this.call.publishVideoStream(stream);
10654
+ return this.call.publishVideoStream(stream, {
10655
+ preferredCodec: this.preferredCodec,
10656
+ });
10672
10657
  }
10673
10658
  stopPublishStream(stopTracks) {
10674
10659
  return this.call.stopPublish(TrackType.VIDEO, stopTracks);
@@ -11004,6 +10989,21 @@ class SpeakerState {
11004
10989
  class SpeakerManager {
11005
10990
  constructor() {
11006
10991
  this.state = new SpeakerState();
10992
+ this.subscriptions = [];
10993
+ this.removeSubscriptions = () => {
10994
+ this.subscriptions.forEach((s) => s.unsubscribe());
10995
+ };
10996
+ if (deviceIds$ && !isReactNative()) {
10997
+ this.subscriptions.push(combineLatest([deviceIds$, this.state.selectedDevice$]).subscribe(([devices, deviceId]) => {
10998
+ if (!deviceId) {
10999
+ return;
11000
+ }
11001
+ const device = devices.find((d) => d.deviceId === deviceId && d.kind === 'audiooutput');
11002
+ if (!device) {
11003
+ this.select('');
11004
+ }
11005
+ }));
11006
+ }
11007
11007
  }
11008
11008
  /**
11009
11009
  * Lists the available audio output devices
@@ -11121,6 +11121,10 @@ class Call {
11121
11121
  this.leaveCallHooks.forEach((hook) => hook());
11122
11122
  this.clientStore.unregisterCall(this);
11123
11123
  this.state.setCallingState(CallingState.LEFT);
11124
+ this.camera.removeSubscriptions();
11125
+ this.microphone.removeSubscriptions();
11126
+ this.screenShare.removeSubscriptions();
11127
+ this.speaker.removeSubscriptions();
11124
11128
  };
11125
11129
  /**
11126
11130
  * Loads the information about the call.
@@ -11251,13 +11255,6 @@ class Call {
11251
11255
  this.state.setCallingState(callingState);
11252
11256
  throw error;
11253
11257
  }
11254
- // FIXME OL: remove once cascading is implemented
11255
- if (typeof window !== 'undefined' && window.location?.search) {
11256
- const params = new URLSearchParams(window.location.search);
11257
- sfuServer.url = params.get('sfuUrl') || sfuServer.url;
11258
- sfuServer.ws_endpoint = params.get('sfuWsUrl') || sfuServer.ws_endpoint;
11259
- sfuServer.edge_name = params.get('sfuUrl') || sfuServer.edge_name;
11260
- }
11261
11258
  const previousSfuClient = this.sfuClient;
11262
11259
  const sfuClient = (this.sfuClient = new StreamSfuClient({
11263
11260
  dispatcher: this.dispatcher,
@@ -11324,8 +11321,11 @@ class Call {
11324
11321
  // restore previous publishing state
11325
11322
  if (audioStream)
11326
11323
  await this.publishAudioStream(audioStream);
11327
- if (videoStream)
11328
- await this.publishVideoStream(videoStream);
11324
+ if (videoStream) {
11325
+ await this.publishVideoStream(videoStream, {
11326
+ preferredCodec: this.camera.preferredCodec,
11327
+ });
11328
+ }
11329
11329
  if (screenShare)
11330
11330
  await this.publishScreenShareStream(screenShare);
11331
11331
  }
@@ -11498,7 +11498,7 @@ class Call {
11498
11498
  await this.initMic({ setStatus: true });
11499
11499
  }
11500
11500
  catch (error) {
11501
- this.logger('warn', 'Camera and/or mic init failed during join call');
11501
+ this.logger('warn', 'Camera and/or mic init failed during join call', error);
11502
11502
  }
11503
11503
  // 3. once we have the "joinResponse", and possibly reconciled the local state
11504
11504
  // we schedule a fast subscription update for all remote participants
@@ -12351,9 +12351,11 @@ class Call {
12351
12351
  if (this.camera.state.status === 'enabled' &&
12352
12352
  this.camera.state.mediaStream &&
12353
12353
  !this.publisher?.isPublishing(TrackType.VIDEO)) {
12354
- await this.publishVideoStream(this.camera.state.mediaStream);
12354
+ await this.publishVideoStream(this.camera.state.mediaStream, {
12355
+ preferredCodec: this.camera.preferredCodec,
12356
+ });
12355
12357
  }
12356
- // Start camera if backend config speicifies, and there is no local setting
12358
+ // Start camera if backend config specifies, and there is no local setting
12357
12359
  if (this.camera.state.status === undefined &&
12358
12360
  this.state.settings?.video.camera_default_on) {
12359
12361
  await this.camera.enable();
@@ -13968,7 +13970,7 @@ class StreamClient {
13968
13970
  });
13969
13971
  };
13970
13972
  this.getUserAgent = () => {
13971
- const version = "0.4.4" ;
13973
+ const version = "0.4.6" ;
13972
13974
  return (this.userAgent ||
13973
13975
  `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
13974
13976
  };
@@ -14503,5 +14505,5 @@ class StreamVideoServerClient extends StreamVideoClient {
14503
14505
  }
14504
14506
  }
14505
14507
 
14506
- export { AudioSettingsDefaultDeviceEnum, AudioSettingsRequestDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsNameEnum, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, OwnCapability, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoServerClient, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
14508
+ export { AudioSettingsDefaultDeviceEnum, AudioSettingsRequestDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CameraManagerState, CreateDeviceRequestPushProviderEnum, DebounceType, DynascaleManager, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, LayoutSettingsNameEnum, LayoutSettingsRequestNameEnum, MicrophoneManager, MicrophoneManagerState, OwnCapability, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, ScreenShareManager, ScreenShareState, events as SfuEvents, models as SfuModels, SpeakerManager, SpeakerState, StreamSfuClient, StreamVideoClient, StreamVideoReadOnlyStateStore, StreamVideoServerClient, StreamVideoWriteableStateStore, TranscriptionSettingsModeEnum, TranscriptionSettingsRequestModeEnum, VideoSettingsCameraFacingEnum, VideoSettingsRequestCameraFacingEnum, ViewportTracker, VisibilityState, checkIfAudioOutputChangeSupported, combineComparators, conditional, createSoundDetector, defaultSortPreset, descending, deviceIds$, disposeOfMediaStream, dominantSpeaker, getAudioDevices, getAudioOutputDevices, getAudioStream, getClientDetails, getDeviceInfo, getLogger, getOSInfo, getScreenShareStream, getSdkInfo, getVideoDevices, getVideoStream, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, paginatedLayoutSortPreset, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setSdkInfo, speakerLayoutSortPreset, speaking };
14507
14509
  //# sourceMappingURL=index.browser.es.js.map