@stream-io/video-client 0.3.12 → 0.3.13

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/dist/index.cjs.js CHANGED
@@ -9533,15 +9533,26 @@ class DynascaleManager {
9533
9533
  }
9534
9534
  });
9535
9535
  });
9536
- const sinkIdSubscription = this.call.state.localParticipant$.subscribe((p) => {
9537
- if (p && p.audioOutputDeviceId && 'setSinkId' in audioElement) {
9536
+ const sinkIdSubscription = rxjs.combineLatest([
9537
+ this.call.state.localParticipant$,
9538
+ this.call.speaker.state.selectedDevice$,
9539
+ ]).subscribe(([p, selectedDevice]) => {
9540
+ var _a;
9541
+ const deviceId = ((_a = getSdkInfo()) === null || _a === void 0 ? void 0 : _a.type) === SdkType.REACT
9542
+ ? p === null || p === void 0 ? void 0 : p.audioOutputDeviceId
9543
+ : selectedDevice;
9544
+ if ('setSinkId' in audioElement) {
9538
9545
  // @ts-expect-error setSinkId is not yet in the lib
9539
- audioElement.setSinkId(p.audioOutputDeviceId);
9546
+ audioElement.setSinkId(deviceId);
9540
9547
  }
9541
9548
  });
9549
+ const volumeSubscription = this.call.speaker.state.volume$.subscribe((volume) => {
9550
+ audioElement.volume = volume;
9551
+ });
9542
9552
  audioElement.autoplay = true;
9543
9553
  return () => {
9544
9554
  sinkIdSubscription.unsubscribe();
9555
+ volumeSubscription.unsubscribe();
9545
9556
  updateMediaStreamSubscription.unsubscribe();
9546
9557
  };
9547
9558
  };
@@ -9688,6 +9699,127 @@ const CallTypes = new CallTypesRegistry([
9688
9699
  }),
9689
9700
  ]);
9690
9701
 
