@livedigital/client 1.13.0 → 1.13.1
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/dist/constants/videoConstrains.d.ts +8 -24
- package/dist/engine/index.d.ts +4 -4
- package/dist/engine/media/VideoConsumer.d.ts +5 -0
- package/dist/engine/media/index.d.ts +3 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.es.js +1 -1
- package/dist/index.js +2 -2
- package/dist/types/common.d.ts +26 -0
- package/package.json +1 -1
- package/src/constants/videoConstrains.ts +5 -5
- package/src/engine/Peer.ts +18 -1
- package/src/engine/handlers/MediaSoupEventHandler.ts +2 -1
- package/src/engine/index.ts +19 -31
- package/src/engine/media/VideoConsumer.ts +23 -0
- package/src/engine/media/index.ts +30 -1
- package/src/index.ts +4 -4
- package/src/types/common.ts +16 -0
package/dist/types/common.d.ts
CHANGED
|
@@ -153,3 +153,29 @@ export declare type PayloadOfPublishedMedia = {
|
|
|
153
153
|
label: TrackLabel;
|
|
154
154
|
};
|
|
155
155
|
export declare type PayloadOfUnpublishedMedia = PayloadOfPublishedMedia;
|
|
156
|
+
export declare type ChangePreferredLayersPayload = PreferredLayersParams & {
|
|
157
|
+
consumerId: string;
|
|
158
|
+
spatialLayer: number;
|
|
159
|
+
temporalLayer: number;
|
|
160
|
+
};
|
|
161
|
+
export declare type CreateVideoTrackParams = {
|
|
162
|
+
videoTrackOptions: {
|
|
163
|
+
deviceId?: string;
|
|
164
|
+
width?: {
|
|
165
|
+
max?: number;
|
|
166
|
+
min?: number;
|
|
167
|
+
ideal?: number;
|
|
168
|
+
};
|
|
169
|
+
height?: {
|
|
170
|
+
max?: number;
|
|
171
|
+
min?: number;
|
|
172
|
+
ideal?: number;
|
|
173
|
+
};
|
|
174
|
+
frameRate?: {
|
|
175
|
+
max?: number;
|
|
176
|
+
min?: number;
|
|
177
|
+
ideal?: number;
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
encoderConfig: VideoEncoderConfig;
|
|
181
|
+
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// eslint-disable-next-line import/prefer-default-export
|
|
2
2
|
export const VIDEO_CONSTRAINS = {
|
|
3
|
-
qvga: { width:
|
|
4
|
-
vga: { width:
|
|
3
|
+
qvga: { width: 320, height: 240 },
|
|
4
|
+
vga: { width: 640, height: 480 },
|
|
5
5
|
hd: {
|
|
6
|
-
width:
|
|
7
|
-
height:
|
|
6
|
+
width: 1280,
|
|
7
|
+
height: 720,
|
|
8
8
|
},
|
|
9
|
-
fullhd: { width:
|
|
9
|
+
fullhd: { width: 1920, height: 1080 },
|
|
10
10
|
};
|
package/src/engine/Peer.ts
CHANGED
|
@@ -9,7 +9,9 @@ import {
|
|
|
9
9
|
ConnectionQuality,
|
|
10
10
|
StartTrackPayload,
|
|
11
11
|
EndTrackPayload,
|
|
12
|
-
PayloadOfPublishedMedia,
|
|
12
|
+
PayloadOfPublishedMedia,
|
|
13
|
+
PayloadOfUnpublishedMedia,
|
|
14
|
+
ChangePreferredLayersPayload,
|
|
13
15
|
} from '../types/common';
|
|
14
16
|
import Consumer from './media/Consumer';
|
|
15
17
|
import VideoConsumer from './media/VideoConsumer';
|
|
@@ -271,6 +273,13 @@ class Peer {
|
|
|
271
273
|
spatialLayer,
|
|
272
274
|
temporalLayer,
|
|
273
275
|
});
|
|
276
|
+
|
|
277
|
+
this.logger.debug('changeConsumerPreferredLayers()', {
|
|
278
|
+
peer: this,
|
|
279
|
+
consumer,
|
|
280
|
+
spatialLayer,
|
|
281
|
+
temporalLayer,
|
|
282
|
+
});
|
|
274
283
|
} catch (err) {
|
|
275
284
|
this.logger.error('changeConsumerPreferredLayers()', {
|
|
276
285
|
peer: this,
|
|
@@ -424,6 +433,14 @@ class Peer {
|
|
|
424
433
|
this.outgoingConnectionQuality = Peer.getConnectionQualityByScore(score);
|
|
425
434
|
this.emitConnectionQuality();
|
|
426
435
|
});
|
|
436
|
+
|
|
437
|
+
this.observer.on(MEDIASOUP_EVENTS.consumerChangePreferredLayers, (payload: ChangePreferredLayersPayload) => {
|
|
438
|
+
const consumer = this.consumers.get(payload.consumerId);
|
|
439
|
+
if (consumer instanceof VideoConsumer) {
|
|
440
|
+
consumer.setCurrentTemporalLayer(payload.temporalLayer);
|
|
441
|
+
consumer.setCurrentSpatialLayer(payload.spatialLayer);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
427
444
|
}
|
|
428
445
|
|
|
429
446
|
private emitConnectionQuality(): void {
|
|
@@ -71,7 +71,7 @@ class MediaSoupEventHandler {
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
connection.on(MEDIASOUP_EVENTS.consumerChangePreferredLayers, ({
|
|
74
|
-
peerId, spatialLayer, temporalLayer,
|
|
74
|
+
peerId, spatialLayer, temporalLayer, consumerId,
|
|
75
75
|
}: ChangePreferredLayersParams) => {
|
|
76
76
|
const peer = this.engine.peers.find((item) => item.id === peerId);
|
|
77
77
|
if (!peer || peer.isMe) {
|
|
@@ -79,6 +79,7 @@ class MediaSoupEventHandler {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
peer.observer.safeEmit(MEDIASOUP_EVENTS.consumerChangePreferredLayers, {
|
|
82
|
+
consumerId,
|
|
82
83
|
spatialLayer,
|
|
83
84
|
temporalLayer,
|
|
84
85
|
});
|
package/src/engine/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { RtpCapabilities } from 'mediasoup-client/lib/RtpParameters';
|
|
2
|
-
import { VIDEO_CONSTRAINS } from '../constants/videoConstrains';
|
|
3
2
|
import {
|
|
4
3
|
PeerResponse,
|
|
5
4
|
JoinChannelParams,
|
|
@@ -193,32 +192,26 @@ class Engine {
|
|
|
193
192
|
}
|
|
194
193
|
}
|
|
195
194
|
|
|
196
|
-
async createCameraVideoTrack(options?: CreateCameraVideoTrackOptions): Promise<Track
|
|
195
|
+
async createCameraVideoTrack(options?: CreateCameraVideoTrackOptions): Promise<Track> {
|
|
196
|
+
const trackParams = Media.getCameraVideoTrackParams(options);
|
|
197
197
|
try {
|
|
198
198
|
const track = await this.media.createUserMediaTrack({
|
|
199
199
|
audio: false,
|
|
200
|
-
video:
|
|
201
|
-
deviceId: options?.deviceId,
|
|
202
|
-
frameRate: options?.frameRate || 15,
|
|
203
|
-
width: options?.width || VIDEO_CONSTRAINS.hd.width,
|
|
204
|
-
height: options?.height || VIDEO_CONSTRAINS.hd.height,
|
|
205
|
-
},
|
|
200
|
+
video: trackParams.videoTrackOptions,
|
|
206
201
|
});
|
|
207
202
|
|
|
208
203
|
track.setLabel(TrackLabel.Camera);
|
|
209
|
-
|
|
210
|
-
track.setEncoderConfig(options.encoderConfig);
|
|
211
|
-
}
|
|
204
|
+
track.setEncoderConfig(trackParams.encoderConfig);
|
|
212
205
|
|
|
213
|
-
this.logger.debug('createCameraVideoTrack()', {
|
|
206
|
+
this.logger.debug('createCameraVideoTrack()', { trackParams, track });
|
|
214
207
|
return track;
|
|
215
208
|
} catch (error) {
|
|
216
|
-
this.logger.error('createCameraVideoTrack()', { error,
|
|
217
|
-
|
|
209
|
+
this.logger.error('createCameraVideoTrack()', { error, trackParams });
|
|
210
|
+
throw new Error(`Can not create camera track: ${error.message}`);
|
|
218
211
|
}
|
|
219
212
|
}
|
|
220
213
|
|
|
221
|
-
async createMicrophoneAudioTrack(options?: CreateMicrophoneAudioTrackOptions): Promise<Track
|
|
214
|
+
async createMicrophoneAudioTrack(options?: CreateMicrophoneAudioTrackOptions): Promise<Track> {
|
|
222
215
|
try {
|
|
223
216
|
const track = await this.media.createUserMediaTrack({
|
|
224
217
|
video: false,
|
|
@@ -236,19 +229,16 @@ class Engine {
|
|
|
236
229
|
return track;
|
|
237
230
|
} catch (error) {
|
|
238
231
|
this.logger.error('createMicrophoneAudioTrack()', { error, options });
|
|
239
|
-
|
|
232
|
+
throw new Error(`Can not create microphone track: ${error.message}`);
|
|
240
233
|
}
|
|
241
234
|
}
|
|
242
235
|
|
|
243
|
-
async createScreenVideoTrack(options?: CreateScreenVideoTrackOptions): Promise<Track
|
|
236
|
+
async createScreenVideoTrack(options?: CreateScreenVideoTrackOptions): Promise<Track> {
|
|
237
|
+
const trackParams = Media.getScreenVideoTrackParams(options);
|
|
244
238
|
try {
|
|
245
239
|
const track = await this.media.createDisplayMediaTrack({
|
|
246
240
|
audio: false,
|
|
247
|
-
video:
|
|
248
|
-
frameRate: options?.frameRate || 30,
|
|
249
|
-
width: options?.width || VIDEO_CONSTRAINS.fullhd.width,
|
|
250
|
-
height: options?.height || VIDEO_CONSTRAINS.fullhd.height,
|
|
251
|
-
},
|
|
241
|
+
video: trackParams.videoTrackOptions,
|
|
252
242
|
});
|
|
253
243
|
|
|
254
244
|
track.mediaStreamTrack.addEventListener('ended', () => {
|
|
@@ -256,19 +246,17 @@ class Engine {
|
|
|
256
246
|
});
|
|
257
247
|
|
|
258
248
|
track.setLabel(TrackLabel.ScreenVideo);
|
|
259
|
-
|
|
260
|
-
track.setEncoderConfig(options.encoderConfig);
|
|
261
|
-
}
|
|
249
|
+
track.setEncoderConfig(trackParams.encoderConfig);
|
|
262
250
|
|
|
263
|
-
this.logger.debug('createScreenVideoTrack()', {
|
|
251
|
+
this.logger.debug('createScreenVideoTrack()', { trackParams, track });
|
|
264
252
|
return track;
|
|
265
253
|
} catch (error) {
|
|
266
|
-
this.logger.error('createScreenVideoTrack()', { error,
|
|
267
|
-
|
|
254
|
+
this.logger.error('createScreenVideoTrack()', { error, trackParams });
|
|
255
|
+
throw new Error(`Can not create screen video track: ${error.message}`);
|
|
268
256
|
}
|
|
269
257
|
}
|
|
270
258
|
|
|
271
|
-
async createScreenAudioTrack(options?: CreateScreenAudioTrackOptions): Promise<Track
|
|
259
|
+
async createScreenAudioTrack(options?: CreateScreenAudioTrackOptions): Promise<Track> {
|
|
272
260
|
try {
|
|
273
261
|
const track = await this.media.createDisplayMediaTrack({
|
|
274
262
|
video: false,
|
|
@@ -288,7 +276,7 @@ class Engine {
|
|
|
288
276
|
return track;
|
|
289
277
|
} catch (error) {
|
|
290
278
|
this.logger.error('createScreenAudioTrack()', { error, options });
|
|
291
|
-
|
|
279
|
+
throw new Error(`Can not create screen audio track: ${error.message}`);
|
|
292
280
|
}
|
|
293
281
|
}
|
|
294
282
|
|
|
@@ -329,7 +317,7 @@ class Engine {
|
|
|
329
317
|
label: track.getLabel(),
|
|
330
318
|
} as StartTrackPayload);
|
|
331
319
|
|
|
332
|
-
this.logger.debug('publish()', { track });
|
|
320
|
+
this.logger.debug('publish()', { track, encodings, codecOptions });
|
|
333
321
|
});
|
|
334
322
|
|
|
335
323
|
try {
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { Consumer as MediasoupConsumer } from 'mediasoup-client/lib/types';
|
|
2
2
|
import { parseScalabilityMode } from 'mediasoup-client';
|
|
3
3
|
import Consumer from './Consumer';
|
|
4
|
+
import Logger from '../Logger';
|
|
4
5
|
|
|
5
6
|
class VideoConsumer extends Consumer {
|
|
6
7
|
public spatialLayers = 0;
|
|
7
8
|
|
|
8
9
|
public temporalLayers = 0;
|
|
9
10
|
|
|
11
|
+
public currentSpatialLayer = 0;
|
|
12
|
+
|
|
13
|
+
public currentTemporalLayer = 0;
|
|
14
|
+
|
|
15
|
+
private readonly logger: Logger;
|
|
16
|
+
|
|
10
17
|
constructor(consumer: MediasoupConsumer) {
|
|
11
18
|
super(consumer);
|
|
19
|
+
this.logger = new Logger('VideoConsumer');
|
|
12
20
|
this.parseScalabilityMode();
|
|
13
21
|
}
|
|
14
22
|
|
|
@@ -18,8 +26,23 @@ class VideoConsumer extends Consumer {
|
|
|
18
26
|
const { spatialLayers, temporalLayers } = parseScalabilityMode(scalabilityMode);
|
|
19
27
|
this.spatialLayers = spatialLayers;
|
|
20
28
|
this.temporalLayers = temporalLayers;
|
|
29
|
+
this.logger.debug('parseScalabilityMode()', {
|
|
30
|
+
scalabilityMode,
|
|
31
|
+
spatialLayers,
|
|
32
|
+
temporalLayers,
|
|
33
|
+
});
|
|
21
34
|
}
|
|
22
35
|
}
|
|
36
|
+
|
|
37
|
+
setCurrentSpatialLayer(currentSpatialLayer: number): void {
|
|
38
|
+
this.currentSpatialLayer = currentSpatialLayer;
|
|
39
|
+
this.logger.debug('setCurrentSpatialLayer()', { currentSpatialLayer });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
setCurrentTemporalLayer(currentTemporalLayer: number): void {
|
|
43
|
+
this.currentTemporalLayer = currentTemporalLayer;
|
|
44
|
+
this.logger.debug('setCurrentTemporalLayer()', { currentTemporalLayer });
|
|
45
|
+
}
|
|
23
46
|
}
|
|
24
47
|
|
|
25
48
|
export default VideoConsumer;
|
|
@@ -2,8 +2,10 @@ import { Device } from 'mediasoup-client';
|
|
|
2
2
|
import { RtpCapabilities, RtpCodecCapability } from 'mediasoup-client/lib/RtpParameters';
|
|
3
3
|
import VideoTrack from './tracks/VideoTrack';
|
|
4
4
|
import AudioTrack from './tracks/AudioTrack';
|
|
5
|
-
import { Track } from '../../types/common';
|
|
5
|
+
import { CreateScreenVideoTrackOptions, CreateVideoTrackParams, Track } from '../../types/common';
|
|
6
6
|
import Logger from '../Logger';
|
|
7
|
+
import { VIDEO_CONSTRAINS } from '../../constants/videoConstrains';
|
|
8
|
+
import { SCREEN_SHARING_SIMULCAST_ENCODINGS, WEBCAM_SIMULCAST_ENCODINGS } from '../../constants/simulcastEncodings';
|
|
7
9
|
|
|
8
10
|
class Media {
|
|
9
11
|
public isDeviceLoaded = false;
|
|
@@ -78,6 +80,33 @@ class Media {
|
|
|
78
80
|
getAllTracks(): Track[] {
|
|
79
81
|
return Array.from(this.tracks.values());
|
|
80
82
|
}
|
|
83
|
+
|
|
84
|
+
static getScreenVideoTrackParams(options?: CreateScreenVideoTrackOptions): CreateVideoTrackParams {
|
|
85
|
+
return {
|
|
86
|
+
videoTrackOptions: {
|
|
87
|
+
frameRate: { ideal: options?.frameRate || 30 },
|
|
88
|
+
width: { ideal: options?.width || VIDEO_CONSTRAINS.fullhd.width },
|
|
89
|
+
height: { ideal: options?.height || VIDEO_CONSTRAINS.fullhd.height },
|
|
90
|
+
},
|
|
91
|
+
encoderConfig: options?.encoderConfig || {
|
|
92
|
+
encodings: SCREEN_SHARING_SIMULCAST_ENCODINGS,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static getCameraVideoTrackParams(options?: CreateScreenVideoTrackOptions): CreateVideoTrackParams {
|
|
98
|
+
return {
|
|
99
|
+
videoTrackOptions: {
|
|
100
|
+
deviceId: options?.deviceId,
|
|
101
|
+
frameRate: { ideal: options?.frameRate || 30 },
|
|
102
|
+
width: { ideal: options?.width || VIDEO_CONSTRAINS.hd.width },
|
|
103
|
+
height: { ideal: options?.height || VIDEO_CONSTRAINS.hd.height },
|
|
104
|
+
},
|
|
105
|
+
encoderConfig: options?.encoderConfig || {
|
|
106
|
+
encodings: WEBCAM_SIMULCAST_ENCODINGS,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
81
110
|
}
|
|
82
111
|
|
|
83
112
|
export default Media;
|
package/src/index.ts
CHANGED
|
@@ -88,19 +88,19 @@ class Client {
|
|
|
88
88
|
return this.engine.resume(track);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
createCameraVideoTrack(options?: CreateCameraVideoTrackOptions): Promise<Track
|
|
91
|
+
createCameraVideoTrack(options?: CreateCameraVideoTrackOptions): Promise<Track> {
|
|
92
92
|
return this.engine.createCameraVideoTrack(options);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
createMicrophoneAudioTrack(options?: CreateMicrophoneAudioTrackOptions): Promise<Track
|
|
95
|
+
createMicrophoneAudioTrack(options?: CreateMicrophoneAudioTrackOptions): Promise<Track> {
|
|
96
96
|
return this.engine.createMicrophoneAudioTrack(options);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
createScreenVideoTrack(options?: CreateScreenVideoTrackOptions): Promise<Track
|
|
99
|
+
createScreenVideoTrack(options?: CreateScreenVideoTrackOptions): Promise<Track> {
|
|
100
100
|
return this.engine.createScreenVideoTrack(options);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
createScreenAudioTrack(options?: CreateScreenAudioTrackOptions): Promise<Track
|
|
103
|
+
createScreenAudioTrack(options?: CreateScreenAudioTrackOptions): Promise<Track> {
|
|
104
104
|
return this.engine.createScreenAudioTrack(options);
|
|
105
105
|
}
|
|
106
106
|
|
package/src/types/common.ts
CHANGED
|
@@ -186,3 +186,19 @@ export type PayloadOfPublishedMedia = {
|
|
|
186
186
|
};
|
|
187
187
|
|
|
188
188
|
export type PayloadOfUnpublishedMedia = PayloadOfPublishedMedia;
|
|
189
|
+
|
|
190
|
+
export type ChangePreferredLayersPayload = PreferredLayersParams & {
|
|
191
|
+
consumerId: string,
|
|
192
|
+
spatialLayer: number,
|
|
193
|
+
temporalLayer: number,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export type CreateVideoTrackParams = {
|
|
197
|
+
videoTrackOptions: {
|
|
198
|
+
deviceId?: string,
|
|
199
|
+
width?: { max?: number, min?: number, ideal?: number };
|
|
200
|
+
height?: { max?: number, min?: number, ideal?: number };
|
|
201
|
+
frameRate?: { max?: number, min?: number, ideal?: number };
|
|
202
|
+
},
|
|
203
|
+
encoderConfig: VideoEncoderConfig,
|
|
204
|
+
};
|