@stream-io/video-client 1.7.1 → 1.7.2
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 +43 -28
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +43 -28
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +43 -28
- package/dist/index.es.js.map +1 -1
- package/dist/src/devices/CameraManager.d.ts +19 -20
- package/dist/src/rtc/videoLayers.d.ts +4 -4
- package/dist/src/types.d.ts +7 -1
- package/package.json +1 -1
- package/src/devices/CameraManager.ts +31 -29
- package/src/devices/__tests__/CameraManager.test.ts +1 -3
- package/src/rtc/Publisher.ts +5 -16
- package/src/rtc/videoLayers.ts +9 -6
- package/src/types.ts +8 -1
|
@@ -2,29 +2,21 @@ import { Observable } from 'rxjs';
|
|
|
2
2
|
import { Call } from '../Call';
|
|
3
3
|
import { CameraDirection, CameraManagerState } from './CameraManagerState';
|
|
4
4
|
import { InputMediaDeviceManager } from './InputMediaDeviceManager';
|
|
5
|
-
import { PublishOptions } from '../types';
|
|
6
|
-
type PreferredCodec = 'vp8' | 'h264' | string;
|
|
5
|
+
import { PreferredCodec, PublishOptions } from '../types';
|
|
7
6
|
export declare class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
|
|
8
7
|
private targetResolution;
|
|
9
8
|
/**
|
|
10
|
-
* The
|
|
9
|
+
* The options to use when publishing the video stream.
|
|
11
10
|
*
|
|
12
|
-
* @internal
|
|
11
|
+
* @internal
|
|
13
12
|
*/
|
|
14
|
-
|
|
13
|
+
publishOptions: PublishOptions | undefined;
|
|
15
14
|
/**
|
|
16
|
-
*
|
|
15
|
+
* Constructs a new CameraManager.
|
|
17
16
|
*
|
|
18
|
-
* @
|
|
17
|
+
* @param call the call instance.
|
|
19
18
|
*/
|
|
20
|
-
preferredBitrate: number | undefined;
|
|
21
19
|
constructor(call: Call);
|
|
22
|
-
/**
|
|
23
|
-
* The publish options for the camera.
|
|
24
|
-
*
|
|
25
|
-
* @internal internal use only, not part of the public API.
|
|
26
|
-
*/
|
|
27
|
-
get publishOptions(): PublishOptions;
|
|
28
20
|
/**
|
|
29
21
|
* Select the camera direction.
|
|
30
22
|
*
|
|
@@ -51,17 +43,24 @@ export declare class CameraManager extends InputMediaDeviceManager<CameraManager
|
|
|
51
43
|
* @internal internal use only, not part of the public API.
|
|
52
44
|
* @param codec the codec to use for encoding the video.
|
|
53
45
|
*/
|
|
54
|
-
setPreferredCodec(codec:
|
|
46
|
+
setPreferredCodec(codec: PreferredCodec | undefined): void;
|
|
55
47
|
/**
|
|
56
|
-
*
|
|
48
|
+
* Updates the preferred publish options for the video stream.
|
|
57
49
|
*
|
|
58
|
-
* @internal
|
|
59
|
-
* @param
|
|
50
|
+
* @internal
|
|
51
|
+
* @param options the options to use.
|
|
52
|
+
*/
|
|
53
|
+
updatePublishOptions(options: PublishOptions): void;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the capture resolution of the camera.
|
|
60
56
|
*/
|
|
61
|
-
|
|
57
|
+
getCaptureResolution(): {
|
|
58
|
+
width: number | undefined;
|
|
59
|
+
height: number | undefined;
|
|
60
|
+
frameRate: number | undefined;
|
|
61
|
+
} | undefined;
|
|
62
62
|
protected getDevices(): Observable<MediaDeviceInfo[]>;
|
|
63
63
|
protected getStream(constraints: MediaTrackConstraints): Promise<MediaStream>;
|
|
64
64
|
protected publishStream(stream: MediaStream): Promise<void>;
|
|
65
65
|
protected stopPublishStream(stopTracks: boolean): Promise<void>;
|
|
66
66
|
}
|
|
67
|
-
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PublishOptions } from '../types';
|
|
2
2
|
import { TargetResolutionResponse } from '../gen/shims';
|
|
3
3
|
export type OptimalVideoLayer = RTCRtpEncodingParameters & {
|
|
4
4
|
width: number;
|
|
@@ -10,9 +10,9 @@ export type OptimalVideoLayer = RTCRtpEncodingParameters & {
|
|
|
10
10
|
*
|
|
11
11
|
* @param videoTrack the video track to find optimal layers for.
|
|
12
12
|
* @param targetResolution the expected target resolution.
|
|
13
|
-
* @param
|
|
13
|
+
* @param publishOptions the publish options for the track.
|
|
14
14
|
*/
|
|
15
|
-
export declare const findOptimalVideoLayers: (videoTrack: MediaStreamTrack, targetResolution
|
|
15
|
+
export declare const findOptimalVideoLayers: (videoTrack: MediaStreamTrack, targetResolution?: TargetResolutionResponse, publishOptions?: PublishOptions) => OptimalVideoLayer[];
|
|
16
16
|
/**
|
|
17
17
|
* Computes the maximum bitrate for a given resolution.
|
|
18
18
|
* If the current resolution is lower than the target resolution,
|
|
@@ -26,4 +26,4 @@ export declare const findOptimalVideoLayers: (videoTrack: MediaStreamTrack, targ
|
|
|
26
26
|
* @param preferredBitrate the preferred bitrate for the track.
|
|
27
27
|
*/
|
|
28
28
|
export declare const getComputedMaxBitrate: (targetResolution: TargetResolutionResponse, currentWidth: number, currentHeight: number, preferredBitrate: number | undefined) => number;
|
|
29
|
-
export declare const findOptimalScreenSharingLayers: (videoTrack: MediaStreamTrack,
|
|
29
|
+
export declare const findOptimalScreenSharingLayers: (videoTrack: MediaStreamTrack, publishOptions?: PublishOptions, defaultMaxBitrate?: number) => OptimalVideoLayer[];
|
package/dist/src/types.d.ts
CHANGED
|
@@ -109,9 +109,15 @@ export type SubscriptionChange = {
|
|
|
109
109
|
export type SubscriptionChanges = {
|
|
110
110
|
[sessionId: string]: SubscriptionChange;
|
|
111
111
|
};
|
|
112
|
+
/**
|
|
113
|
+
* A preferred codec to use when publishing a video track.
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
export type PreferredCodec = 'vp8' | 'h264' | string;
|
|
112
117
|
export type PublishOptions = {
|
|
113
|
-
preferredCodec?:
|
|
118
|
+
preferredCodec?: PreferredCodec | null;
|
|
114
119
|
preferredBitrate?: number;
|
|
120
|
+
bitrateDownscaleFactor?: number;
|
|
115
121
|
screenShareSettings?: ScreenShareSettings;
|
|
116
122
|
};
|
|
117
123
|
export type ScreenShareSettings = {
|
package/package.json
CHANGED
|
@@ -4,9 +4,7 @@ import { CameraDirection, CameraManagerState } from './CameraManagerState';
|
|
|
4
4
|
import { InputMediaDeviceManager } from './InputMediaDeviceManager';
|
|
5
5
|
import { getVideoDevices, getVideoStream } from './devices';
|
|
6
6
|
import { TrackType } from '../gen/video/sfu/models/models';
|
|
7
|
-
import { PublishOptions } from '../types';
|
|
8
|
-
|
|
9
|
-
type PreferredCodec = 'vp8' | 'h264' | string;
|
|
7
|
+
import { PreferredCodec, PublishOptions } from '../types';
|
|
10
8
|
|
|
11
9
|
export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
|
|
12
10
|
private targetResolution = {
|
|
@@ -15,35 +13,21 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
|
|
|
15
13
|
};
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
|
-
* The
|
|
16
|
+
* The options to use when publishing the video stream.
|
|
19
17
|
*
|
|
20
|
-
* @internal
|
|
18
|
+
* @internal
|
|
21
19
|
*/
|
|
22
|
-
|
|
20
|
+
publishOptions: PublishOptions | undefined;
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
|
-
*
|
|
23
|
+
* Constructs a new CameraManager.
|
|
26
24
|
*
|
|
27
|
-
* @
|
|
25
|
+
* @param call the call instance.
|
|
28
26
|
*/
|
|
29
|
-
preferredBitrate: number | undefined;
|
|
30
|
-
|
|
31
27
|
constructor(call: Call) {
|
|
32
28
|
super(call, new CameraManagerState(), TrackType.VIDEO);
|
|
33
29
|
}
|
|
34
30
|
|
|
35
|
-
/**
|
|
36
|
-
* The publish options for the camera.
|
|
37
|
-
*
|
|
38
|
-
* @internal internal use only, not part of the public API.
|
|
39
|
-
*/
|
|
40
|
-
get publishOptions(): PublishOptions {
|
|
41
|
-
return {
|
|
42
|
-
preferredCodec: this.preferredCodec,
|
|
43
|
-
preferredBitrate: this.preferredBitrate,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
31
|
/**
|
|
48
32
|
* Select the camera direction.
|
|
49
33
|
*
|
|
@@ -104,18 +88,36 @@ export class CameraManager extends InputMediaDeviceManager<CameraManagerState> {
|
|
|
104
88
|
* @internal internal use only, not part of the public API.
|
|
105
89
|
* @param codec the codec to use for encoding the video.
|
|
106
90
|
*/
|
|
107
|
-
setPreferredCodec(codec:
|
|
108
|
-
this.preferredCodec
|
|
91
|
+
setPreferredCodec(codec: PreferredCodec | undefined) {
|
|
92
|
+
this.updatePublishOptions({ preferredCodec: codec });
|
|
109
93
|
}
|
|
110
94
|
|
|
111
95
|
/**
|
|
112
|
-
*
|
|
96
|
+
* Updates the preferred publish options for the video stream.
|
|
113
97
|
*
|
|
114
|
-
* @internal
|
|
115
|
-
* @param
|
|
98
|
+
* @internal
|
|
99
|
+
* @param options the options to use.
|
|
116
100
|
*/
|
|
117
|
-
|
|
118
|
-
this.
|
|
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
|
+
};
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
protected getDevices(): Observable<MediaDeviceInfo[]> {
|
package/src/rtc/Publisher.ts
CHANGED
|
@@ -259,16 +259,11 @@ export class Publisher {
|
|
|
259
259
|
const screenShareBitrate =
|
|
260
260
|
settings?.screensharing.target_resolution?.bitrate;
|
|
261
261
|
|
|
262
|
-
const { preferredBitrate, preferredCodec, screenShareSettings } = opts;
|
|
263
262
|
const videoEncodings =
|
|
264
263
|
trackType === TrackType.VIDEO
|
|
265
|
-
? findOptimalVideoLayers(track, targetResolution,
|
|
264
|
+
? findOptimalVideoLayers(track, targetResolution, opts)
|
|
266
265
|
: trackType === TrackType.SCREEN_SHARE
|
|
267
|
-
? findOptimalScreenSharingLayers(
|
|
268
|
-
track,
|
|
269
|
-
screenShareSettings,
|
|
270
|
-
screenShareBitrate,
|
|
271
|
-
)
|
|
266
|
+
? findOptimalScreenSharingLayers(track, opts, screenShareBitrate)
|
|
272
267
|
: undefined;
|
|
273
268
|
|
|
274
269
|
// listen for 'ended' event on the track as it might be ended abruptly
|
|
@@ -293,6 +288,7 @@ export class Publisher {
|
|
|
293
288
|
this.transceiverRegistry[trackType] = transceiver;
|
|
294
289
|
this.publishOptionsPerTrackType.set(trackType, opts);
|
|
295
290
|
|
|
291
|
+
const { preferredCodec } = opts;
|
|
296
292
|
const codec =
|
|
297
293
|
isReactNative() && trackType === TrackType.VIDEO && !preferredCodec
|
|
298
294
|
? getRNOptimalCodec()
|
|
@@ -713,16 +709,9 @@ export class Publisher {
|
|
|
713
709
|
const publishOpts = this.publishOptionsPerTrackType.get(trackType);
|
|
714
710
|
optimalLayers =
|
|
715
711
|
trackType === TrackType.VIDEO
|
|
716
|
-
? findOptimalVideoLayers(
|
|
717
|
-
track,
|
|
718
|
-
targetResolution,
|
|
719
|
-
publishOpts?.preferredBitrate,
|
|
720
|
-
)
|
|
712
|
+
? findOptimalVideoLayers(track, targetResolution, publishOpts)
|
|
721
713
|
: trackType === TrackType.SCREEN_SHARE
|
|
722
|
-
? findOptimalScreenSharingLayers(
|
|
723
|
-
track,
|
|
724
|
-
publishOpts?.screenShareSettings,
|
|
725
|
-
)
|
|
714
|
+
? findOptimalScreenSharingLayers(track, publishOpts)
|
|
726
715
|
: [];
|
|
727
716
|
this.trackLayersCache[trackType] = optimalLayers;
|
|
728
717
|
} else {
|
package/src/rtc/videoLayers.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PublishOptions } from '../types';
|
|
2
2
|
import { TargetResolutionResponse } from '../gen/shims';
|
|
3
3
|
|
|
4
4
|
export type OptimalVideoLayer = RTCRtpEncodingParameters & {
|
|
@@ -25,17 +25,17 @@ const defaultBitratePerRid: Record<string, number> = {
|
|
|
25
25
|
*
|
|
26
26
|
* @param videoTrack the video track to find optimal layers for.
|
|
27
27
|
* @param targetResolution the expected target resolution.
|
|
28
|
-
* @param
|
|
28
|
+
* @param publishOptions the publish options for the track.
|
|
29
29
|
*/
|
|
30
30
|
export const findOptimalVideoLayers = (
|
|
31
31
|
videoTrack: MediaStreamTrack,
|
|
32
32
|
targetResolution: TargetResolutionResponse = defaultTargetResolution,
|
|
33
|
-
|
|
33
|
+
publishOptions?: PublishOptions,
|
|
34
34
|
) => {
|
|
35
35
|
const optimalVideoLayers: OptimalVideoLayer[] = [];
|
|
36
36
|
const settings = videoTrack.getSettings();
|
|
37
37
|
const { width: w = 0, height: h = 0 } = settings;
|
|
38
|
-
|
|
38
|
+
const { preferredBitrate, bitrateDownscaleFactor = 2 } = publishOptions || {};
|
|
39
39
|
const maxBitrate = getComputedMaxBitrate(
|
|
40
40
|
targetResolution,
|
|
41
41
|
w,
|
|
@@ -43,6 +43,7 @@ export const findOptimalVideoLayers = (
|
|
|
43
43
|
preferredBitrate,
|
|
44
44
|
);
|
|
45
45
|
let downscaleFactor = 1;
|
|
46
|
+
let bitrateFactor = 1;
|
|
46
47
|
['f', 'h', 'q'].forEach((rid) => {
|
|
47
48
|
// Reversing the order [f, h, q] to [q, h, f] as Chrome uses encoding index
|
|
48
49
|
// when deciding which layer to disable when CPU or bandwidth is constrained.
|
|
@@ -53,11 +54,12 @@ export const findOptimalVideoLayers = (
|
|
|
53
54
|
width: Math.round(w / downscaleFactor),
|
|
54
55
|
height: Math.round(h / downscaleFactor),
|
|
55
56
|
maxBitrate:
|
|
56
|
-
Math.round(maxBitrate /
|
|
57
|
+
Math.round(maxBitrate / bitrateFactor) || defaultBitratePerRid[rid],
|
|
57
58
|
scaleResolutionDownBy: downscaleFactor,
|
|
58
59
|
maxFramerate: 30,
|
|
59
60
|
});
|
|
60
61
|
downscaleFactor *= 2;
|
|
62
|
+
bitrateFactor *= bitrateDownscaleFactor;
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
// for simplicity, we start with all layers enabled, then this function
|
|
@@ -135,9 +137,10 @@ const withSimulcastConstraints = (
|
|
|
135
137
|
|
|
136
138
|
export const findOptimalScreenSharingLayers = (
|
|
137
139
|
videoTrack: MediaStreamTrack,
|
|
138
|
-
|
|
140
|
+
publishOptions?: PublishOptions,
|
|
139
141
|
defaultMaxBitrate = 3000000,
|
|
140
142
|
): OptimalVideoLayer[] => {
|
|
143
|
+
const { screenShareSettings: preferences } = publishOptions || {};
|
|
141
144
|
const settings = videoTrack.getSettings();
|
|
142
145
|
return [
|
|
143
146
|
{
|
package/src/types.ts
CHANGED
|
@@ -146,9 +146,16 @@ export type SubscriptionChanges = {
|
|
|
146
146
|
[sessionId: string]: SubscriptionChange;
|
|
147
147
|
};
|
|
148
148
|
|
|
149
|
+
/**
|
|
150
|
+
* A preferred codec to use when publishing a video track.
|
|
151
|
+
* @internal
|
|
152
|
+
*/
|
|
153
|
+
export type PreferredCodec = 'vp8' | 'h264' | string;
|
|
154
|
+
|
|
149
155
|
export type PublishOptions = {
|
|
150
|
-
preferredCodec?:
|
|
156
|
+
preferredCodec?: PreferredCodec | null;
|
|
151
157
|
preferredBitrate?: number;
|
|
158
|
+
bitrateDownscaleFactor?: number;
|
|
152
159
|
screenShareSettings?: ScreenShareSettings;
|
|
153
160
|
};
|
|
154
161
|
|