Skip to content

Commit f1cccbb

Browse files
committed
Merge branch 'refs/heads/main' into docs/cc-react
2 parents e44bfd6 + 82cb3e3 commit f1cccbb

File tree

93 files changed

+3973
-2208
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+3973
-2208
lines changed

packages/client/CHANGELOG.md

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

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

5+
## [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+
7+
8+
### Bug Fixes
9+
10+
* **client:** invoke call.reject only when reject param specified ([#1530](https://github.com/GetStream/stream-video-js/issues/1530)) ([eac4e4e](https://github.com/GetStream/stream-video-js/commit/eac4e4ebd2575f5269f65db7173107d5cafab9bf))
11+
12+
## [1.9.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.9.0...@stream-io/video-client-1.9.1) (2024-10-18)
13+
14+
15+
### Bug Fixes
16+
17+
* **svc:** announce downscaled layers in setPublisher ([#1526](https://github.com/GetStream/stream-video-js/issues/1526)) ([96cadd0](https://github.com/GetStream/stream-video-js/commit/96cadd05e995392eac4ec300828d07b287d691a0))
18+
19+
## [1.9.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.8.4...@stream-io/video-client-1.9.0) (2024-10-16)
20+
21+
22+
### Features
23+
24+
* **svc-codec:** VP9 and AV1 support ([#1434](https://github.com/GetStream/stream-video-js/issues/1434)) ([c9c8530](https://github.com/GetStream/stream-video-js/commit/c9c8530d48c9206dc3803e6aa6cc1859fd433920))
25+
26+
## [1.8.4](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.8.3...@stream-io/video-client-1.8.4) (2024-10-16)
27+
28+
29+
### Bug Fixes
30+
31+
* ignore camera direction for desktop devices ([#1521](https://github.com/GetStream/stream-video-js/issues/1521)) ([562b5cc](https://github.com/GetStream/stream-video-js/commit/562b5cca77264330d08dff5305eccc489970076a))
32+
33+
## [1.8.3](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.8.2...@stream-io/video-client-1.8.3) (2024-10-10)
34+
35+
36+
### Bug Fixes
37+
38+
* do not release track if track was not removed from stream ([#1517](https://github.com/GetStream/stream-video-js/issues/1517)) ([5bfc528](https://github.com/GetStream/stream-video-js/commit/5bfc52850c36ffe0de37e47066538a8a14dc9e01))
39+
40+
## [1.8.2](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.8.1...@stream-io/video-client-1.8.2) (2024-10-10)
41+
42+
43+
### Bug Fixes
44+
45+
* add track release for react-native whenever track stop is called ([#1516](https://github.com/GetStream/stream-video-js/issues/1516)) ([5074510](https://github.com/GetStream/stream-video-js/commit/50745101d28d0339592c22ca02b076040ad3bdeb))
46+
47+
## [1.8.1](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.8.0...@stream-io/video-client-1.8.1) (2024-10-10)
48+
49+
50+
### Bug Fixes
51+
52+
* mic not fully released in some cases ([#1515](https://github.com/GetStream/stream-video-js/issues/1515)) ([b7bf90b](https://github.com/GetStream/stream-video-js/commit/b7bf90b9b1a83fb80d01a82ebee8754343963ae5))
53+
554
## [1.8.0](https://github.com/GetStream/stream-video-js/compare/@stream-io/video-client-1.7.4...@stream-io/video-client-1.8.0) (2024-10-02)
655

756

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.8.0",
3+
"version": "1.9.2",
44
"packageManager": "[email protected]",
55
"main": "dist/index.cjs.js",
66
"module": "dist/index.es.js",

packages/client/src/Call.ts

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,7 @@ import {
9090
VideoTrackType,
9191
} from './types';
9292
import { BehaviorSubject, Subject, takeWhile } from 'rxjs';
93-
import {
94-
ReconnectDetails,
95-
VideoLayerSetting,
96-
} from './gen/video/sfu/event/events';
93+
import { ReconnectDetails } from './gen/video/sfu/event/events';
9794
import {
9895
ClientDetails,
9996
TrackType,
@@ -205,6 +202,7 @@ export class Call {
205202
*/
206203
private readonly dispatcher = new Dispatcher();
207204

205+
private publishOptions?: PublishOptions;
208206
private statsReporter?: StatsReporter;
209207
private sfuStatsReporter?: SfuStatsReporter;
210208
private dropTimeout: ReturnType<typeof setTimeout> | undefined;
@@ -521,7 +519,7 @@ export class Call {
521519
await waitUntilCallJoined();
522520
}
523521

524-
if (this.ringing) {
522+
if (reject && this.ringing) {
525523
// I'm the one who started the call, so I should cancel it.
526524
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
527525
if (
@@ -532,7 +530,7 @@ export class Call {
532530
// Signals other users that I have cancelled my call to them
533531
// before they accepted it.
534532
await this.reject();
535-
} else if (reject && callingState === CallingState.RINGING) {
533+
} else if (callingState === CallingState.RINGING) {
536534
// Signals other users that I have rejected the incoming call.
537535
await this.reject();
538536
}
@@ -1296,19 +1294,12 @@ export class Call {
12961294
break;
12971295
case TrackType.VIDEO:
12981296
const videoStream = this.camera.state.mediaStream;
1299-
if (videoStream) {
1300-
await this.publishVideoStream(
1301-
videoStream,
1302-
this.camera.publishOptions,
1303-
);
1304-
}
1297+
if (videoStream) await this.publishVideoStream(videoStream);
13051298
break;
13061299
case TrackType.SCREEN_SHARE:
13071300
const screenShareStream = this.screenShare.state.mediaStream;
13081301
if (screenShareStream) {
1309-
await this.publishScreenShareStream(screenShareStream, {
1310-
screenShareSettings: this.screenShare.getSettings(),
1311-
});
1302+
await this.publishScreenShareStream(screenShareStream);
13121303
}
13131304
break;
13141305
// screen share audio can't exist without a screen share, so we handle it there
@@ -1340,12 +1331,8 @@ export class Call {
13401331
* The previous video stream will be stopped.
13411332
*
13421333
* @param videoStream the video stream to publish.
1343-
* @param opts the options to use when publishing the stream.
13441334
*/
1345-
publishVideoStream = async (
1346-
videoStream: MediaStream,
1347-
opts: PublishOptions = {},
1348-
) => {
1335+
publishVideoStream = async (videoStream: MediaStream) => {
13491336
if (!this.sfuClient) throw new Error(`Call not joined yet.`);
13501337
// joining is in progress, and we should wait until the client is ready
13511338
await this.sfuClient.joinTask;
@@ -1367,7 +1354,7 @@ export class Call {
13671354
videoStream,
13681355
videoTrack,
13691356
TrackType.VIDEO,
1370-
opts,
1357+
this.publishOptions,
13711358
);
13721359
};
13731360

@@ -1411,12 +1398,8 @@ export class Call {
14111398
* The previous screen-share stream will be stopped.
14121399
*
14131400
* @param screenShareStream the screen-share stream to publish.
1414-
* @param opts the options to use when publishing the stream.
14151401
*/
1416-
publishScreenShareStream = async (
1417-
screenShareStream: MediaStream,
1418-
opts: PublishOptions = {},
1419-
) => {
1402+
publishScreenShareStream = async (screenShareStream: MediaStream) => {
14201403
if (!this.sfuClient) throw new Error(`Call not joined yet.`);
14211404
// joining is in progress, and we should wait until the client is ready
14221405
await this.sfuClient.joinTask;
@@ -1435,6 +1418,9 @@ export class Call {
14351418
if (!this.trackPublishOrder.includes(TrackType.SCREEN_SHARE)) {
14361419
this.trackPublishOrder.push(TrackType.SCREEN_SHARE);
14371420
}
1421+
const opts: PublishOptions = {
1422+
screenShareSettings: this.screenShare.getSettings(),
1423+
};
14381424
await this.publisher.publishStream(
14391425
screenShareStream,
14401426
screenShareTrack,
@@ -1471,6 +1457,16 @@ export class Call {
14711457
await this.publisher?.unpublishStream(trackType, stopTrack);
14721458
};
14731459

1460+
/**
1461+
* Updates the preferred publishing options
1462+
*
1463+
* @internal
1464+
* @param options the options to use.
1465+
*/
1466+
updatePublishOptions(options: PublishOptions) {
1467+
this.publishOptions = { ...this.publishOptions, ...options };
1468+
}
1469+
14741470
/**
14751471
* Notifies the SFU that a noise cancellation process has started.
14761472
*
@@ -1533,16 +1529,6 @@ export class Call {
15331529
return this.state.setSortParticipantsBy(criteria);
15341530
};
15351531

1536-
/**
1537-
* Updates the list of video layers to publish.
1538-
*
1539-
* @internal
1540-
* @param enabledLayers the list of layers to enable.
1541-
*/
1542-
updatePublishQuality = async (enabledLayers: VideoLayerSetting[]) => {
1543-
return this.publisher?.updateVideoPublishQuality(enabledLayers);
1544-
};
1545-
15461532
/**
15471533
* Sends a reaction to the other call participants.
15481534
*
@@ -2143,10 +2129,7 @@ export class Call {
21432129
this.camera.state.mediaStream &&
21442130
!this.publisher?.isPublishing(TrackType.VIDEO)
21452131
) {
2146-
await this.publishVideoStream(
2147-
this.camera.state.mediaStream,
2148-
this.camera.publishOptions,
2149-
);
2132+
await this.publishVideoStream(this.camera.state.mediaStream);
21502133
}
21512134

21522135
// Start camera if backend config specifies, and there is no local setting

packages/client/src/compatibility.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/**
2+
* Checks if the current platform is a mobile device.
3+
*
4+
* See:
5+
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
6+
*/
7+
export const isMobile = () => /Mobi/i.test(navigator.userAgent);

packages/client/src/devices/CameraManager.ts

Lines changed: 18 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,15 @@ import { CameraDirection, CameraManagerState } from './CameraManagerState';
44
import { InputMediaDeviceManager } from './InputMediaDeviceManager';
55
import { getVideoDevices, getVideoStream } from './devices';
66
import { TrackType } from '../gen/video/sfu/models/models';
7-
import { PreferredCodec, PublishOptions } from '../types';
7+
import { PreferredCodec } from '../types';
8+
import { isMobile } from '../compatibility';
89

910
export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
1011
private targetResolution = {
1112
width: 1280,
1213
height: 720,
1314
};
1415

15-
/**
16-
* The options to use when publishing the video stream.
17-
*
18-
* @internal
19-
*/
20-
publishOptions: PublishOptions | undefined;
21-
2216
/**
2317
* Constructs a new CameraManager.
2418
*
@@ -34,10 +28,14 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
3428
* @param direction the direction of the camera to select.
3529
*/
3630
async selectDirection(direction: Exclude<CameraDirection, undefined>) {
37-
this.state.setDirection(direction);
38-
// Providing both device id and direction doesn't work, so we deselect the device
39-
this.state.setDevice(undefined);
40-
await this.applySettingsToStream();
31+
if (isMobile()) {
32+
this.state.setDirection(direction);
33+
// Providing both device id and direction doesn't work, so we deselect the device
34+
this.state.setDevice(undefined);
35+
await this.applySettingsToStream();
36+
} else {
37+
this.logger('warn', 'Camera direction ignored for desktop devices');
38+
}
4139
}
4240

4341
/**
@@ -65,10 +63,10 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
6563
this.logger('warn', 'could not apply target resolution', error);
6664
}
6765
}
68-
if (this.enabled) {
69-
const { width, height } = this.state
70-
.mediaStream!.getVideoTracks()[0]
71-
?.getSettings();
66+
if (this.enabled && this.state.mediaStream) {
67+
const [videoTrack] = this.state.mediaStream.getVideoTracks();
68+
if (!videoTrack) return;
69+
const { width, height } = videoTrack.getSettings();
7270
if (
7371
width !== this.targetResolution.width ||
7472
height !== this.targetResolution.height
@@ -86,38 +84,11 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
8684
* Sets the preferred codec for encoding the video.
8785
*
8886
* @internal internal use only, not part of the public API.
87+
* @deprecated use {@link call.updatePublishOptions} instead.
8988
* @param codec the codec to use for encoding the video.
9089
*/
9190
setPreferredCodec(codec: PreferredCodec | undefined) {
92-
this.updatePublishOptions({ preferredCodec: codec });
93-
}
94-
95-
/**
96-
* Updates the preferred publish options for the video stream.
97-
*
98-
* @internal
99-
* @param options the options to use.
100-
*/
101-
updatePublishOptions(options: PublishOptions) {
102-
this.publishOptions = { ...this.publishOptions, ...options };
103-
}
104-
105-
/**
106-
* Returns the capture resolution of the camera.
107-
*/
108-
getCaptureResolution() {
109-
const { mediaStream } = this.state;
110-
if (!mediaStream) return;
111-
112-
const [videoTrack] = mediaStream.getVideoTracks();
113-
if (!videoTrack) return;
114-
115-
const settings = videoTrack.getSettings();
116-
return {
117-
width: settings.width,
118-
height: settings.height,
119-
frameRate: settings.frameRate,
120-
};
91+
this.call.updatePublishOptions({ preferredCodec: codec });
12192
}
12293

12394
protected getDevices(): Observable<MediaDeviceInfo[]> {
@@ -131,15 +102,15 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
131102
constraints.height = this.targetResolution.height;
132103
// We can't set both device id and facing mode
133104
// Device id has higher priority
134-
if (!constraints.deviceId && this.state.direction) {
105+
if (!constraints.deviceId && this.state.direction && isMobile()) {
135106
constraints.facingMode =
136107
this.state.direction === 'front' ? 'user' : 'environment';
137108
}
138109
return getVideoStream(constraints);
139110
}
140111

141112
protected publishStream(stream: MediaStream): Promise<void> {
142-
return this.call.publishVideoStream(stream, this.publishOptions);
113+
return this.call.publishVideoStream(stream);
143114
}
144115

145116
protected stopPublishStream(stopTracks: boolean): Promise<void> {

packages/client/src/devices/ScreenShareManager.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ export class ScreenShareManager extends InputMediaDeviceManager<
8080
}
8181

8282
protected publishStream(stream: MediaStream): Promise<void> {
83-
return this.call.publishScreenShareStream(stream, {
84-
screenShareSettings: this.state.settings,
85-
});
83+
return this.call.publishScreenShareStream(stream);
8684
}
8785

8886
protected async stopPublishStream(stopTracks: boolean): Promise<void> {

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

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ vi.mock('../../Call.ts', () => {
3636
};
3737
});
3838

39+
vi.mock('../../compatibility.ts', () => {
40+
console.log('MOCKING mobile device');
41+
return {
42+
isMobile: () => true,
43+
};
44+
});
45+
3946
describe('CameraManager', () => {
4047
let manager: CameraManager;
4148

@@ -82,21 +89,6 @@ describe('CameraManager', () => {
8289

8390
expect(manager['call'].publishVideoStream).toHaveBeenCalledWith(
8491
manager.state.mediaStream,
85-
undefined,
86-
);
87-
});
88-
89-
it('publish stream with preferred codec', async () => {
90-
manager['call'].state.setCallingState(CallingState.JOINED);
91-
manager.setPreferredCodec('h264');
92-
93-
await manager.enable();
94-
95-
expect(manager['call'].publishVideoStream).toHaveBeenCalledWith(
96-
manager.state.mediaStream,
97-
{
98-
preferredCodec: 'h264',
99-
},
10092
);
10193
});
10294

0 commit comments

Comments
 (0)