Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into docs/cc-react
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverlaz committed Oct 22, 2024
2 parents e44bfd6 + 82cb3e3 commit f1cccbb
Show file tree
Hide file tree
Showing 93 changed files with 3,973 additions and 2,208 deletions.
49 changes: 49 additions & 0 deletions packages/client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,55 @@

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

## [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)


### Bug Fixes

* **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))

## [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)


### Bug Fixes

* **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))

## [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)


### Features

* **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))

## [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)


### Bug Fixes

* 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))

## [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)


### Bug Fixes

* 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))

## [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)


### Bug Fixes

* 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))

## [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)


### Bug Fixes

* 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))

## [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)


Expand Down
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stream-io/video-client",
"version": "1.8.0",
"version": "1.9.2",
"packageManager": "[email protected]",
"main": "dist/index.cjs.js",
"module": "dist/index.es.js",
Expand Down
63 changes: 23 additions & 40 deletions packages/client/src/Call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,7 @@ import {
VideoTrackType,
} from './types';
import { BehaviorSubject, Subject, takeWhile } from 'rxjs';
import {
ReconnectDetails,
VideoLayerSetting,
} from './gen/video/sfu/event/events';
import { ReconnectDetails } from './gen/video/sfu/event/events';
import {
ClientDetails,
TrackType,
Expand Down Expand Up @@ -205,6 +202,7 @@ export class Call {
*/
private readonly dispatcher = new Dispatcher();

private publishOptions?: PublishOptions;
private statsReporter?: StatsReporter;
private sfuStatsReporter?: SfuStatsReporter;
private dropTimeout: ReturnType<typeof setTimeout> | undefined;
Expand Down Expand Up @@ -521,7 +519,7 @@ export class Call {
await waitUntilCallJoined();
}

if (this.ringing) {
if (reject && this.ringing) {
// I'm the one who started the call, so I should cancel it.
const hasOtherParticipants = this.state.remoteParticipants.length > 0;
if (
Expand All @@ -532,7 +530,7 @@ export class Call {
// Signals other users that I have cancelled my call to them
// before they accepted it.
await this.reject();
} else if (reject && callingState === CallingState.RINGING) {
} else if (callingState === CallingState.RINGING) {
// Signals other users that I have rejected the incoming call.
await this.reject();
}
Expand Down Expand Up @@ -1296,19 +1294,12 @@ export class Call {
break;
case TrackType.VIDEO:
const videoStream = this.camera.state.mediaStream;
if (videoStream) {
await this.publishVideoStream(
videoStream,
this.camera.publishOptions,
);
}
if (videoStream) await this.publishVideoStream(videoStream);
break;
case TrackType.SCREEN_SHARE:
const screenShareStream = this.screenShare.state.mediaStream;
if (screenShareStream) {
await this.publishScreenShareStream(screenShareStream, {
screenShareSettings: this.screenShare.getSettings(),
});
await this.publishScreenShareStream(screenShareStream);
}
break;
// screen share audio can't exist without a screen share, so we handle it there
Expand Down Expand Up @@ -1340,12 +1331,8 @@ export class Call {
* The previous video stream will be stopped.
*
* @param videoStream the video stream to publish.
* @param opts the options to use when publishing the stream.
*/
publishVideoStream = async (
videoStream: MediaStream,
opts: PublishOptions = {},
) => {
publishVideoStream = async (videoStream: MediaStream) => {
if (!this.sfuClient) throw new Error(`Call not joined yet.`);
// joining is in progress, and we should wait until the client is ready
await this.sfuClient.joinTask;
Expand All @@ -1367,7 +1354,7 @@ export class Call {
videoStream,
videoTrack,
TrackType.VIDEO,
opts,
this.publishOptions,
);
};

Expand Down Expand Up @@ -1411,12 +1398,8 @@ export class Call {
* The previous screen-share stream will be stopped.
*
* @param screenShareStream the screen-share stream to publish.
* @param opts the options to use when publishing the stream.
*/
publishScreenShareStream = async (
screenShareStream: MediaStream,
opts: PublishOptions = {},
) => {
publishScreenShareStream = async (screenShareStream: MediaStream) => {
if (!this.sfuClient) throw new Error(`Call not joined yet.`);
// joining is in progress, and we should wait until the client is ready
await this.sfuClient.joinTask;
Expand All @@ -1435,6 +1418,9 @@ export class Call {
if (!this.trackPublishOrder.includes(TrackType.SCREEN_SHARE)) {
this.trackPublishOrder.push(TrackType.SCREEN_SHARE);
}
const opts: PublishOptions = {
screenShareSettings: this.screenShare.getSettings(),
};
await this.publisher.publishStream(
screenShareStream,
screenShareTrack,
Expand Down Expand Up @@ -1471,6 +1457,16 @@ export class Call {
await this.publisher?.unpublishStream(trackType, stopTrack);
};

/**
* Updates the preferred publishing options
*
* @internal
* @param options the options to use.
*/
updatePublishOptions(options: PublishOptions) {
this.publishOptions = { ...this.publishOptions, ...options };
}

/**
* Notifies the SFU that a noise cancellation process has started.
*
Expand Down Expand Up @@ -1533,16 +1529,6 @@ export class Call {
return this.state.setSortParticipantsBy(criteria);
};

/**
* Updates the list of video layers to publish.
*
* @internal
* @param enabledLayers the list of layers to enable.
*/
updatePublishQuality = async (enabledLayers: VideoLayerSetting[]) => {
return this.publisher?.updateVideoPublishQuality(enabledLayers);
};

/**
* Sends a reaction to the other call participants.
*
Expand Down Expand Up @@ -2143,10 +2129,7 @@ export class Call {
this.camera.state.mediaStream &&
!this.publisher?.isPublishing(TrackType.VIDEO)
) {
await this.publishVideoStream(
this.camera.state.mediaStream,
this.camera.publishOptions,
);
await this.publishVideoStream(this.camera.state.mediaStream);
}

// Start camera if backend config specifies, and there is no local setting
Expand Down
7 changes: 7 additions & 0 deletions packages/client/src/compatibility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Checks if the current platform is a mobile device.
*
* See:
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent
*/
export const isMobile = () => /Mobi/i.test(navigator.userAgent);
65 changes: 18 additions & 47 deletions packages/client/src/devices/CameraManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@ import { CameraDirection, CameraManagerState } from './CameraManagerState';
import { InputMediaDeviceManager } from './InputMediaDeviceManager';
import { getVideoDevices, getVideoStream } from './devices';
import { TrackType } from '../gen/video/sfu/models/models';
import { PreferredCodec, PublishOptions } from '../types';
import { PreferredCodec } from '../types';
import { isMobile } from '../compatibility';

export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
private targetResolution = {
width: 1280,
height: 720,
};

/**
* The options to use when publishing the video stream.
*
* @internal
*/
publishOptions: PublishOptions | undefined;

/**
* Constructs a new CameraManager.
*
Expand All @@ -34,10 +28,14 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
* @param direction the direction of the camera to select.
*/
async selectDirection(direction: Exclude<CameraDirection, undefined>) {
this.state.setDirection(direction);
// Providing both device id and direction doesn't work, so we deselect the device
this.state.setDevice(undefined);
await this.applySettingsToStream();
if (isMobile()) {
this.state.setDirection(direction);
// Providing both device id and direction doesn't work, so we deselect the device
this.state.setDevice(undefined);
await this.applySettingsToStream();
} else {
this.logger('warn', 'Camera direction ignored for desktop devices');
}
}

/**
Expand Down Expand Up @@ -65,10 +63,10 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
this.logger('warn', 'could not apply target resolution', error);
}
}
if (this.enabled) {
const { width, height } = this.state
.mediaStream!.getVideoTracks()[0]
?.getSettings();
if (this.enabled && this.state.mediaStream) {
const [videoTrack] = this.state.mediaStream.getVideoTracks();
if (!videoTrack) return;
const { width, height } = videoTrack.getSettings();
if (
width !== this.targetResolution.width ||
height !== this.targetResolution.height
Expand All @@ -86,38 +84,11 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
* Sets the preferred codec for encoding the video.
*
* @internal internal use only, not part of the public API.
* @deprecated use {@link call.updatePublishOptions} instead.
* @param codec the codec to use for encoding the video.
*/
setPreferredCodec(codec: PreferredCodec | undefined) {
this.updatePublishOptions({ preferredCodec: codec });
}

/**
* Updates the preferred publish options for the video stream.
*
* @internal
* @param options the options to use.
*/
updatePublishOptions(options: PublishOptions) {
this.publishOptions = { ...this.publishOptions, ...options };
}

/**
* Returns the capture resolution of the camera.
*/
getCaptureResolution() {
const { mediaStream } = this.state;
if (!mediaStream) return;

const [videoTrack] = mediaStream.getVideoTracks();
if (!videoTrack) return;

const settings = videoTrack.getSettings();
return {
width: settings.width,
height: settings.height,
frameRate: settings.frameRate,
};
this.call.updatePublishOptions({ preferredCodec: codec });
}

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

protected publishStream(stream: MediaStream): Promise<void> {
return this.call.publishVideoStream(stream, this.publishOptions);
return this.call.publishVideoStream(stream);
}

protected stopPublishStream(stopTracks: boolean): Promise<void> {
Expand Down
4 changes: 1 addition & 3 deletions packages/client/src/devices/ScreenShareManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ export class ScreenShareManager extends InputMediaDeviceManager<
}

protected publishStream(stream: MediaStream): Promise<void> {
return this.call.publishScreenShareStream(stream, {
screenShareSettings: this.state.settings,
});
return this.call.publishScreenShareStream(stream);
}

protected async stopPublishStream(stopTracks: boolean): Promise<void> {
Expand Down
22 changes: 7 additions & 15 deletions packages/client/src/devices/__tests__/CameraManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ vi.mock('../../Call.ts', () => {
};
});

vi.mock('../../compatibility.ts', () => {
console.log('MOCKING mobile device');
return {
isMobile: () => true,
};
});

describe('CameraManager', () => {
let manager: CameraManager;

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

expect(manager['call'].publishVideoStream).toHaveBeenCalledWith(
manager.state.mediaStream,
undefined,
);
});

it('publish stream with preferred codec', async () => {
manager['call'].state.setCallingState(CallingState.JOINED);
manager.setPreferredCodec('h264');

await manager.enable();

expect(manager['call'].publishVideoStream).toHaveBeenCalledWith(
manager.state.mediaStream,
{
preferredCodec: 'h264',
},
);
});

Expand Down
Loading

0 comments on commit f1cccbb

Please sign in to comment.