@stream-io/video-client 0.3.0 → 0.3.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 (36) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/index.browser.es.js +662 -256
  3. package/dist/index.browser.es.js.map +1 -1
  4. package/dist/index.cjs.js +664 -254
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.es.js +662 -256
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/src/Call.d.ts +18 -1
  9. package/dist/src/devices/CameraManager.d.ts +31 -0
  10. package/dist/src/devices/CameraManagerState.d.ts +28 -0
  11. package/dist/src/devices/InputMediaDeviceManager.d.ts +47 -0
  12. package/dist/src/devices/InputMediaDeviceManagerState.d.ts +69 -0
  13. package/dist/src/devices/MicrophoneManager.d.ts +19 -0
  14. package/dist/src/devices/MicrophoneManagerState.d.ts +4 -0
  15. package/dist/src/devices/__tests__/CameraManager.test.d.ts +1 -0
  16. package/dist/src/devices/__tests__/InputMediaDeviceManager.test.d.ts +1 -0
  17. package/dist/src/devices/__tests__/MicrophoneManager.test.d.ts +1 -0
  18. package/dist/src/devices/__tests__/mocks.d.ts +13 -0
  19. package/dist/src/devices/index.d.ts +4 -0
  20. package/dist/src/types.d.ts +4 -0
  21. package/dist/version.d.ts +1 -1
  22. package/package.json +1 -1
  23. package/src/Call.ts +100 -3
  24. package/src/__tests__/StreamVideoClient.test.ts +3 -0
  25. package/src/devices/CameraManager.ts +73 -0
  26. package/src/devices/CameraManagerState.ts +61 -0
  27. package/src/devices/InputMediaDeviceManager.ts +121 -0
  28. package/src/devices/InputMediaDeviceManagerState.ts +111 -0
  29. package/src/devices/MicrophoneManager.ts +45 -0
  30. package/src/devices/MicrophoneManagerState.ts +9 -0
  31. package/src/devices/__tests__/CameraManager.test.ts +150 -0
  32. package/src/devices/__tests__/InputMediaDeviceManager.test.ts +159 -0
  33. package/src/devices/__tests__/MicrophoneManager.test.ts +103 -0
  34. package/src/devices/__tests__/mocks.ts +98 -0
  35. package/src/devices/index.ts +4 -0
  36. package/src/types.ts +4 -0
@@ -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, BehaviorSubject, takeWhile, filter, pairwise, tap, debounce, timer, map as map$2, Observable, debounceTime, concatMap, from, shareReplay, merge, combineLatest } from 'rxjs';
7
+ import { ReplaySubject, BehaviorSubject, distinctUntilChanged as distinctUntilChanged$1, Observable, debounceTime, concatMap, from, shareReplay, merge, map as map$2, combineLatest, filter, pairwise, takeWhile, tap, debounce, timer } from 'rxjs';
8
8
  import * as SDP from 'sdp-transform';
9
9
  import WebSocket from 'isomorphic-ws';
10
10
  import { take, map as map$1, distinctUntilChanged } from 'rxjs/operators';
@@ -9514,6 +9514,591 @@ const getClientDetails = () => {
9514
9514
  };
9515
9515
  };
9516
9516
 
