Skip to content

Commit d8a5739

Browse files
committed
Merge branch 'add-layout-switcher' into rn-design-v2-record-call-flow
2 parents 98b565e + 5e27b61 commit d8a5739

File tree

26 files changed

+465
-277
lines changed

26 files changed

+465
-277
lines changed

packages/client/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
44

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+
519
## [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)
620

721

packages/client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@stream-io/video-client",
3-
"version": "1.9.2",
3+
"version": "1.10.0",
44
"packageManager": "[email protected]",
55
"main": "dist/index.cjs.js",
66
"module": "dist/index.es.js",

packages/client/src/Call.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,9 @@ export class Call {
993993
options: statsOptions,
994994
subscriber: this.subscriber,
995995
publisher: this.publisher,
996+
microphone: this.microphone,
997+
camera: this.camera,
998+
state: this.state,
996999
});
9971000
this.sfuStatsReporter.start();
9981001
}

packages/client/src/coordinator/connection/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ export class StreamClient {
252252
) {
253253
this.logger(
254254
'warn',
255-
'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.',
255+
'Please do not use connectUser server side. Use our @stream-io/node-sdk instead: https://getstream.io/video/docs/api/',
256256
);
257257
}
258258

packages/client/src/devices/InputMediaDeviceManager.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,17 @@ export abstract class InputMediaDeviceManager<
206206
'This method is not supported in React Native. Please visit https://getstream.io/video/docs/reactnative/core/camera-and-microphone/#speaker-management for reference.',
207207
);
208208
}
209-
if (deviceId === this.state.selectedDevice) {
209+
const prevDeviceId = this.state.selectedDevice;
210+
if (deviceId === prevDeviceId) {
210211
return;
211212
}
212-
this.state.setDevice(deviceId);
213-
await this.applySettingsToStream();
213+
try {
214+
this.state.setDevice(deviceId);
215+
await this.applySettingsToStream();
216+
} catch (error) {
217+
this.state.setDevice(prevDeviceId);
218+
throw error;
219+
}
214220
}
215221

216222
/**
@@ -308,7 +314,9 @@ export abstract class InputMediaDeviceManager<
308314
const defaultConstraints = this.state.defaultConstraints;
309315
const constraints: MediaTrackConstraints = {
310316
...defaultConstraints,
311-
deviceId: this.state.selectedDevice,
317+
deviceId: this.state.selectedDevice
318+
? { exact: this.state.selectedDevice }
319+
: undefined,
312320
};
313321

314322
/**

packages/client/src/devices/__tests__/CameraManager.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ describe('CameraManager', () => {
157157
await manager.select(deviceId);
158158

159159
expect((getVideoStream as Mock).mock.lastCall[0]).toEqual({
160-
deviceId,
160+
deviceId: { exact: deviceId },
161161
width: 1280,
162162
height: 720,
163163
});
@@ -182,7 +182,7 @@ describe('CameraManager', () => {
182182
await manager.selectTargetResolution({ width: 640, height: 480 });
183183

184184
expect((getVideoStream as Mock).mock.lastCall[0]).toEqual({
185-
deviceId: mockVideoDevices[0].deviceId,
185+
deviceId: { exact: mockVideoDevices[0].deviceId },
186186
width: 640,
187187
height: 480,
188188
});

packages/client/src/devices/__tests__/InputMediaDeviceManager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ describe('InputMediaDeviceManager.test', () => {
181181

182182
expect(manager.stopPublishStream).toHaveBeenCalledWith(true);
183183
expect(manager.getStream).toHaveBeenCalledWith({
184-
deviceId,
184+
deviceId: { exact: deviceId },
185185
});
186186
expect(manager.publishStream).toHaveBeenCalled();
187187
});

packages/client/src/devices/devices.ts

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ const getStream = async (constraints: MediaStreamConstraints) => {
167167
*/
168168
export const getAudioStream = async (
169169
trackConstraints?: MediaTrackConstraints,
170-
) => {
170+
): Promise<MediaStream> => {
171171
const constraints: MediaStreamConstraints = {
172172
audio: {
173173
...audioDeviceConstraints.audio,
@@ -180,13 +180,23 @@ export const getAudioStream = async (
180180
throwOnNotAllowed: true,
181181
forcePrompt: true,
182182
});
183-
return getStream(constraints);
184-
} catch (e) {
183+
return await getStream(constraints);
184+
} catch (error) {
185+
if (error instanceof OverconstrainedError && trackConstraints?.deviceId) {
186+
const { deviceId, ...relaxedContraints } = trackConstraints;
187+
getLogger(['devices'])(
188+
'warn',
189+
'Failed to get audio stream, will try again with relaxed contraints',
190+
{ error, constraints, relaxedContraints },
191+
);
192+
return getAudioStream(relaxedContraints);
193+
}
194+
185195
getLogger(['devices'])('error', 'Failed to get audio stream', {
186-
error: e,
187-
constraints: constraints,
196+
error,
197+
constraints,
188198
});
189-
throw e;
199+
throw error;
190200
}
191201
};
192202

