@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/CHANGELOG.md +7 -0
- package/dist/index.browser.es.js +250 -126
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +249 -125
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +250 -126
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +6 -1
- package/dist/src/devices/SpeakerManager.d.ts +28 -0
- package/dist/src/devices/SpeakerState.d.ts +64 -0
- package/dist/src/devices/__tests__/SpeakerManager.test.d.ts +1 -0
- package/dist/src/types.d.ts +2 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Call.ts +12 -1
- package/src/devices/SpeakerManager.ts +50 -0
- package/src/devices/SpeakerState.ts +90 -0
- package/src/devices/__tests__/SpeakerManager.test.ts +66 -0
- package/src/helpers/DynascaleManager.ts +25 -7
- package/src/helpers/__tests__/DynascaleManager.test.ts +30 -2
- package/src/types.ts +2 -0
package/dist/index.cjs.js
CHANGED
|
@@ -9533,15 +9533,26 @@ class DynascaleManager {
|
|
|
9533
9533
|
}
|
|
9534
9534
|
});
|
|
9535
9535
|
});
|
|
9536
|
-
const sinkIdSubscription =
|
|
9537
|
-
|
|
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(
|
|
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.
|
|
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/`;
|