9517
+ class InputMediaDeviceManagerState {
9518
+ constructor() {
9519
+ this.statusSubject = new BehaviorSubject(undefined);
9520
+ this.mediaStreamSubject = new BehaviorSubject(undefined);
9521
+ this.selectedDeviceSubject = new BehaviorSubject(undefined);
9522
+ /**
9523
+ * Gets the current value of an observable, or undefined if the observable has
9524
+ * not emitted a value yet.
9525
+ *
9526
+ * @param observable$ the observable to get the value from.
9527
+ */
9528
+ this.getCurrentValue = getCurrentValue;
9529
+ /**
9530
+ * Updates the value of the provided Subject.
9531
+ * An `update` can either be a new value or a function which takes
9532
+ * the current value and returns a new value.
9533
+ *
9534
+ * @internal
9535
+ *
9536
+ * @param subject the subject to update.
9537
+ * @param update the update to apply to the subject.
9538
+ * @return the updated value.
9539
+ */
9540
+ this.setCurrentValue = setCurrentValue;
9541
+ this.mediaStream$ = this.mediaStreamSubject.asObservable();
9542
+ this.selectedDevice$ = this.selectedDeviceSubject
9543
+ .asObservable()
9544
+ .pipe(distinctUntilChanged$1());
9545
+ this.status$ = this.statusSubject.asObservable();
9546
+ }
9547
+ /**
9548
+ * The device status
9549
+ */
9550
+ get status() {
9551
+ return this.getCurrentValue(this.status$);
9552
+ }
9553
+ /**
9554
+ * The currently selected device
9555
+ */
9556
+ get selectedDevice() {
9557
+ return this.getCurrentValue(this.selectedDevice$);
9558
+ }
9559
+ /**
9560
+ * The current media stream, or `undefined` if the device is currently disabled.
9561
+ */
9562
+ get mediaStream() {
9563
+ return this.getCurrentValue(this.mediaStream$);
9564
+ }
9565
+ /**
9566
+ * @internal
9567
+ * @param status
9568
+ */
9569
+ setStatus(status) {
9570
+ this.setCurrentValue(this.statusSubject, status);
9571
+ }
9572
+ /**
9573
+ * @internal
9574
+ * @param stream
9575
+ */
9576
+ setMediaStream(stream) {
9577
+ this.setCurrentValue(this.mediaStreamSubject, stream);
9578
+ if (stream) {
9579
+ this.setDevice(this.getDeviceIdFromStream(stream));
9580
+ }
9581
+ }
9582
+ /**
9583
+ * @internal
9584
+ * @param stream
9585
+ */
9586
+ setDevice(deviceId) {
9587
+ this.setCurrentValue(this.selectedDeviceSubject, deviceId);
9588
+ }
9589
+ }
9590
+
9591
+ class CameraManagerState extends InputMediaDeviceManagerState {
9592
+ constructor() {
9593
+ super();
9594
+ this.directionSubject = new BehaviorSubject(undefined);
9595
+ this.direction$ = this.directionSubject
9596
+ .asObservable()
9597
+ .pipe(distinctUntilChanged$1());
9598
+ }
9599
+ /**
9600
+ * The preferred camera direction
9601
+ * front - means the camera facing the user
9602
+ * back - means the camera facing the environment
9603
+ */
9604
+ get direction() {
9605
+ return this.getCurrentValue(this.direction$);
9606
+ }
9607
+ /**
9608
+ * @internal
9609
+ */
9610
+ setDirection(direction) {
9611
+ this.setCurrentValue(this.directionSubject, direction);
9612
+ }
9613
+ /**
9614
+ * @internal
9615
+ */
9616
+ setMediaStream(stream) {
9617
+ var _a;
9618
+ super.setMediaStream(stream);
9619
+ if (stream) {
9620
+ // RN getSettings() doesn't return facingMode, so we don't verify camera direction
9621
+ const direction = isReactNative()
9622
+ ? this.direction
9623
+ : ((_a = stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().facingMode) === 'environment'
9624
+ ? 'back'
9625
+ : 'front';
9626
+ this.setDirection(direction);
9627
+ }
9628
+ }
9629
+ getDeviceIdFromStream(stream) {
9630
+ var _a;
9631
+ return (_a = stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
9632
+ }
9633
+ }
9634
+
9635
+ const getDevices = (constraints) => {
9636
+ return new Observable((subscriber) => {
9637
+ navigator.mediaDevices
9638
+ .getUserMedia(constraints)
9639
+ .then((media) => {
9640
+ // in Firefox, devices can be enumerated after userMedia is requested
9641
+ // and permissions granted. Otherwise, device labels are empty
9642
+ navigator.mediaDevices.enumerateDevices().then((devices) => {
9643
+ subscriber.next(devices);
9644
+ // If we stop the tracks before enumerateDevices -> the labels won't show up in Firefox
9645
+ disposeOfMediaStream(media);
9646
+ subscriber.complete();
9647
+ });
9648
+ })
9649
+ .catch((error) => {
9650
+ getLogger(['devices'])('error', 'Failed to get devices', error);
9651
+ subscriber.error(error);
9652
+ });
9653
+ });
9654
+ };
9655
+ /**
9656
+ * [Tells if the browser supports audio output change on 'audio' elements](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId).
9657
+ *
9658
+ * @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.
9659
+ */
9660
+ const checkIfAudioOutputChangeSupported = () => {
9661
+ if (typeof document === 'undefined')
9662
+ return false;
9663
+ const element = document.createElement('audio');
9664
+ return element.sinkId !== undefined;
9665
+ };
9666
+ /**
9667
+ * The default constraints used to request audio devices.
9668
+ */
9669
+ const audioDeviceConstraints = {
9670
+ audio: {
9671
+ autoGainControl: true,
9672
+ noiseSuppression: true,
9673
+ echoCancellation: true,
9674
+ },
9675
+ };
9676
+ /**
9677
+ * The default constraints used to request video devices.
9678
+ */
9679
+ const videoDeviceConstraints = {
9680
+ video: {
9681
+ width: 1280,
9682
+ height: 720,
9683
+ },
9684
+ };
9685
+ // Audio and video devices are requested in two separate requests: that way users will be presented with two separate prompts -> they can give access to just camera, or just microphone
9686
+ const deviceChange$ = new Observable((subscriber) => {
9687
+ var _a, _b;
9688
+ const deviceChangeHandler = () => subscriber.next();
9689
+ (_b = (_a = navigator.mediaDevices).addEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, 'devicechange', deviceChangeHandler);
9690
+ return () => {
9691
+ var _a, _b;
9692
+ return (_b = (_a = navigator.mediaDevices).removeEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, 'devicechange', deviceChangeHandler);
9693
+ };
9694
+ }).pipe(debounceTime(500), concatMap(() => from(navigator.mediaDevices.enumerateDevices())), shareReplay(1));
9695
+ const audioDevices$ = merge(getDevices(audioDeviceConstraints), deviceChange$).pipe(shareReplay(1));
9696
+ const videoDevices$ = merge(getDevices(videoDeviceConstraints), deviceChange$).pipe(shareReplay(1));
9697
+ /**
9698
+ * Prompts the user for a permission to use audio devices (if not already granted) and lists the available 'audioinput' devices, if devices are added/removed the list is updated.
9699
+ *
9700
+ * @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.
9701
+ * @returns
9702
+ */
9703
+ const getAudioDevices = () => audioDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'audioinput')));
9704
+ /**
9705
+ * Prompts the user for a permission to use video devices (if not already granted) and lists the available 'videoinput' devices, if devices are added/removed the list is updated.
9706
+ *
9707
+ * @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.
9708
+ * @returns
9709
+ */
9710
+ const getVideoDevices = () => videoDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'videoinput' && d.deviceId.length)));
9711
+ /**
9712
+ * Prompts the user for a permission to use audio devices (if not already granted) and lists the available 'audiooutput' devices, if devices are added/removed the list is updated. Selecting 'audiooutput' device only makes sense if [the browser has support for changing audio output on 'audio' elements](#checkifaudiooutputchangesupported)
9713
+ *
9714
+ * @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.
9715
+ * @returns
9716
+ */
9717
+ const getAudioOutputDevices = () => {
9718
+ return audioDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'audiooutput')));
9719
+ };
9720
+ const getStream = (constraints) => __awaiter(void 0, void 0, void 0, function* () {
9721
+ try {
9722
+ return yield navigator.mediaDevices.getUserMedia(constraints);
9723
+ }
9724
+ catch (e) {
9725
+ getLogger(['devices'])('error', `Failed get user media`, {
9726
+ error: e,
9727
+ constraints: constraints,
9728
+ });
9729
+ throw e;
9730
+ }
9731
+ });
9732
+ /**
9733
+ * Returns an audio media stream that fulfills the given constraints.
9734
+ * If no constraints are provided, it uses the browser's default ones.
9735
+ *
9736
+ * @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.
9737
+ * @param trackConstraints the constraints to use when requesting the stream.
9738
+ * @returns the new `MediaStream` fulfilling the given constraints.
9739
+ */
9740
+ const getAudioStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, function* () {
9741
+ const constraints = {
9742
+ audio: Object.assign(Object.assign({}, audioDeviceConstraints.audio), trackConstraints),
9743
+ };
9744
+ return getStream(constraints);
9745
+ });
9746
+ /**
9747
+ * Returns a video media stream that fulfills the given constraints.
9748
+ * If no constraints are provided, it uses the browser's default ones.
9749
+ *
9750
+ * @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.
9751
+ * @param trackConstraints the constraints to use when requesting the stream.
9752
+ * @returns a new `MediaStream` fulfilling the given constraints.
9753
+ */
9754
+ const getVideoStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, function* () {
9755
+ const constraints = {
9756
+ video: Object.assign(Object.assign({}, videoDeviceConstraints.video), trackConstraints),
9757
+ };
9758
+ return getStream(constraints);
9759
+ });
9760
+ /**
9761
+ * Prompts the user for a permission to share a screen.
9762
+ * If the user grants the permission, a screen sharing stream is returned. Throws otherwise.
9763
+ *
9764
+ * The callers of this API are responsible to handle the possible errors.
9765
+ *
9766
+ * @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.
9767
+ *
9768
+ * @param options any additional options to pass to the [`getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) API.
9769
+ */
9770
+ const getScreenShareStream = (options) => __awaiter(void 0, void 0, void 0, function* () {
9771
+ try {
9772
+ return yield navigator.mediaDevices.getDisplayMedia(Object.assign({ video: true, audio: false }, options));
9773
+ }
9774
+ catch (e) {
9775
+ getLogger(['devices'])('error', 'Failed to get screen share stream', e);
9776
+ throw e;
9777
+ }
9778
+ });
9779
+ const watchForDisconnectedDevice = (kind, deviceId$) => {
9780
+ let devices$;
9781
+ switch (kind) {
9782
+ case 'audioinput':
9783
+ devices$ = getAudioDevices();
9784
+ break;
9785
+ case 'videoinput':
9786
+ devices$ = getVideoDevices();
9787
+ break;
9788
+ case 'audiooutput':
9789
+ devices$ = getAudioOutputDevices();
9790
+ break;
9791
+ }
9792
+ return combineLatest([devices$, deviceId$]).pipe(filter(([devices, deviceId]) => !!deviceId && !devices.find((d) => d.deviceId === deviceId)), map$2(() => true));
9793
+ };
9794
+ /**
9795
+ * Notifies the subscriber if a given 'audioinput' device is disconnected
9796
+ *
9797
+ * @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.
9798
+ * @param deviceId$ an Observable that specifies which device to watch for
9799
+ * @returns
9800
+ */
9801
+ const watchForDisconnectedAudioDevice = (deviceId$) => {
9802
+ return watchForDisconnectedDevice('audioinput', deviceId$);
9803
+ };
9804
+ /**
9805
+ * Notifies the subscriber if a given 'videoinput' device is disconnected
9806
+ *
9807
+ * @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.
9808
+ * @param deviceId$ an Observable that specifies which device to watch for
9809
+ * @returns
9810
+ */
9811
+ const watchForDisconnectedVideoDevice = (deviceId$) => {
9812
+ return watchForDisconnectedDevice('videoinput', deviceId$);
9813
+ };
9814
+ /**
9815
+ * Notifies the subscriber if a given 'audiooutput' device is disconnected
9816
+ *
9817
+ * @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.
9818
+ * @param deviceId$ an Observable that specifies which device to watch for
9819
+ * @returns
9820
+ */
9821
+ const watchForDisconnectedAudioOutputDevice = (deviceId$) => {
9822
+ return watchForDisconnectedDevice('audiooutput', deviceId$);
9823
+ };
9824
+ const watchForAddedDefaultDevice = (kind) => {
9825
+ let devices$;
9826
+ switch (kind) {
9827
+ case 'audioinput':
9828
+ devices$ = getAudioDevices();
9829
+ break;
9830
+ case 'videoinput':
9831
+ devices$ = getVideoDevices();
9832
+ break;
9833
+ case 'audiooutput':
9834
+ devices$ = getAudioOutputDevices();
9835
+ break;
9836
+ default:
9837
+ throw new Error('Unknown MediaDeviceKind', kind);
9838
+ }
9839
+ return devices$.pipe(pairwise(), filter(([prev, current]) => {
9840
+ const prevDefault = prev.find((device) => device.deviceId === 'default');
9841
+ const currentDefault = current.find((device) => device.deviceId === 'default');
9842
+ return !!(current.length > prev.length &&
9843
+ prevDefault &&
9844
+ currentDefault &&
9845
+ prevDefault.groupId !== currentDefault.groupId);
9846
+ }), map$2(() => true));
9847
+ };
9848
+ /**
9849
+ * Notifies the subscriber about newly added default audio input device.
9850
+ * @returns Observable<boolean>
9851
+ */
9852
+ const watchForAddedDefaultAudioDevice = () => watchForAddedDefaultDevice('audioinput');
9853
+ /**
9854
+ * Notifies the subscriber about newly added default audio output device.
9855
+ * @returns Observable<boolean>
9856
+ */
9857
+ const watchForAddedDefaultAudioOutputDevice = () => watchForAddedDefaultDevice('audiooutput');
9858
+ /**
9859
+ * Notifies the subscriber about newly added default video input device.
9860
+ * @returns Observable<boolean>
9861
+ */
9862
+ const watchForAddedDefaultVideoDevice = () => watchForAddedDefaultDevice('videoinput');
9863
+ /**
9864
+ * Deactivates MediaStream (stops and removes tracks) to be later garbage collected
9865
+ *
9866
+ * @param stream MediaStream
9867
+ * @returns void
9868
+ */
9869
+ const disposeOfMediaStream = (stream) => {
9870
+ if (!stream.active)
9871
+ return;
9872
+ stream.getTracks().forEach((track) => {
9873
+ track.stop();
9874
+ stream.removeTrack(track);
9875
+ });
9876
+ // @ts-expect-error release() is present in react-native-webrtc and must be called to dispose the stream
9877
+ if (typeof stream.release === 'function') {
9878
+ // @ts-expect-error
9879
+ stream.release();
9880
+ }
9881
+ };
9882
+
9883
+ class InputMediaDeviceManager {
9884
+ constructor(call, state) {
9885
+ this.call = call;
9886
+ this.state = state;
9887
+ }
9888
+ /**
9889
+ * Lists the available audio/video devices
9890
+ *
9891
+ * Note: It prompts the user for a permission to use devices (if not already granted)
9892
+ *
9893
+ * @returns an Observable that will be updated if a device is connected or disconnected
9894
+ */
9895
+ listDevices() {
9896
+ return this.getDevices();
9897
+ }
9898
+ /**
9899
+ * Starts camera/microphone
9900
+ */
9901
+ enable() {
9902
+ return __awaiter(this, void 0, void 0, function* () {
9903
+ if (this.state.status === 'enabled') {
9904
+ return;
9905
+ }
9906
+ yield this.startStream();
9907
+ this.state.setStatus('enabled');
9908
+ });
9909
+ }
9910
+ /**
9911
+ * Stops camera/microphone
9912
+ * @returns
9913
+ */
9914
+ disable() {
9915
+ return __awaiter(this, void 0, void 0, function* () {
9916
+ if (this.state.status === 'disabled') {
9917
+ return;
9918
+ }
9919
+ yield this.stopStream();
9920
+ this.state.setStatus('disabled');
9921
+ });
9922
+ }
9923
+ /**
9924
+ * If current device statis is disabled, it will enable the device, else it will disable it.
9925
+ * @returns
9926
+ */
9927
+ toggle() {
9928
+ return __awaiter(this, void 0, void 0, function* () {
9929
+ if (this.state.status === 'enabled') {
9930
+ return this.disable();
9931
+ }
9932
+ else {
9933
+ return this.enable();
9934
+ }
9935
+ });
9936
+ }
9937
+ /**
9938
+ * Select device
9939
+ *
9940
+ * Note: this method is not supported in React Native
9941
+ *
9942
+ * @param deviceId
9943
+ */
9944
+ select(deviceId) {
9945
+ return __awaiter(this, void 0, void 0, function* () {
9946
+ if (isReactNative()) {
9947
+ throw new Error('This method is not supported in React Native');
9948
+ }
9949
+ if (deviceId === this.state.selectedDevice) {
9950
+ return;
9951
+ }
9952
+ this.state.setDevice(deviceId);
9953
+ yield this.applySettingsToStream();
9954
+ });
9955
+ }
9956
+ applySettingsToStream() {
9957
+ return __awaiter(this, void 0, void 0, function* () {
9958
+ if (this.state.status === 'enabled') {
9959
+ yield this.stopStream();
9960
+ yield this.startStream();
9961
+ }
9962
+ });
9963
+ }
9964
+ stopStream() {
9965
+ return __awaiter(this, void 0, void 0, function* () {
9966
+ if (!this.state.mediaStream) {
9967
+ return;
9968
+ }
9969
+ if (this.call.state.callingState === CallingState.JOINED) {
9970
+ yield this.stopPublishStream();
9971
+ }
9972
+ else if (this.state.mediaStream) {
9973
+ disposeOfMediaStream(this.state.mediaStream);
9974
+ }
9975
+ this.state.setMediaStream(undefined);
9976
+ });
9977
+ }
9978
+ startStream() {
9979
+ return __awaiter(this, void 0, void 0, function* () {
9980
+ if (this.state.mediaStream) {
9981
+ return;
9982
+ }
9983
+ const constraints = { deviceId: this.state.selectedDevice };
9984
+ const stream = yield this.getStream(constraints);
9985
+ if (this.call.state.callingState === CallingState.JOINED) {
9986
+ yield this.publishStream(stream);
9987
+ }
9988
+ this.state.setMediaStream(stream);
9989
+ });
9990
+ }
9991
+ }
9992
+
9993
+ class CameraManager extends InputMediaDeviceManager {
9994
+ constructor(call) {
9995
+ super(call, new CameraManagerState());
9996
+ }
9997
+ /**
9998
+ * Select the camera direaction
9999
+ * @param direction
10000
+ */
10001
+ selectDirection(direction) {
10002
+ return __awaiter(this, void 0, void 0, function* () {
10003
+ this.state.setDirection(direction);
10004
+ // Providing both device id and direction doesn't work, so we deselect the device
10005
+ this.state.setDevice(undefined);
10006
+ yield this.applySettingsToStream();
10007
+ });
10008
+ }
10009
+ /**
10010
+ * Flips the camera direction: if it's front it will change to back, if it's back, it will change to front.
10011
+ *
10012
+ * Note: if there is no available camera with the desired direction, this method will do nothing.
10013
+ * @returns
10014
+ */
10015
+ flip() {
10016
+ return __awaiter(this, void 0, void 0, function* () {
10017
+ const newDirection = this.state.direction === 'front' ? 'back' : 'front';
10018
+ this.selectDirection(newDirection);
10019
+ });
10020
+ }
10021
+ getDevices() {
10022
+ return getVideoDevices();
10023
+ }
10024
+ getStream(constraints) {
10025
+ // We can't set both device id and facing mode
10026
+ // Device id has higher priority
10027
+ if (!constraints.deviceId && this.state.direction) {
10028
+ constraints.facingMode =
10029
+ this.state.direction === 'front' ? 'user' : 'environment';
10030
+ }
10031
+ return getVideoStream(constraints);
10032
+ }
10033
+ publishStream(stream) {
10034
+ return this.call.publishVideoStream(stream);
10035
+ }
10036
+ stopPublishStream() {
10037
+ return this.call.stopPublish(TrackType.VIDEO);
10038
+ }
10039
+ /**
10040
+ * Disables the video tracks of the camera
10041
+ */
10042
+ pause() {
10043
+ var _a;
10044
+ (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks().forEach((track) => {
10045
+ track.enabled = false;
10046
+ });
10047
+ }
10048
+ /**
10049
+ * (Re)enables the video tracks of the camera
10050
+ */
10051
+ resume() {
10052
+ var _a;
10053
+ (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getVideoTracks().forEach((track) => {
10054
+ track.enabled = true;
10055
+ });
10056
+ }
10057
+ }
10058
+
10059
+ class MicrophoneManagerState extends InputMediaDeviceManagerState {
10060
+ getDeviceIdFromStream(stream) {
10061
+ var _a;
10062
+ return (_a = stream.getAudioTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
10063
+ }
10064
+ }
10065
+
10066
+ class MicrophoneManager extends InputMediaDeviceManager {
10067
+ constructor(call) {
10068
+ super(call, new MicrophoneManagerState());
10069
+ }
10070
+ getDevices() {
10071
+ return getAudioDevices();
10072
+ }
10073
+ getStream(constraints) {
10074
+ return getAudioStream(constraints);
10075
+ }
10076
+ publishStream(stream) {
10077
+ return this.call.publishAudioStream(stream);
10078
+ }
10079
+ stopPublishStream() {
10080
+ return this.call.stopPublish(TrackType.AUDIO);
10081
+ }
10082
+ /**
10083
+ * Disables the audio tracks of the microphone
10084
+ */
10085
+ pause() {
10086
+ var _a;
10087
+ (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach((track) => {
10088
+ track.enabled = false;
10089
+ });
10090
+ }
10091
+ /**
10092
+ * (Re)enables the audio tracks of the microphone
10093
+ */
10094
+ resume() {
10095
+ var _a;
10096
+ (_a = this.state.mediaStream) === null || _a === void 0 ? void 0 : _a.getAudioTracks().forEach((track) => {
10097
+ track.enabled = true;
10098
+ });
10099
+ }
10100
+ }
10101
+
9517
10102
  /**
9518
10103
  * An object representation of a `Call`.
9519
10104
  */
@@ -9680,7 +10265,7 @@ class Call {
9680
10265
  * @returns a promise which resolves once the call join-flow has finished.
9681
10266
  */
9682
10267
  this.join = (data) => __awaiter(this, void 0, void 0, function* () {
9683
- var _e, _f, _g;
10268
+ var _e, _f, _g, _h;
9684
10269
  const callingState = this.state.callingState;
9685
10270
  if ([CallingState.JOINED, CallingState.JOINING].includes(callingState)) {
9686
10271
  this.logger('warn', 'Join method called twice, you should only call this once');
@@ -9949,6 +10534,11 @@ class Call {
9949
10534
  this.state.setServerSidePins(pins);
9950
10535
  this.reconnectAttempts = 0; // reset the reconnect attempts counter
9951
10536
  this.state.setCallingState(CallingState.JOINED);
10537
+ // React uses a different device management for now
10538
+ if (((_h = getSdkInfo()) === null || _h === void 0 ? void 0 : _h.type) !== SdkType.REACT) {
10539
+ this.initCamera();
10540
+ this.initMic();
10541
+ }
9952
10542
  // 3. once we have the "joinResponse", and possibly reconciled the local state
9953
10543
  // we schedule a fast subscription update for all remote participants
9954
10544
  // that were visible before we reconnected or migrated to a new SFU.
@@ -10071,9 +10661,9 @@ class Call {
10071
10661
  * @param trackType the track type to stop publishing.
10072
10662
  */
10073
10663
  this.stopPublish = (trackType) => __awaiter(this, void 0, void 0, function* () {
10074
- var _h;
10664
+ var _j;
10075
10665
  this.logger('info', `stopPublish ${TrackType[trackType]}`);
10076
- yield ((_h = this.publisher) === null || _h === void 0 ? void 0 : _h.unpublishStream(trackType));
10666
+ yield ((_j = this.publisher) === null || _j === void 0 ? void 0 : _j.unpublishStream(trackType));
10077
10667
  });
10078
10668
  /**
10079
10669
  * Update track subscription configuration for one or more participants.
@@ -10174,6 +10764,8 @@ class Call {
10174
10764
  *
10175
10765
  *
10176
10766
  * @param deviceId the selected device, pass `undefined` to clear the device selection
10767
+ *
10768
+ * @deprecated use call.microphone.select
10177
10769
  */
10178
10770
  this.setAudioDevice = (deviceId) => {
10179
10771
  if (!this.sfuClient)
@@ -10188,6 +10780,8 @@ class Call {
10188
10780
  * This method only stores the selection, if you want to start publishing a media stream call the [`publishVideoStream` method](#publishvideostream) that will set `videoDeviceId` as well.
10189
10781
  *
10190
10782
  * @param deviceId the selected device, pass `undefined` to clear the device selection
10783
+ *
10784
+ * @deprecated use call.camera.select
10191
10785
  */
10192
10786
  this.setVideoDevice = (deviceId) => {
10193
10787
  if (!this.sfuClient)
@@ -10220,8 +10814,8 @@ class Call {
10220
10814
  * @returns
10221
10815
  */
10222
10816
  this.updatePublishQuality = (enabledRids) => __awaiter(this, void 0, void 0, function* () {
10223
- var _j;
10224
- return (_j = this.publisher) === null || _j === void 0 ? void 0 : _j.updateVideoPublishQuality(enabledRids);
10817
+ var _k;
10818
+ return (_k = this.publisher) === null || _k === void 0 ? void 0 : _k.updateVideoPublishQuality(enabledRids);
10225
10819
  });
10226
10820
  this.assertCallJoined = () => {
10227
10821
  return new Promise((resolve) => {
@@ -10564,6 +11158,8 @@ class Call {
10564
11158
  this.leaveCallHooks.push(registerEventHandlers(this, this.state, this.dispatcher));
10565
11159
  this.registerEffects();
10566
11160
  this.leaveCallHooks.push(createSubscription(this.trackSubscriptionsSubject.pipe(debounce((v) => timer(v.type)), map$2((v) => v.data)), (subscriptions) => { var _a; return (_a = this.sfuClient) === null || _a === void 0 ? void 0 : _a.updateSubscriptions(subscriptions); }));
11161
+ this.camera = new CameraManager(this);
11162
+ this.microphone = new MicrophoneManager(this);
10567
11163
  }
10568
11164
  registerEffects() {
10569
11165
  this.leaveCallHooks.push(
@@ -10671,6 +11267,64 @@ class Call {
10671
11267
  var _a;
10672
11268
  return ((_a = this.state.createdBy) === null || _a === void 0 ? void 0 : _a.id) === this.currentUserId;
10673
11269
  }
11270
+ initCamera() {
11271
+ var _a, _b, _c;
11272
+ if (((_a = this.state.localParticipant) === null || _a === void 0 ? void 0 : _a.videoStream) ||
11273
+ !this.permissionsContext.hasPermission('send-video')) {
11274
+ return;
11275
+ }
11276
+ // Set camera direction if it's not yet set
11277
+ // This will also start publishing if camera is enabled
11278
+ if (!this.camera.state.direction && !this.camera.state.selectedDevice) {
11279
+ let defaultDirection = 'front';
11280
+ const backendSetting = (_b = this.state.settings) === null || _b === void 0 ? void 0 : _b.video.camera_facing;
11281
+ if (backendSetting) {
11282
+ defaultDirection = backendSetting === 'front' ? 'front' : 'back';
11283
+ }
11284
+ this.camera.selectDirection(defaultDirection);
11285
+ }
11286
+ else if (this.camera.state.status === 'enabled') {
11287
+ // Publish already started media streams (this is the case if there is a lobby screen before join)
11288
+ // Wait for media stream
11289
+ this.camera.state.mediaStream$
11290
+ .pipe(takeWhile((s) => s === undefined, true))
11291
+ .subscribe((stream) => {
11292
+ var _a;
11293
+ if (!((_a = this.state.localParticipant) === null || _a === void 0 ? void 0 : _a.videoStream)) {
11294
+ this.publishVideoStream(stream);
11295
+ }
11296
+ });
11297
+ }
11298
+ // Apply backend config (this is the case if there is no lobby screen before join)
11299
+ if (this.camera.state.status === undefined &&
11300
+ ((_c = this.state.settings) === null || _c === void 0 ? void 0 : _c.video.camera_default_on)) {
11301
+ void this.camera.enable();
11302
+ }
11303
+ }
11304
+ initMic() {
11305
+ var _a, _b;
11306
+ if (((_a = this.state.localParticipant) === null || _a === void 0 ? void 0 : _a.audioStream) ||
11307
+ !this.permissionsContext.hasPermission('send-audio')) {
11308
+ return;
11309
+ }
11310
+ // Publish already started media streams (this is the case if there is a lobby screen before join)
11311
+ if (this.microphone.state.status === 'enabled') {
11312
+ // Wait for media stream
11313
+ this.microphone.state.mediaStream$
11314
+ .pipe(takeWhile((s) => s === undefined, true))
11315
+ .subscribe((stream) => {
11316
+ var _a;
11317
+ if (!((_a = this.state.localParticipant) === null || _a === void 0 ? void 0 : _a.audioStream)) {
11318
+ this.publishAudioStream(stream);
11319
+ }
11320
+ });
11321
+ }
11322
+ // Apply backend config (this is the case if there is no lobby screen before join)
11323
+ if (this.microphone.state.status === undefined &&
11324
+ ((_b = this.state.settings) === null || _b === void 0 ? void 0 : _b.audio.mic_default_on)) {
11325
+ void this.microphone.enable();
11326
+ }
11327
+ }
10674
11328
  }
10675
11329
 
10676
11330
  var https = null;
@@ -11781,7 +12435,7 @@ class WSConnectionFallback {
11781
12435
  }
11782
12436
  }
11783
12437
 
11784
- const version = '0.3.0';
12438
+ const version = '0.3.1';
11785
12439
 
11786
12440
  const logger = getLogger(['location']);
11787
12441
  const HINT_URL = `https://hint.stream-io-video.com/`;
@@ -12755,254 +13409,6 @@ class StreamVideoServerClient extends StreamVideoClient {
12755
13409
  }
12756
13410
  }
12757
13411
 
12758
- const getDevices = (constraints) => {
12759
- return new Observable((subscriber) => {
12760
- navigator.mediaDevices
12761
- .getUserMedia(constraints)
12762
- .then((media) => {
12763
- // in Firefox, devices can be enumerated after userMedia is requested
12764
- // and permissions granted. Otherwise, device labels are empty
12765
- navigator.mediaDevices.enumerateDevices().then((devices) => {
12766
- subscriber.next(devices);
12767
- // If we stop the tracks before enumerateDevices -> the labels won't show up in Firefox
12768
- disposeOfMediaStream(media);
12769
- subscriber.complete();
12770
- });
12771
- })
12772
- .catch((error) => {
12773
- getLogger(['devices'])('error', 'Failed to get devices', error);
12774
- subscriber.error(error);
12775
- });
12776
- });
12777
- };
12778
- /**
12779
- * [Tells if the browser supports audio output change on 'audio' elements](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId).
12780
- *
12781
- * @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.
12782
- */
12783
- const checkIfAudioOutputChangeSupported = () => {
12784
- if (typeof document === 'undefined')
12785
- return false;
12786
- const element = document.createElement('audio');
12787
- return element.sinkId !== undefined;
12788
- };
12789
- /**
12790
- * The default constraints used to request audio devices.
12791
- */
12792
- const audioDeviceConstraints = {
12793
- audio: {
12794
- autoGainControl: true,
12795
- noiseSuppression: true,
12796
- echoCancellation: true,
12797
- },
12798
- };
12799
- /**
12800
- * The default constraints used to request video devices.
12801
- */
12802
- const videoDeviceConstraints = {
12803
- video: {
12804
- width: 1280,
12805
- height: 720,
12806
- },
12807
- };
12808
- // Audio and video devices are requested in two separate requests: that way users will be presented with two separate prompts -> they can give access to just camera, or just microphone
12809
- const deviceChange$ = new Observable((subscriber) => {
12810
- var _a, _b;
12811
- const deviceChangeHandler = () => subscriber.next();
12812
- (_b = (_a = navigator.mediaDevices).addEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, 'devicechange', deviceChangeHandler);
12813
- return () => {
12814
- var _a, _b;
12815
- return (_b = (_a = navigator.mediaDevices).removeEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, 'devicechange', deviceChangeHandler);
12816
- };
12817
- }).pipe(debounceTime(500), concatMap(() => from(navigator.mediaDevices.enumerateDevices())), shareReplay(1));
12818
- const audioDevices$ = merge(getDevices(audioDeviceConstraints), deviceChange$).pipe(shareReplay(1));
12819
- const videoDevices$ = merge(getDevices(videoDeviceConstraints), deviceChange$).pipe(shareReplay(1));
12820
- /**
12821
- * Prompts the user for a permission to use audio devices (if not already granted) and lists the available 'audioinput' devices, if devices are added/removed the list is updated.
12822
- *
12823
- * @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.
12824
- * @returns
12825
- */
12826
- const getAudioDevices = () => audioDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'audioinput')));
12827
- /**
12828
- * Prompts the user for a permission to use video devices (if not already granted) and lists the available 'videoinput' devices, if devices are added/removed the list is updated.
12829
- *
12830
- * @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.
12831
- * @returns
12832
- */
12833
- const getVideoDevices = () => videoDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'videoinput' && d.deviceId.length)));
12834
- /**
12835
- * Prompts the user for a permission to use audio devices (if not already granted) and lists the available 'audiooutput' devices, if devices are added/removed the list is updated. Selecting 'audiooutput' device only makes sense if [the browser has support for changing audio output on 'audio' elements](#checkifaudiooutputchangesupported)
12836
- *
12837
- * @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.
12838
- * @returns
12839
- */
12840
- const getAudioOutputDevices = () => {
12841
- return audioDevices$.pipe(map$2((values) => values.filter((d) => d.kind === 'audiooutput')));
12842
- };
12843
- const getStream = (constraints) => __awaiter(void 0, void 0, void 0, function* () {
12844
- try {
12845
- return yield navigator.mediaDevices.getUserMedia(constraints);
12846
- }
12847
- catch (e) {
12848
- getLogger(['devices'])('error', `Failed get user media`, {
12849
- error: e,
12850
- constraints: constraints,
12851
- });
12852
- throw e;
12853
- }
12854
- });
12855
- /**
12856
- * Returns an audio media stream that fulfills the given constraints.
12857
- * If no constraints are provided, it uses the browser's default ones.
12858
- *
12859
- * @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.
12860
- * @param trackConstraints the constraints to use when requesting the stream.
12861
- * @returns the new `MediaStream` fulfilling the given constraints.
12862
- */
12863
- const getAudioStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, function* () {
12864
- const constraints = {
12865
- audio: Object.assign(Object.assign({}, audioDeviceConstraints.audio), trackConstraints),
12866
- };
12867
- return getStream(constraints);
12868
- });
12869
- /**
12870
- * Returns a video media stream that fulfills the given constraints.
12871
- * If no constraints are provided, it uses the browser's default ones.
12872
- *
12873
- * @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.
12874
- * @param trackConstraints the constraints to use when requesting the stream.
12875
- * @returns a new `MediaStream` fulfilling the given constraints.
12876
- */
12877
- const getVideoStream = (trackConstraints) => __awaiter(void 0, void 0, void 0, function* () {
12878
- const constraints = {
12879
- video: Object.assign(Object.assign({}, videoDeviceConstraints.video), trackConstraints),
12880
- };
12881
- return getStream(constraints);
12882
- });
12883
- /**
12884
- * Prompts the user for a permission to share a screen.
12885
- * If the user grants the permission, a screen sharing stream is returned. Throws otherwise.
12886
- *
12887
- * The callers of this API are responsible to handle the possible errors.
12888
- *
12889
- * @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.
12890
- *
12891
- * @param options any additional options to pass to the [`getDisplayMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) API.
12892
- */
12893
- const getScreenShareStream = (options) => __awaiter(void 0, void 0, void 0, function* () {
12894
- try {
12895
- return yield navigator.mediaDevices.getDisplayMedia(Object.assign({ video: true, audio: false }, options));
12896
- }
12897
- catch (e) {
12898
- getLogger(['devices'])('error', 'Failed to get screen share stream', e);
12899
- throw e;
12900
- }
12901
- });
12902
- const watchForDisconnectedDevice = (kind, deviceId$) => {
12903
- let devices$;
12904
- switch (kind) {
12905
- case 'audioinput':
12906
- devices$ = getAudioDevices();
12907
- break;
12908
- case 'videoinput':
12909
- devices$ = getVideoDevices();
12910
- break;
12911
- case 'audiooutput':
12912
- devices$ = getAudioOutputDevices();
12913
- break;
12914
- }
12915
- return combineLatest([devices$, deviceId$]).pipe(filter(([devices, deviceId]) => !!deviceId && !devices.find((d) => d.deviceId === deviceId)), map$2(() => true));
12916
- };
12917
- /**
12918
- * Notifies the subscriber if a given 'audioinput' device is disconnected
12919
- *
12920
- * @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.
12921
- * @param deviceId$ an Observable that specifies which device to watch for
12922
- * @returns
12923
- */
12924
- const watchForDisconnectedAudioDevice = (deviceId$) => {
12925
- return watchForDisconnectedDevice('audioinput', deviceId$);
12926
- };
12927
- /**
12928
- * Notifies the subscriber if a given 'videoinput' device is disconnected
12929
- *
12930
- * @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.
12931
- * @param deviceId$ an Observable that specifies which device to watch for
12932
- * @returns
12933
- */
12934
- const watchForDisconnectedVideoDevice = (deviceId$) => {
12935
- return watchForDisconnectedDevice('videoinput', deviceId$);
12936
- };
12937
- /**
12938
- * Notifies the subscriber if a given 'audiooutput' device is disconnected
12939
- *
12940
- * @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.
12941
- * @param deviceId$ an Observable that specifies which device to watch for
12942
- * @returns
12943
- */
12944
- const watchForDisconnectedAudioOutputDevice = (deviceId$) => {
12945
- return watchForDisconnectedDevice('audiooutput', deviceId$);
12946
- };
12947
- const watchForAddedDefaultDevice = (kind) => {
12948
- let devices$;
12949
- switch (kind) {
12950
- case 'audioinput':
12951
- devices$ = getAudioDevices();
12952
- break;
12953
- case 'videoinput':
12954
- devices$ = getVideoDevices();
12955
- break;
12956
- case 'audiooutput':
12957
- devices$ = getAudioOutputDevices();
12958
- break;
12959
- default:
12960
- throw new Error('Unknown MediaDeviceKind', kind);
12961
- }
12962
- return devices$.pipe(pairwise(), filter(([prev, current]) => {
12963
- const prevDefault = prev.find((device) => device.deviceId === 'default');
12964
- const currentDefault = current.find((device) => device.deviceId === 'default');
12965
- return !!(current.length > prev.length &&
12966
- prevDefault &&
12967
- currentDefault &&
12968
- prevDefault.groupId !== currentDefault.groupId);
12969
- }), map$2(() => true));
12970
- };
12971
- /**
12972
- * Notifies the subscriber about newly added default audio input device.
12973
- * @returns Observable<boolean>
12974
- */
12975
- const watchForAddedDefaultAudioDevice = () => watchForAddedDefaultDevice('audioinput');
12976
- /**
12977
- * Notifies the subscriber about newly added default audio output device.
12978
- * @returns Observable<boolean>
12979
- */
12980
- const watchForAddedDefaultAudioOutputDevice = () => watchForAddedDefaultDevice('audiooutput');
12981
- /**
12982
- * Notifies the subscriber about newly added default video input device.
12983
- * @returns Observable<boolean>
12984
- */
12985
- const watchForAddedDefaultVideoDevice = () => watchForAddedDefaultDevice('videoinput');
12986
- /**
12987
- * Deactivates MediaStream (stops and removes tracks) to be later garbage collected
12988
- *
12989
- * @param stream MediaStream
12990
- * @returns void
12991
- */
12992
- const disposeOfMediaStream = (stream) => {
12993
- if (!stream.active)
12994
- return;
12995
- stream.getTracks().forEach((track) => {
12996
- track.stop();
12997
- stream.removeTrack(track);
12998
- });
12999
- // @ts-expect-error release() is present in react-native-webrtc and must be called to dispose the stream
13000
- if (typeof stream.release === 'function') {
13001
- // @ts-expect-error
13002
- stream.release();
13003
- }
13004
- };
13005
-
13006
13412
  const DETECTION_FREQUENCY_IN_MS = 500;
13007
13413
  const AUDIO_LEVEL_THRESHOLD = 150;
13008
13414
  const FFT_SIZE = 128;
@@ -13083,5 +13489,5 @@ var browsers = /*#__PURE__*/Object.freeze({
13083
13489
  isSafari: isSafari
13084
13490
  });
13085
13491
 
13086
- export { AudioSettingsDefaultDeviceEnum, AudioSettingsRequestDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, 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, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
13492
+ export { AudioSettingsDefaultDeviceEnum, AudioSettingsRequestDefaultDeviceEnum, browsers as Browsers, Call, CallState, CallType, CallTypes, CallingState, CameraManager, CreateDeviceRequestPushProviderEnum, DebounceType, ErrorFromResponse, InputMediaDeviceManager, InputMediaDeviceManagerState, MicrophoneManager, OwnCapability, RecordSettingsModeEnum, RecordSettingsQualityEnum, RecordSettingsRequestModeEnum, RecordSettingsRequestQualityEnum, rxUtils as RxUtils, events as SfuEvents, models as SfuModels, 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, isStreamVideoLocalParticipant, livestreamOrAudioRoomSortPreset, logLevels, logToConsole, name, noopComparator, pinned, publishingAudio, publishingVideo, reactionType, role, screenSharing, setDeviceInfo, setLogLevel, setLogger, setOSInfo, setSdkInfo, speakerLayoutSortPreset, speaking, watchForAddedDefaultAudioDevice, watchForAddedDefaultAudioOutputDevice, watchForAddedDefaultVideoDevice, watchForDisconnectedAudioDevice, watchForDisconnectedAudioOutputDevice, watchForDisconnectedVideoDevice };
13087
13493
  //# sourceMappingURL=index.browser.es.js.map