@@ -200,7 +210,7 @@ export const getAudioStream = async (
200210
*/
201211
export const getVideoStream = async (
202212
trackConstraints?: MediaTrackConstraints,
203-
) => {
213+
): Promise<MediaStream> => {
204214
const constraints: MediaStreamConstraints = {
205215
video: {
206216
...videoDeviceConstraints.video,
@@ -212,13 +222,23 @@ export const getVideoStream = async (
212222
throwOnNotAllowed: true,
213223
forcePrompt: true,
214224
});
215-
return getStream(constraints);
216-
} catch (e) {
225+
return await getStream(constraints);
226+
} catch (error) {
227+
if (error instanceof OverconstrainedError && trackConstraints?.deviceId) {
228+
const { deviceId, ...relaxedContraints } = trackConstraints;
229+
getLogger(['devices'])(
230+
'warn',
231+
'Failed to get video stream, will try again with relaxed contraints',
232+
{ error, constraints, relaxedContraints },
233+
);
234+
return getVideoStream(relaxedContraints);
235+
}
236+
217237
getLogger(['devices'])('error', 'Failed to get video stream', {
218-
error: e,
219-
constraints: constraints,
238+
error,
239+
constraints,
220240
});
221-
throw e;
241+
throw error;
222242
}
223243
};
224244

packages/client/src/gen/video/sfu/models/models.ts

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,51 @@ export interface CallGrants {
442442
*/
443443
canScreenshare: boolean;
444444
}
445+
/**
446+
* @generated from protobuf message stream.video.sfu.models.InputDevices
447+
*/
448+
export interface InputDevices {
449+
/**
450+
* @generated from protobuf field: repeated string available_devices = 1;
451+
*/
452+
availableDevices: string[];
453+
/**
454+
* @generated from protobuf field: string current_device = 2;
455+
*/
456+
currentDevice: string;
457+
/**
458+
* @generated from protobuf field: bool is_permitted = 3;
459+
*/
460+
isPermitted: boolean;
461+
}
462+
/**
463+
* @generated from protobuf message stream.video.sfu.models.AndroidState
464+
*/
465+
export interface AndroidState {
466+
/**
467+
* @generated from protobuf field: stream.video.sfu.models.AndroidThermalState thermal_state = 1;
468+
*/
469+
thermalState: AndroidThermalState;
470+
/**
471+
* @generated from protobuf field: bool is_power_saver_mode = 2;
472+
*/
473+
isPowerSaverMode: boolean;
474+
}
475+
/**
476+
* @generated from protobuf message stream.video.sfu.models.AppleState
477+
*/
478+
export interface AppleState {
479+
/**
480+
* @generated from protobuf field: stream.video.sfu.models.AppleThermalState thermal_state = 1;
481+
*/
482+
thermalState: AppleThermalState;
483+
/**
484+
* https://developer.apple.com/documentation/foundation/processinfo/1617047-islowpowermodeenabled
485+
*
486+
* @generated from protobuf field: bool is_low_power_mode_enabled = 2;
487+
*/
488+
isLowPowerModeEnabled: boolean;
489+
}
445490
/**
446491
* @generated from protobuf enum stream.video.sfu.models.PeerType
447492
*/
@@ -773,6 +818,74 @@ export enum WebsocketReconnectStrategy {
773818
*/
774819
MIGRATE = 4,
775820
}
821+
/**
822+
* AndroidThermalState is reported by the Android API. The full list of values is documented here
823+
* https://developer.android.com/reference/android/os/PowerManager.html#getCurrentThermalStatus()
824+
*
825+
* @generated from protobuf enum stream.video.sfu.models.AndroidThermalState
826+
*/
827+
export enum AndroidThermalState {
828+
/**
829+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_UNSPECIFIED = 0;
830+
*/
831+
UNSPECIFIED = 0,
832+
/**
833+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_NONE = 1;
834+
*/
835+
NONE = 1,
836+
/**
837+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_LIGHT = 2;
838+
*/
839+
LIGHT = 2,
840+
/**
841+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_MODERATE = 3;
842+
*/
843+
MODERATE = 3,
844+
/**
845+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_SEVERE = 4;
846+
*/
847+
SEVERE = 4,
848+
/**
849+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_CRITICAL = 5;
850+
*/
851+
CRITICAL = 5,
852+
/**
853+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_EMERGENCY = 6;
854+
*/
855+
EMERGENCY = 6,
856+
/**
857+
* @generated from protobuf enum value: ANDROID_THERMAL_STATE_SHUTDOWN = 7;
858+
*/
859+
SHUTDOWN = 7,
860+
}
861+
/**
862+
* AppleThermalState is the thermal state as reported by Apple devices when available or applicable to the platform.
863+
* The full list of states (enum) is available here: https://developer.apple.com/documentation/foundation/processinfo/thermalstate
864+
*
865+
* @generated from protobuf enum stream.video.sfu.models.AppleThermalState
866+
*/
867+
export enum AppleThermalState {
868+
/**
869+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_UNSPECIFIED = 0;
870+
*/
871+
UNSPECIFIED = 0,
872+
/**
873+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_NOMINAL = 1;
874+
*/
875+
NOMINAL = 1,
876+
/**
877+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_FAIR = 2;
878+
*/
879+
FAIR = 2,
880+
/**
881+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_SERIOUS = 3;
882+
*/
883+
SERIOUS = 3,
884+
/**
885+
* @generated from protobuf enum value: APPLE_THERMAL_STATE_CRITICAL = 4;
886+
*/
887+
CRITICAL = 4,
888+
}
776889
// @generated message type with reflection information, may provide speed optimized methods
777890
class CallState$Type extends MessageType<CallState> {
778891
constructor() {
@@ -1211,3 +1324,82 @@ class CallGrants$Type extends MessageType<CallGrants> {
12111324
* @generated MessageType for protobuf message stream.video.sfu.models.CallGrants
12121325
*/
12131326
export const CallGrants = new CallGrants$Type();
1327+
// @generated message type with reflection information, may provide speed optimized methods
1328+
class InputDevices$Type extends MessageType<InputDevices> {
1329+
constructor() {
1330+
super('stream.video.sfu.models.InputDevices', [
1331+
{
1332+
no: 1,
1333+
name: 'available_devices',
1334+
kind: 'scalar',
1335+
repeat: 2 /*RepeatType.UNPACKED*/,
1336+
T: 9 /*ScalarType.STRING*/,
1337+
},
1338+
{
1339+
no: 2,
1340+
name: 'current_device',
1341+
kind: 'scalar',
1342+
T: 9 /*ScalarType.STRING*/,
1343+
},
1344+
{ no: 3, name: 'is_permitted', kind: 'scalar', T: 8 /*ScalarType.BOOL*/ },
1345+
]);
1346+
}
1347+
}
1348+
/**
1349+
* @generated MessageType for protobuf message stream.video.sfu.models.InputDevices
1350+
*/
1351+
export const InputDevices = new InputDevices$Type();
1352+
// @generated message type with reflection information, may provide speed optimized methods
1353+
class AndroidState$Type extends MessageType<AndroidState> {
1354+
constructor() {
1355+
super('stream.video.sfu.models.AndroidState', [
1356+
{
1357+
no: 1,
1358+
name: 'thermal_state',
1359+
kind: 'enum',
1360+
T: () => [
1361+
'stream.video.sfu.models.AndroidThermalState',
1362+
AndroidThermalState,
1363+
'ANDROID_THERMAL_STATE_',
1364+
],
1365+
},
1366+
{
1367+
no: 2,
1368+
name: 'is_power_saver_mode',
1369+
kind: 'scalar',
1370+
T: 8 /*ScalarType.BOOL*/,
1371+
},
1372+
]);
1373+
}
1374+
}
1375+
/**
1376+
* @generated MessageType for protobuf message stream.video.sfu.models.AndroidState
1377+
*/
1378+
export const AndroidState = new AndroidState$Type();
1379+
// @generated message type with reflection information, may provide speed optimized methods
1380+
class AppleState$Type extends MessageType<AppleState> {
1381+
constructor() {
1382+
super('stream.video.sfu.models.AppleState', [
1383+
{
1384+
no: 1,
1385+
name: 'thermal_state',
1386+
kind: 'enum',
1387+
T: () => [
1388+
'stream.video.sfu.models.AppleThermalState',
1389+
AppleThermalState,
1390+
'APPLE_THERMAL_STATE_',
1391+
],
1392+
},
1393+
{
1394+
no: 2,
1395+
name: 'is_low_power_mode_enabled',
1396+
kind: 'scalar',
1397+
T: 8 /*ScalarType.BOOL*/,
1398+
},
1399+
]);
1400+
}
1401+
}
1402+
/**
1403+
* @generated MessageType for protobuf message stream.video.sfu.models.AppleState
1404+
*/
1405+
export const AppleState = new AppleState$Type();

0 commit comments

Comments
 (0)