@stream-io/video-client 1.9.2 → 1.10.0
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 +14 -0
- package/dist/index.browser.es.js +260 -26
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +260 -26
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +260 -26
- package/dist/index.es.js.map +1 -1
- package/dist/src/gen/video/sfu/models/models.d.ts +134 -0
- package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +27 -1
- package/dist/src/stats/SfuStatsReporter.d.ts +13 -1
- package/dist/src/store/rxUtils.d.ts +2 -1
- package/package.json +1 -1
- package/src/Call.ts +3 -0
- package/src/coordinator/connection/client.ts +1 -1
- package/src/devices/InputMediaDeviceManager.ts +12 -4
- package/src/devices/__tests__/CameraManager.test.ts +2 -2
- package/src/devices/__tests__/InputMediaDeviceManager.test.ts +1 -1
- package/src/devices/devices.ts +32 -12
- package/src/gen/video/sfu/models/models.ts +192 -0
- package/src/gen/video/sfu/signal_rpc/signal.ts +48 -0
- package/src/stats/SfuStatsReporter.ts +83 -5
- package/src/store/rxUtils.ts +6 -5
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
|
+
## [1.10.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.9.3...@stream-io/video-client-1.10.0) (2024-10-30)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* report input devices in call stats ([#1533](https://github.com/GetStream/stream-video-js/issues/1533)) ([f34fe0a](https://github.com/GetStream/stream-video-js/commit/f34fe0a0444903099565ae55a9639e39fc19b76c))
|
|
11
|
+
|
|
12
|
+
## [1.9.3](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.9.2...@stream-io/video-client-1.9.3) (2024-10-28)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* make device selection by device id exact ([#1538](https://github.com/GetStream/stream-video-js/issues/1538)) ([6274cac](https://github.com/GetStream/stream-video-js/commit/6274cac2ecf155aa6ce0c6d764229e0e9cd39a6a))
|
|
18
|
+
|
|
5
19
|
## [1.9.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.9.1...@stream-io/video-client-1.9.2) (2024-10-21)
|
|
6
20
|
|
|
7
21
|
|
package/dist/index.browser.es.js
CHANGED
|
@@ -841,6 +841,76 @@ var WebsocketReconnectStrategy;
|
|
|
841
841
|
*/
|
|
842
842
|
WebsocketReconnectStrategy[WebsocketReconnectStrategy["MIGRATE"] = 4] = "MIGRATE";
|
|
843
843
|
})(WebsocketReconnectStrategy || (WebsocketReconnectStrategy = {}));
|
|
844
|
+
/**
|
|
845
|
+
* AndroidThermalState is reported by the Android API. The full list of values is documented here
|
|
846
|
+
* https://developer.android.com/reference/android/os/PowerManager.html#getCurrentThermalStatus()
|
|
847
|
+
*
|
|
848
|
+
* @generated from protobuf enum stream.video.sfu.models.AndroidThermalState
|
|
849
|
+
*/
|
|
850
|
+
var AndroidThermalState;
|
|
851
|
+
(function (AndroidThermalState) {
|
|
852
|
+
/**
|
|
853
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_UNSPECIFIED = 0;
|
|
854
|
+
*/
|
|
855
|
+
AndroidThermalState[AndroidThermalState["UNSPECIFIED"] = 0] = "UNSPECIFIED";
|
|
856
|
+
/**
|
|
857
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_NONE = 1;
|
|
858
|
+
*/
|
|
859
|
+
AndroidThermalState[AndroidThermalState["NONE"] = 1] = "NONE";
|
|
860
|
+
/**
|
|
861
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_LIGHT = 2;
|
|
862
|
+
*/
|
|
863
|
+
AndroidThermalState[AndroidThermalState["LIGHT"] = 2] = "LIGHT";
|
|
864
|
+
/**
|
|
865
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_MODERATE = 3;
|
|
866
|
+
*/
|
|
867
|
+
AndroidThermalState[AndroidThermalState["MODERATE"] = 3] = "MODERATE";
|
|
868
|
+
/**
|
|
869
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_SEVERE = 4;
|
|
870
|
+
*/
|
|
871
|
+
AndroidThermalState[AndroidThermalState["SEVERE"] = 4] = "SEVERE";
|
|
872
|
+
/**
|
|
873
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_CRITICAL = 5;
|
|
874
|
+
*/
|
|
875
|
+
AndroidThermalState[AndroidThermalState["CRITICAL"] = 5] = "CRITICAL";
|
|
876
|
+
/**
|
|
877
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_EMERGENCY = 6;
|
|
878
|
+
*/
|
|
879
|
+
AndroidThermalState[AndroidThermalState["EMERGENCY"] = 6] = "EMERGENCY";
|
|
880
|
+
/**
|
|
881
|
+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_SHUTDOWN = 7;
|
|
882
|
+
*/
|
|
883
|
+
AndroidThermalState[AndroidThermalState["SHUTDOWN"] = 7] = "SHUTDOWN";
|
|
884
|
+
})(AndroidThermalState || (AndroidThermalState = {}));
|
|
885
|
+
/**
|
|
886
|
+
* AppleThermalState is the thermal state as reported by Apple devices when available or applicable to the platform.
|
|
887
|
+
* The full list of states (enum) is available here: https://developer.apple.com/documentation/foundation/processinfo/thermalstate
|
|
888
|
+
*
|
|
889
|
+
* @generated from protobuf enum stream.video.sfu.models.AppleThermalState
|
|
890
|
+
*/
|
|
891
|
+
var AppleThermalState;
|
|
892
|
+
(function (AppleThermalState) {
|
|
893
|
+
/**
|
|
894
|
+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_UNSPECIFIED = 0;
|
|
895
|
+
*/
|
|
896
|
+
AppleThermalState[AppleThermalState["UNSPECIFIED"] = 0] = "UNSPECIFIED";
|
|
897
|
+
/**
|
|
898
|
+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_NOMINAL = 1;
|
|
899
|
+
*/
|
|
900
|
+
AppleThermalState[AppleThermalState["NOMINAL"] = 1] = "NOMINAL";
|
|
901
|
+
/**
|
|
902
|
+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_FAIR = 2;
|
|
903
|
+
*/
|
|
904
|
+
AppleThermalState[AppleThermalState["FAIR"] = 2] = "FAIR";
|
|
905
|
+
/**
|
|
906
|
+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_SERIOUS = 3;
|
|
907
|
+
*/
|
|
908
|
+
AppleThermalState[AppleThermalState["SERIOUS"] = 3] = "SERIOUS";
|
|
909
|
+
/**
|
|
910
|
+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_CRITICAL = 4;
|
|
911
|
+
*/
|
|
912
|
+
AppleThermalState[AppleThermalState["CRITICAL"] = 4] = "CRITICAL";
|
|
913
|
+
})(AppleThermalState || (AppleThermalState = {}));
|
|
844
914
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
845
915
|
class CallState$Type extends MessageType {
|
|
846
916
|
constructor() {
|
|
@@ -1279,9 +1349,92 @@ class CallGrants$Type extends MessageType {
|
|
|
1279
1349
|
* @generated MessageType for protobuf message stream.video.sfu.models.CallGrants
|
|
1280
1350
|
*/
|
|
1281
1351
|
const CallGrants = new CallGrants$Type();
|
|
1352
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
1353
|
+
class InputDevices$Type extends MessageType {
|
|
1354
|
+
constructor() {
|
|
1355
|
+
super('stream.video.sfu.models.InputDevices', [
|
|
1356
|
+
{
|
|
1357
|
+
no: 1,
|
|
1358
|
+
name: 'available_devices',
|
|
1359
|
+
kind: 'scalar',
|
|
1360
|
+
repeat: 2 /*RepeatType.UNPACKED*/,
|
|
1361
|
+
T: 9 /*ScalarType.STRING*/,
|
|
1362
|
+
},
|
|
1363
|
+
{
|
|
1364
|
+
no: 2,
|
|
1365
|
+
name: 'current_device',
|
|
1366
|
+
kind: 'scalar',
|
|
1367
|
+
T: 9 /*ScalarType.STRING*/,
|
|
1368
|
+
},
|
|
1369
|
+
{ no: 3, name: 'is_permitted', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
|
|
1370
|
+
]);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* @generated MessageType for protobuf message stream.video.sfu.models.InputDevices
|
|
1375
|
+
*/
|
|
1376
|
+
const InputDevices = new InputDevices$Type();
|
|
1377
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
1378
|
+
class AndroidState$Type extends MessageType {
|
|
1379
|
+
constructor() {
|
|
1380
|
+
super('stream.video.sfu.models.AndroidState', [
|
|
1381
|
+
{
|
|
1382
|
+
no: 1,
|
|
1383
|
+
name: 'thermal_state',
|
|
1384
|
+
kind: 'enum',
|
|
1385
|
+
T: () => [
|
|
1386
|
+
'stream.video.sfu.models.AndroidThermalState',
|
|
1387
|
+
AndroidThermalState,
|
|
1388
|
+
'ANDROID_THERMAL_STATE_',
|
|
1389
|
+
],
|
|
1390
|
+
},
|
|
1391
|
+
{
|
|
1392
|
+
no: 2,
|
|
1393
|
+
name: 'is_power_saver_mode',
|
|
1394
|
+
kind: 'scalar',
|
|
1395
|
+
T: 8 /*ScalarType.BOOL*/,
|
|
1396
|
+
},
|
|
1397
|
+
]);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* @generated MessageType for protobuf message stream.video.sfu.models.AndroidState
|
|
1402
|
+
*/
|
|
1403
|
+
const AndroidState = new AndroidState$Type();
|
|
1404
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
1405
|
+
class AppleState$Type extends MessageType {
|
|
1406
|
+
constructor() {
|
|
1407
|
+
super('stream.video.sfu.models.AppleState', [
|
|
1408
|
+
{
|
|
1409
|
+
no: 1,
|
|
1410
|
+
name: 'thermal_state',
|
|
1411
|
+
kind: 'enum',
|
|
1412
|
+
T: () => [
|
|
1413
|
+
'stream.video.sfu.models.AppleThermalState',
|
|
1414
|
+
AppleThermalState,
|
|
1415
|
+
'APPLE_THERMAL_STATE_',
|
|
1416
|
+
],
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
no: 2,
|
|
1420
|
+
name: 'is_low_power_mode_enabled',
|
|
1421
|
+
kind: 'scalar',
|
|
1422
|
+
T: 8 /*ScalarType.BOOL*/,
|
|
1423
|
+
},
|
|
1424
|
+
]);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
/**
|
|
1428
|
+
* @generated MessageType for protobuf message stream.video.sfu.models.AppleState
|
|
1429
|
+
*/
|
|
1430
|
+
const AppleState = new AppleState$Type();
|
|
1282
1431
|
|
|
1283
1432
|
var models = /*#__PURE__*/Object.freeze({
|
|
1284
1433
|
__proto__: null,
|
|
1434
|
+
AndroidState: AndroidState,
|
|
1435
|
+
get AndroidThermalState () { return AndroidThermalState; },
|
|
1436
|
+
AppleState: AppleState,
|
|
1437
|
+
get AppleThermalState () { return AppleThermalState; },
|
|
1285
1438
|
Browser: Browser,
|
|
1286
1439
|
Call: Call$1,
|
|
1287
1440
|
get CallEndedReason () { return CallEndedReason; },
|
|
@@ -1295,6 +1448,7 @@ var models = /*#__PURE__*/Object.freeze({
|
|
|
1295
1448
|
get ErrorCode () { return ErrorCode; },
|
|
1296
1449
|
get GoAwayReason () { return GoAwayReason; },
|
|
1297
1450
|
ICETrickle: ICETrickle$1,
|
|
1451
|
+
InputDevices: InputDevices,
|
|
1298
1452
|
OS: OS,
|
|
1299
1453
|
Participant: Participant,
|
|
1300
1454
|
ParticipantCount: ParticipantCount,
|
|
@@ -1394,6 +1548,22 @@ class SendStatsRequest$Type extends MessageType {
|
|
|
1394
1548
|
kind: 'scalar',
|
|
1395
1549
|
T: 9 /*ScalarType.STRING*/,
|
|
1396
1550
|
},
|
|
1551
|
+
{ no: 7, name: 'audio_devices', kind: 'message', T: () => InputDevices },
|
|
1552
|
+
{ no: 8, name: 'video_devices', kind: 'message', T: () => InputDevices },
|
|
1553
|
+
{
|
|
1554
|
+
no: 9,
|
|
1555
|
+
name: 'android',
|
|
1556
|
+
kind: 'message',
|
|
1557
|
+
oneof: 'deviceState',
|
|
1558
|
+
T: () => AndroidState,
|
|
1559
|
+
},
|
|
1560
|
+
{
|
|
1561
|
+
no: 10,
|
|
1562
|
+
name: 'apple',
|
|
1563
|
+
kind: 'message',
|
|
1564
|
+
oneof: 'deviceState',
|
|
1565
|
+
T: () => AppleState,
|
|
1566
|
+
},
|
|
1397
1567
|
]);
|
|
1398
1568
|
}
|
|
1399
1569
|
}
|
|
@@ -2938,7 +3108,7 @@ const retryable = async (rpc, signal) => {
|
|
|
2938
3108
|
return result;
|
|
2939
3109
|
};
|
|
2940
3110
|
|
|
2941
|
-
const version = "1.
|
|
3111
|
+
const version = "1.10.0";
|
|
2942
3112
|
const [major, minor, patch] = version.split('.');
|
|
2943
3113
|
let sdkInfo = {
|
|
2944
3114
|
type: SdkType.PLAIN_JAVASCRIPT,
|
|
@@ -3668,9 +3838,10 @@ const setCurrentValue = (subject, update) => {
|
|
|
3668
3838
|
*
|
|
3669
3839
|
* @param observable the observable to subscribe to.
|
|
3670
3840
|
* @param handler the handler to call when the observable emits a value.
|
|
3841
|
+
* @param onError an optional error handler.
|
|
3671
3842
|
*/
|
|
3672
|
-
const createSubscription = (observable, handler) => {
|
|
3673
|
-
const subscription = observable.subscribe(handler);
|
|
3843
|
+
const createSubscription = (observable, handler, onError = (error) => getLogger(['RxUtils'])('warn', 'An observable emitted an error', error)) => {
|
|
3844
|
+
const subscription = observable.subscribe({ next: handler, error: onError });
|
|
3674
3845
|
return () => {
|
|
3675
3846
|
subscription.unsubscribe();
|
|
3676
3847
|
};
|
|
@@ -3685,12 +3856,9 @@ const createSubscription = (observable, handler) => {
|
|
|
3685
3856
|
*/
|
|
3686
3857
|
const createSafeAsyncSubscription = (observable, handler) => {
|
|
3687
3858
|
const tag = Symbol();
|
|
3688
|
-
|
|
3859
|
+
return createSubscription(observable, (value) => {
|
|
3689
3860
|
withoutConcurrency(tag, () => handler(value));
|
|
3690
3861
|
});
|
|
3691
|
-
return () => {
|
|
3692
|
-
subscription.unsubscribe();
|
|
3693
|
-
};
|
|
3694
3862
|
};
|
|
3695
3863
|
|
|
3696
3864
|
var rxUtils = /*#__PURE__*/Object.freeze({
|
|
@@ -6960,8 +7128,38 @@ const aggregate = (stats) => {
|
|
|
6960
7128
|
};
|
|
6961
7129
|
|
|
6962
7130
|
class SfuStatsReporter {
|
|
6963
|
-
constructor(sfuClient, { options, clientDetails, subscriber, publisher }) {
|
|
7131
|
+
constructor(sfuClient, { options, clientDetails, subscriber, publisher, microphone, camera, state, }) {
|
|
6964
7132
|
this.logger = getLogger(['SfuStatsReporter']);
|
|
7133
|
+
this.inputDevices = new Map();
|
|
7134
|
+
this.observeDevice = (device, kind) => {
|
|
7135
|
+
const { hasBrowserPermission$ } = device.state;
|
|
7136
|
+
this.unsubscribeDevicePermissionsSubscription?.();
|
|
7137
|
+
this.unsubscribeDevicePermissionsSubscription = createSubscription(combineLatest([hasBrowserPermission$, this.state.ownCapabilities$]), ([hasPermission, ownCapabilities]) => {
|
|
7138
|
+
// cleanup the previous listDevices() subscription in case
|
|
7139
|
+
// permissions or capabilities have changed.
|
|
7140
|
+
// we will subscribe again if everything is in order.
|
|
7141
|
+
this.unsubscribeListDevicesSubscription?.();
|
|
7142
|
+
const hasCapability = kind === 'mic'
|
|
7143
|
+
? ownCapabilities.includes(OwnCapability.SEND_AUDIO)
|
|
7144
|
+
: ownCapabilities.includes(OwnCapability.SEND_VIDEO);
|
|
7145
|
+
if (!hasPermission || !hasCapability) {
|
|
7146
|
+
this.inputDevices.set(kind, {
|
|
7147
|
+
currentDevice: '',
|
|
7148
|
+
availableDevices: [],
|
|
7149
|
+
isPermitted: false,
|
|
7150
|
+
});
|
|
7151
|
+
return;
|
|
7152
|
+
}
|
|
7153
|
+
this.unsubscribeListDevicesSubscription = createSubscription(combineLatest([device.listDevices(), device.state.selectedDevice$]), ([devices, deviceId]) => {
|
|
7154
|
+
const selected = devices.find((d) => d.deviceId === deviceId);
|
|
7155
|
+
this.inputDevices.set(kind, {
|
|
7156
|
+
currentDevice: selected?.label || deviceId || '',
|
|
7157
|
+
availableDevices: devices.map((d) => d.label),
|
|
7158
|
+
isPermitted: true,
|
|
7159
|
+
});
|
|
7160
|
+
});
|
|
7161
|
+
});
|
|
7162
|
+
};
|
|
6965
7163
|
this.run = async () => {
|
|
6966
7164
|
const [subscriberStats, publisherStats] = await Promise.all([
|
|
6967
7165
|
this.subscriber.getStats().then(flatten).then(JSON.stringify),
|
|
@@ -6973,11 +7171,16 @@ class SfuStatsReporter {
|
|
|
6973
7171
|
webrtcVersion: this.webRTCVersion,
|
|
6974
7172
|
subscriberStats,
|
|
6975
7173
|
publisherStats,
|
|
7174
|
+
audioDevices: this.inputDevices.get('mic'),
|
|
7175
|
+
videoDevices: this.inputDevices.get('camera'),
|
|
7176
|
+
deviceState: { oneofKind: undefined },
|
|
6976
7177
|
});
|
|
6977
7178
|
};
|
|
6978
7179
|
this.start = () => {
|
|
6979
7180
|
if (this.options.reporting_interval_ms <= 0)
|
|
6980
7181
|
return;
|
|
7182
|
+
this.observeDevice(this.microphone, 'mic');
|
|
7183
|
+
this.observeDevice(this.camera, 'camera');
|
|
6981
7184
|
clearInterval(this.intervalId);
|
|
6982
7185
|
this.intervalId = setInterval(() => {
|
|
6983
7186
|
this.run().catch((err) => {
|
|
@@ -6986,6 +7189,11 @@ class SfuStatsReporter {
|
|
|
6986
7189
|
}, this.options.reporting_interval_ms);
|
|
6987
7190
|
};
|
|
6988
7191
|
this.stop = () => {
|
|
7192
|
+
this.unsubscribeDevicePermissionsSubscription?.();
|
|
7193
|
+
this.unsubscribeDevicePermissionsSubscription = undefined;
|
|
7194
|
+
this.unsubscribeListDevicesSubscription?.();
|
|
7195
|
+
this.unsubscribeListDevicesSubscription = undefined;
|
|
7196
|
+
this.inputDevices.clear();
|
|
6989
7197
|
clearInterval(this.intervalId);
|
|
6990
7198
|
this.intervalId = undefined;
|
|
6991
7199
|
};
|
|
@@ -6993,11 +7201,15 @@ class SfuStatsReporter {
|
|
|
6993
7201
|
this.options = options;
|
|
6994
7202
|
this.subscriber = subscriber;
|
|
6995
7203
|
this.publisher = publisher;
|
|
6996
|
-
|
|
7204
|
+
this.microphone = microphone;
|
|
7205
|
+
this.camera = camera;
|
|
7206
|
+
this.state = state;
|
|
6997
7207
|
const { sdk, browser } = clientDetails;
|
|
6998
7208
|
this.sdkName = getSdkName(sdk);
|
|
6999
7209
|
this.sdkVersion = getSdkVersion(sdk);
|
|
7000
|
-
//
|
|
7210
|
+
// use the WebRTC version if set by the SDK (React Native) otherwise,
|
|
7211
|
+
// use the browser version as a fallback
|
|
7212
|
+
const webRTCInfo = getWebRTCInfo();
|
|
7001
7213
|
this.webRTCVersion =
|
|
7002
7214
|
webRTCInfo?.version ||
|
|
7003
7215
|
`${browser?.name || ''}-${browser?.version || ''}` ||
|
|
@@ -7847,14 +8059,19 @@ const getAudioStream = async (trackConstraints) => {
|
|
|
7847
8059
|
throwOnNotAllowed: true,
|
|
7848
8060
|
forcePrompt: true,
|
|
7849
8061
|
});
|
|
7850
|
-
return getStream(constraints);
|
|
8062
|
+
return await getStream(constraints);
|
|
7851
8063
|
}
|
|
7852
|
-
catch (
|
|
8064
|
+
catch (error) {
|
|
8065
|
+
if (error instanceof OverconstrainedError && trackConstraints?.deviceId) {
|
|
8066
|
+
const { deviceId, ...relaxedContraints } = trackConstraints;
|
|
8067
|
+
getLogger(['devices'])('warn', 'Failed to get audio stream, will try again with relaxed contraints', { error, constraints, relaxedContraints });
|
|
8068
|
+
return getAudioStream(relaxedContraints);
|
|
8069
|
+
}
|
|
7853
8070
|
getLogger(['devices'])('error', 'Failed to get audio stream', {
|
|
7854
|
-
error
|
|
7855
|
-
constraints
|
|
8071
|
+
error,
|
|
8072
|
+
constraints,
|
|
7856
8073
|
});
|
|
7857
|
-
throw
|
|
8074
|
+
throw error;
|
|
7858
8075
|
}
|
|
7859
8076
|
};
|
|
7860
8077
|
/**
|
|
@@ -7877,14 +8094,19 @@ const getVideoStream = async (trackConstraints) => {
|
|
|
7877
8094
|
throwOnNotAllowed: true,
|
|
7878
8095
|
forcePrompt: true,
|
|
7879
8096
|
});
|
|
7880
|
-
return getStream(constraints);
|
|
8097
|
+
return await getStream(constraints);
|
|
7881
8098
|
}
|
|
7882
|
-
catch (
|
|
8099
|
+
catch (error) {
|
|
8100
|
+
if (error instanceof OverconstrainedError && trackConstraints?.deviceId) {
|
|
8101
|
+
const { deviceId, ...relaxedContraints } = trackConstraints;
|
|
8102
|
+
getLogger(['devices'])('warn', 'Failed to get video stream, will try again with relaxed contraints', { error, constraints, relaxedContraints });
|
|
8103
|
+
return getVideoStream(relaxedContraints);
|
|
8104
|
+
}
|
|
7883
8105
|
getLogger(['devices'])('error', 'Failed to get video stream', {
|
|
7884
|
-
error
|
|
7885
|
-
constraints
|
|
8106
|
+
error,
|
|
8107
|
+
constraints,
|
|
7886
8108
|
});
|
|
7887
|
-
throw
|
|
8109
|
+
throw error;
|
|
7888
8110
|
}
|
|
7889
8111
|
};
|
|
7890
8112
|
/**
|
|
@@ -8102,11 +8324,18 @@ class InputMediaDeviceManager {
|
|
|
8102
8324
|
if (isReactNative()) {
|
|
8103
8325
|
throw new Error('This method is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for reference.');
|
|
8104
8326
|
}
|
|
8105
|
-
|
|
8327
|
+
const prevDeviceId = this.state.selectedDevice;
|
|
8328
|
+
if (deviceId === prevDeviceId) {
|
|
8106
8329
|
return;
|
|
8107
8330
|
}
|
|
8108
|
-
|
|
8109
|
-
|
|
8331
|
+
try {
|
|
8332
|
+
this.state.setDevice(deviceId);
|
|
8333
|
+
await this.applySettingsToStream();
|
|
8334
|
+
}
|
|
8335
|
+
catch (error) {
|
|
8336
|
+
this.state.setDevice(prevDeviceId);
|
|
8337
|
+
throw error;
|
|
8338
|
+
}
|
|
8110
8339
|
}
|
|
8111
8340
|
async applySettingsToStream() {
|
|
8112
8341
|
await withCancellation(this.statusChangeConcurrencyTag, async () => {
|
|
@@ -8181,7 +8410,9 @@ class InputMediaDeviceManager {
|
|
|
8181
8410
|
const defaultConstraints = this.state.defaultConstraints;
|
|
8182
8411
|
const constraints = {
|
|
8183
8412
|
...defaultConstraints,
|
|
8184
|
-
deviceId: this.state.selectedDevice
|
|
8413
|
+
deviceId: this.state.selectedDevice
|
|
8414
|
+
? { exact: this.state.selectedDevice }
|
|
8415
|
+
: undefined,
|
|
8185
8416
|
};
|
|
8186
8417
|
/**
|
|
8187
8418
|
* Chains two media streams together.
|
|
@@ -9763,6 +9994,9 @@ class Call {
|
|
|
9763
9994
|
options: statsOptions,
|
|
9764
9995
|
subscriber: this.subscriber,
|
|
9765
9996
|
publisher: this.publisher,
|
|
9997
|
+
microphone: this.microphone,
|
|
9998
|
+
camera: this.camera,
|
|
9999
|
+
state: this.state,
|
|
9766
10000
|
});
|
|
9767
10001
|
this.sfuStatsReporter.start();
|
|
9768
10002
|
}
|
|
@@ -12074,7 +12308,7 @@ class StreamClient {
|
|
|
12074
12308
|
}
|
|
12075
12309
|
if ((this._isUsingServerAuth() || this.node) &&
|
|
12076
12310
|
!this.options.allowServerSideConnect) {
|
|
12077
|
-
this.logger('warn', 'Please do not use connectUser server side.
|
|
12311
|
+
this.logger('warn', 'Please do not use connectUser server side. Use our @stream-io/node-sdk instead: https://getstream.io/video/docs/api/');
|
|
12078
12312
|
}
|
|
12079
12313
|
// we generate the client id client side
|
|
12080
12314
|
this.userID = user.id;
|
|
@@ -12450,7 +12684,7 @@ class StreamClient {
|
|
|
12450
12684
|
});
|
|
12451
12685
|
};
|
|
12452
12686
|
this.getUserAgent = () => {
|
|
12453
|
-
const version = "1.
|
|
12687
|
+
const version = "1.10.0";
|
|
12454
12688
|
return (this.userAgent ||
|
|
12455
12689
|
`stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${version}`);
|
|
12456
12690
|
};
|