9702
+ class InputMediaDeviceManagerState {
9703
+ constructor(disableMode = 'stop-tracks') {
9704
+ this.disableMode = disableMode;
9705
+ this.statusSubject = new rxjs.BehaviorSubject(undefined);
9706
+ this.mediaStreamSubject = new rxjs.BehaviorSubject(undefined);
9707
+ this.selectedDeviceSubject = new rxjs.BehaviorSubject(undefined);
9708
+ /**
9709
+ * Gets the current value of an observable, or undefined if the observable has
9710
+ * not emitted a value yet.
9711
+ *
9712
+ * @param observable$ the observable to get the value from.
9713
+ */
9714
+ this.getCurrentValue = getCurrentValue;
9715
+ /**
9716
+ * Updates the value of the provided Subject.
9717
+ * An `update` can either be a new value or a function which takes
9718
+ * the current value and returns a new value.
9719
+ *
9720
+ * @internal
9721
+ *
9722
+ * @param subject the subject to update.
9723
+ * @param update the update to apply to the subject.
9724
+ * @return the updated value.
9725
+ */
9726
+ this.setCurrentValue = setCurrentValue;
9727
+ this.mediaStream$ = this.mediaStreamSubject.asObservable();
9728
+ this.selectedDevice$ = this.selectedDeviceSubject
9729
+ .asObservable()
9730
+ .pipe(rxjs.distinctUntilChanged());
9731
+ this.status$ = this.statusSubject
9732
+ .asObservable()
9733
+ .pipe(rxjs.distinctUntilChanged());
9734
+ }
9735
+ /**
9736
+ * The device status
9737
+ */
9738
+ get status() {
9739
+ return this.getCurrentValue(this.status$);
9740
+ }
9741
+ /**
9742
+ * The currently selected device
9743
+ */
9744
+ get selectedDevice() {
9745
+ return this.getCurrentValue(this.selectedDevice$);
9746
+ }
9747
+ /**
9748
+ * The current media stream, or `undefined` if the device is currently disabled.
9749
+ */
9750
+ get mediaStream() {
9751
+ return this.getCurrentValue(this.mediaStream$);
9752
+ }
9753
+ /**
9754
+ * @internal
9755
+ * @param status
9756
+ */
9757
+ setStatus(status) {
9758
+ this.setCurrentValue(this.statusSubject, status);
9759
+ }
9760
+ /**
9761
+ * @internal
9762
+ * @param stream
9763
+ */
9764
+ setMediaStream(stream) {
9765
+ this.setCurrentValue(this.mediaStreamSubject, stream);
9766
+ if (stream) {
9767
+ this.setDevice(this.getDeviceIdFromStream(stream));
9768
+ }
9769
+ }
9770
+ /**
9771
+ * @internal
9772
+ * @param stream
9773
+ */
9774
+ setDevice(deviceId) {
9775
+ this.setCurrentValue(this.selectedDeviceSubject, deviceId);
9776
+ }
9777
+ }
9778
+
9779
+ class CameraManagerState extends InputMediaDeviceManagerState {
9780
+ constructor() {
9781
+ super('stop-tracks');
9782
+ this.directionSubject = new rxjs.BehaviorSubject(undefined);
9783
+ this.direction$ = this.directionSubject
9784
+ .asObservable()
9785
+ .pipe(rxjs.distinctUntilChanged());
9786
+ }
9787
+ /**
9788
+ * The preferred camera direction
9789
+ * front - means the camera facing the user
9790
+ * back - means the camera facing the environment
9791
+ */
9792
+ get direction() {
9793
+ return this.getCurrentValue(this.direction$);
9794
+ }
9795
+ /**
9796
+ * @internal
9797
+ */
9798
+ setDirection(direction) {
9799
+ this.setCurrentValue(this.directionSubject, direction);
9800
+ }
9801
+ /**
9802
+ * @internal
9803
+ */
9804
+ setMediaStream(stream) {
9805
+ var _a;
9806
+ super.setMediaStream(stream);
9807
+ if (stream) {
9808
+ // RN getSettings() doesn't return facingMode, so we don't verify camera direction
9809
+ const direction = isReactNative()
9810
+ ? this.direction
9811
+ : ((_a = stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().facingMode) === 'environment'
9812
+ ? 'back'
9813
+ : 'front';
9814
+ this.setDirection(direction);
9815
+ }
9816
+ }
9817
+ getDeviceIdFromStream(stream) {
9818
+ var _a;
9819
+ return (_a = stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
9820
+ }
9821
+ }
9822
+
9691
9823
  const getDevices = (constraints) => {
9692
9824
  return new rxjs.Observable((subscriber) => {
9693
9825
  navigator.mediaDevices
@@ -10083,127 +10215,6 @@ class InputMediaDeviceManager {
10083
10215
  }
10084
10216
  }
10085
10217
 
10086
- class InputMediaDeviceManagerState {
10087
- constructor(disableMode = 'stop-tracks') {
10088
- this.disableMode = disableMode;
10089
- this.statusSubject = new rxjs.BehaviorSubject(undefined);
10090
- this.mediaStreamSubject = new rxjs.BehaviorSubject(undefined);
10091
- this.selectedDeviceSubject = new rxjs.BehaviorSubject(undefined);
10092
- /**
10093
- * Gets the current value of an observable, or undefined if the observable has
10094
- * not emitted a value yet.
10095
- *
10096
- * @param observable$ the observable to get the value from.
10097
- */
10098
- this.getCurrentValue = getCurrentValue;
10099
- /**
10100
- * Updates the value of the provided Subject.
10101
- * An `update` can either be a new value or a function which takes
10102
- * the current value and returns a new value.
10103
- *
10104
- * @internal
10105
- *
10106
- * @param subject the subject to update.
10107
- * @param update the update to apply to the subject.
10108
- * @return the updated value.
10109
- */
10110
- this.setCurrentValue = setCurrentValue;
10111
- this.mediaStream$ = this.mediaStreamSubject.asObservable();
10112
- this.selectedDevice$ = this.selectedDeviceSubject
10113
- .asObservable()
10114
- .pipe(rxjs.distinctUntilChanged());
10115
- this.status$ = this.statusSubject
10116
- .asObservable()
10117
- .pipe(rxjs.distinctUntilChanged());
10118
- }
10119
- /**
10120
- * The device status
10121
- */
10122
- get status() {
10123
- return this.getCurrentValue(this.status$);
10124
- }
10125
- /**
10126
- * The currently selected device
10127
- */
10128
- get selectedDevice() {
10129
- return this.getCurrentValue(this.selectedDevice$);
10130
- }
10131
- /**
10132
- * The current media stream, or `undefined` if the device is currently disabled.
10133
- */
10134
- get mediaStream() {
10135
- return this.getCurrentValue(this.mediaStream$);
10136
- }
10137
- /**
10138
- * @internal
10139
- * @param status
10140
- */
10141
- setStatus(status) {
10142
- this.setCurrentValue(this.statusSubject, status);
10143
- }
10144
- /**
10145
- * @internal
10146
- * @param stream
10147
- */
10148
- setMediaStream(stream) {
10149
- this.setCurrentValue(this.mediaStreamSubject, stream);
10150
- if (stream) {
10151
- this.setDevice(this.getDeviceIdFromStream(stream));
10152
- }
10153
- }
10154
- /**
10155
- * @internal
10156
- * @param stream
10157
- */
10158
- setDevice(deviceId) {
10159
- this.setCurrentValue(this.selectedDeviceSubject, deviceId);
10160
- }
10161
- }
10162
-
10163
- class CameraManagerState extends InputMediaDeviceManagerState {
10164
- constructor() {
10165
- super('stop-tracks');
10166
- this.directionSubject = new rxjs.BehaviorSubject(undefined);
10167
- this.direction$ = this.directionSubject
10168
- .asObservable()
10169
- .pipe(rxjs.distinctUntilChanged());
10170
- }
10171
- /**
10172
- * The preferred camera direction
10173
- * front - means the camera facing the user
10174
- * back - means the camera facing the environment
10175
- */
10176
- get direction() {
10177
- return this.getCurrentValue(this.direction$);
10178
- }
10179
- /**
10180
- * @internal
10181
- */
10182
- setDirection(direction) {
10183
- this.setCurrentValue(this.directionSubject, direction);
10184
- }
10185
- /**
10186
- * @internal
10187
- */
10188
- setMediaStream(stream) {
10189
- var _a;
10190
- super.setMediaStream(stream);
10191
- if (stream) {
10192
- // RN getSettings() doesn't return facingMode, so we don't verify camera direction
10193
- const direction = isReactNative()
10194
- ? this.direction
10195
- : ((_a = stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().facingMode) === 'environment'
10196
- ? 'back'
10197
- : 'front';
10198
- this.setDirection(direction);
10199
- }
10200
- }
10201
- getDeviceIdFromStream(stream) {
10202
- var _a;
10203
- return (_a = stream.getVideoTracks()[0]) === null || _a === void 0 ? void 0 : _a.getSettings().deviceId;
10204
- }
10205
- }
10206
-
10207
10218
  class CameraManager extends InputMediaDeviceManager {
10208
10219
  constructor(call) {
10209
10220
  super(call, new CameraManagerState());
@@ -10327,6 +10338,116 @@ class MicrophoneManager extends InputMediaDeviceManager {
10327
10338
  }
10328
10339
  }
10329
10340
 
10341
+ class SpeakerState {
10342
+ constructor() {
10343
+ this.selectedDeviceSubject = new rxjs.BehaviorSubject('');
10344
+ this.volumeSubject = new rxjs.BehaviorSubject(1);
10345
+ /**
10346
+ * [Tells if the browser supports audio output change on 'audio' elements](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId).
10347
+ */
10348
+ this.isDeviceSelectionSupported = checkIfAudioOutputChangeSupported();
10349
+ /**
10350
+ * Gets the current value of an observable, or undefined if the observable has
10351
+ * not emitted a value yet.
10352
+ *
10353
+ * @param observable$ the observable to get the value from.
10354
+ */
10355
+ this.getCurrentValue = getCurrentValue;
10356
+ /**
10357
+ * Updates the value of the provided Subject.
10358
+ * An `update` can either be a new value or a function which takes
10359
+ * the current value and returns a new value.
10360
+ *
10361
+ * @internal
10362
+ *
10363
+ * @param subject the subject to update.
10364
+ * @param update the update to apply to the subject.
10365
+ * @return the updated value.
10366
+ */
10367
+ this.setCurrentValue = setCurrentValue;
10368
+ this.selectedDevice$ = this.selectedDeviceSubject
10369
+ .asObservable()
10370
+ .pipe(rxjs.distinctUntilChanged());
10371
+ this.volume$ = this.volumeSubject
10372
+ .asObservable()
10373
+ .pipe(rxjs.distinctUntilChanged());
10374
+ }
10375
+ /**
10376
+ * The currently selected device
10377
+ *
10378
+ * Note: this feature is not supported in React Native
10379
+ */
10380
+ get selectedDevice() {
10381
+ return this.getCurrentValue(this.selectedDevice$);
10382
+ }
10383
+ /**
10384
+ * The currently selected volume
10385
+ *
10386
+ * Note: this feature is not supported in React Native
10387
+ */
10388
+ get volume() {
10389
+ return this.getCurrentValue(this.volume$);
10390
+ }
10391
+ /**
10392
+ * @internal
10393
+ * @param deviceId
10394
+ */
10395
+ setDevice(deviceId) {
10396
+ this.setCurrentValue(this.selectedDeviceSubject, deviceId);
10397
+ }
10398
+ /**
10399
+ * @internal
10400
+ * @param volume
10401
+ */
10402
+ setVolume(volume) {
10403
+ this.setCurrentValue(this.volumeSubject, volume);
10404
+ }
10405
+ }
10406
+
10407
+ class SpeakerManager {
10408
+ constructor() {
10409
+ this.state = new SpeakerState();
10410
+ }
10411
+ /**
10412
+ * Lists the available audio output devices
10413
+ *
10414
+ * Note: It prompts the user for a permission to use devices (if not already granted)
10415
+ *
10416
+ * @returns an Observable that will be updated if a device is connected or disconnected
10417
+ */
10418
+ listDevices() {
10419
+ return getAudioOutputDevices();
10420
+ }
10421
+ /**
10422
+ * Select device
10423
+ *
10424
+ * Note: this method is not supported in React Native
10425
+ *
10426
+ * @param deviceId empty string means the system default
10427
+ */
10428
+ select(deviceId) {
10429
+ if (isReactNative()) {
10430
+ throw new Error('This feature is not supported in React Native');
10431
+ }
10432
+ this.state.setDevice(deviceId);
10433
+ }
10434
+ /**
10435
+ * Set the volume of the audio elements
10436
+ * @param volume a number between 0 and 1
10437
+ *
10438
+ * Note: this method is not supported in React Native
10439
+ */
10440
+ setVolume(volume) {
10441
+ if (isReactNative()) {
10442
+ throw new Error('This feature is not supported in React Native');
10443
+ }
10444
+ if (volume && (volume < 0 || volume > 1)) {
10445
+ throw new Error('Volume must be between 0 and 1');
10446
+ }
10447
+ this.state.setVolume(volume);
10448
+ }
10449
+ }
10450
+
10330
10451
  /**
10331
10452
  * An object representation of a `Call`.
10332
10453
  */
@@ -11001,6 +11122,8 @@ class Call {
11001
11122
  *
11002
11123
  *
11003
11124
  * @param deviceId the selected device, `undefined` means the user wants to use the system's default audio output
11125
+ *
11126
+ * @deprecated use `call.speaker` instead
11004
11127
  */
11005
11128
  this.setAudioOutputDevice = (deviceId) => {
11006
11129
  if (!this.sfuClient)
@@ -11475,6 +11598,7 @@ class Call {
11475
11598
  this.leaveCallHooks.add(createSubscription(this.trackSubscriptionsSubject.pipe(rxjs.debounce((v) => rxjs.timer(v.type)), rxjs.map((v) => v.data)), (subscriptions) => { var _a; return (_a = this.sfuClient) === null || _a === void 0 ? void 0 : _a.updateSubscriptions(subscriptions); }));
11476
11599
  this.camera = new CameraManager(this);
11477
11600
  this.microphone = new MicrophoneManager(this);
11601
+ this.speaker = new SpeakerManager();
11478
11602
  }
11479
11603
  registerEffects() {
11480
11604
  this.leaveCallHooks.add(
@@ -12765,7 +12889,7 @@ class WSConnectionFallback {
12765
12889
  }
12766
12890
  }
12767
12891
 
12768
- const version = '0.3.12';
12892
+ const version = '0.3.13';
12769
12893
 
12770
12894
  const logger = getLogger(['location']);
12771
12895
  const HINT_URL = `https://hint.stream-io-video.com/`;