@livedigital/client 2.26.0 → 2.27.0
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/engine/index.d.ts +1 -0
- package/dist/engine/media/tracks/BaseTrack.d.ts +3 -0
- package/dist/engine/media/tracks/MediaStreamTrackManager.d.ts +14 -0
- package/dist/index.es.js +1 -1
- package/dist/index.js +1 -1
- package/dist/types/common.d.ts +4 -0
- package/package.json +2 -2
- package/src/engine/index.ts +20 -17
- package/src/engine/media/index.ts +16 -9
- package/src/engine/media/tracks/BaseTrack.ts +22 -6
- package/src/engine/media/tracks/MediaStreamTrackManager.ts +46 -0
- package/src/types/common.ts +5 -0
package/dist/types/common.d.ts
CHANGED
|
@@ -304,6 +304,10 @@ export declare type UpdatePeerAppDataPayload = {
|
|
|
304
304
|
peerId: string;
|
|
305
305
|
appData: Record<string, unknown>;
|
|
306
306
|
};
|
|
307
|
+
export declare type CreateTracksPayload = {
|
|
308
|
+
mediaStreamTracks: MediaStreamTrack[];
|
|
309
|
+
constraints: MediaStreamConstraints;
|
|
310
|
+
};
|
|
307
311
|
export declare type TrackPublishParams = {
|
|
308
312
|
keyFrameRequestDelay?: number;
|
|
309
313
|
};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@livedigital/client",
|
|
3
3
|
"author": "vlprojects",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.27.0",
|
|
6
6
|
"private": false,
|
|
7
7
|
"bugs": {
|
|
8
8
|
"url": "https://github.com/vlprojects/livedigital-sdk/issues"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"qs": "^6.9.6",
|
|
49
49
|
"serialize-error": "^7.0.1",
|
|
50
50
|
"socket.io-client": "^4.3.0",
|
|
51
|
-
"webrtc-issue-detector": "^1.3.
|
|
51
|
+
"webrtc-issue-detector": "^1.3.1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@rollup/plugin-commonjs": "^19.0.0",
|
package/src/engine/index.ts
CHANGED
|
@@ -457,20 +457,7 @@ class Engine {
|
|
|
457
457
|
|
|
458
458
|
private watchClientEvents(): void {
|
|
459
459
|
this.clientEventEmitter.on(INTERNAL_CLIENT_EVENTS.trackProduced, (track: Track) => {
|
|
460
|
-
|
|
461
|
-
if (!myPeer) {
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const peerTrack = new PeerTrack({
|
|
466
|
-
mediaStreamTrack: track.mediaStreamTrack,
|
|
467
|
-
label: track.getLabel(),
|
|
468
|
-
engine: this,
|
|
469
|
-
isPaused: track.isPaused,
|
|
470
|
-
peerEventEmitter: myPeer.observer,
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
myPeer.tracks.set(peerTrack.label, peerTrack);
|
|
460
|
+
this.createSelfPeerTrack(track);
|
|
474
461
|
});
|
|
475
462
|
|
|
476
463
|
this.clientEventEmitter.on(INTERNAL_CLIENT_EVENTS.trackUnproduced, (track: Track) => {
|
|
@@ -481,14 +468,30 @@ class Engine {
|
|
|
481
468
|
|
|
482
469
|
this.clientEventEmitter.on(INTERNAL_CLIENT_EVENTS.trackPaused, (track: Track) => {
|
|
483
470
|
const peerTrack = this.myPeer?.tracks.get(track.getLabel());
|
|
484
|
-
peerTrack?.
|
|
471
|
+
peerTrack?.close();
|
|
485
472
|
});
|
|
486
473
|
|
|
487
474
|
this.clientEventEmitter.on(INTERNAL_CLIENT_EVENTS.trackResumed, (track: Track) => {
|
|
488
|
-
|
|
489
|
-
peerTrack?.resume();
|
|
475
|
+
this.createSelfPeerTrack(track);
|
|
490
476
|
});
|
|
491
477
|
}
|
|
478
|
+
|
|
479
|
+
private createSelfPeerTrack(track: Track): void {
|
|
480
|
+
const myPeer = this.peersRepository.get(<string> this.mySocketId);
|
|
481
|
+
if (!myPeer) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const peerTrack = new PeerTrack({
|
|
486
|
+
mediaStreamTrack: track.mediaStreamTrack,
|
|
487
|
+
label: track.getLabel(),
|
|
488
|
+
engine: this,
|
|
489
|
+
isPaused: track.isPaused,
|
|
490
|
+
peerEventEmitter: myPeer.observer,
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
myPeer.tracks.set(peerTrack.label, peerTrack);
|
|
494
|
+
}
|
|
492
495
|
}
|
|
493
496
|
|
|
494
497
|
export default Engine;
|
|
@@ -3,7 +3,11 @@ import { RtpCapabilities, RtpCodecCapability } from 'mediasoup-client/lib/RtpPar
|
|
|
3
3
|
import VideoTrack from './tracks/VideoTrack';
|
|
4
4
|
import AudioTrack from './tracks/AudioTrack';
|
|
5
5
|
import {
|
|
6
|
-
CreateScreenVideoTrackOptions,
|
|
6
|
+
CreateScreenVideoTrackOptions,
|
|
7
|
+
CreateTracksPayload,
|
|
8
|
+
CreateVideoTrackParams,
|
|
9
|
+
LogLevel,
|
|
10
|
+
Track,
|
|
7
11
|
} from '../../types/common';
|
|
8
12
|
import Logger from '../Logger';
|
|
9
13
|
import { VIDEO_CONSTRAINS } from '../../constants/videoConstrains';
|
|
@@ -11,6 +15,7 @@ import { SCREEN_SHARING_SIMULCAST_ENCODINGS, WEBCAM_SIMULCAST_ENCODINGS } from '
|
|
|
11
15
|
import { CreateMediaParams } from '../../types/engine';
|
|
12
16
|
import Engine from '../index';
|
|
13
17
|
import EnhancedEventEmitter from '../../EnhancedEventEmitter';
|
|
18
|
+
import MediaStreamTrackManager from './tracks/MediaStreamTrackManager';
|
|
14
19
|
|
|
15
20
|
class Media {
|
|
16
21
|
public isDeviceLoaded = false;
|
|
@@ -27,6 +32,8 @@ class Media {
|
|
|
27
32
|
|
|
28
33
|
readonly #clientEventEmitter: EnhancedEventEmitter;
|
|
29
34
|
|
|
35
|
+
readonly #mediaStreamTrackManager: MediaStreamTrackManager;
|
|
36
|
+
|
|
30
37
|
constructor(params: CreateMediaParams) {
|
|
31
38
|
this.#logLevel = params.logLevel;
|
|
32
39
|
this.#logger = new Logger({
|
|
@@ -35,6 +42,7 @@ class Media {
|
|
|
35
42
|
});
|
|
36
43
|
this.#engine = params.engine;
|
|
37
44
|
this.#clientEventEmitter = params.clientEventEmitter;
|
|
45
|
+
this.#mediaStreamTrackManager = new MediaStreamTrackManager(params.logLevel);
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
get mediasoupDevice(): Device {
|
|
@@ -62,20 +70,20 @@ class Media {
|
|
|
62
70
|
return codecs.find((c) => c.mimeType.toLowerCase() === `${track.kind}/${track.getPreferredCodec()}`);
|
|
63
71
|
}
|
|
64
72
|
|
|
65
|
-
private createTracks(
|
|
66
|
-
const mediaStreamTracks = stream.getTracks();
|
|
73
|
+
private createTracks({ constraints, mediaStreamTracks }: CreateTracksPayload): Track[] {
|
|
67
74
|
return mediaStreamTracks.map((mediaStreamTrack) => {
|
|
68
75
|
const params = {
|
|
69
76
|
mediaStreamTrack,
|
|
70
77
|
logLevel: this.#logLevel,
|
|
71
78
|
engine: this.#engine,
|
|
72
79
|
clientEventEmitter: this.#clientEventEmitter,
|
|
80
|
+
constraints,
|
|
81
|
+
mediaStreamTrackManager: this.#mediaStreamTrackManager,
|
|
73
82
|
};
|
|
74
83
|
|
|
75
84
|
const track = mediaStreamTrack.kind === 'audio' ? new AudioTrack(params) : new VideoTrack(params);
|
|
76
85
|
this.tracks.set(track.id, track);
|
|
77
86
|
this.#logger.debug('createTrack() track created', {
|
|
78
|
-
streamId: stream.id,
|
|
79
87
|
trackId: track.id,
|
|
80
88
|
kind: track.kind,
|
|
81
89
|
});
|
|
@@ -85,14 +93,13 @@ class Media {
|
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
async createUserMediaTracks(constraints: MediaStreamConstraints): Promise<Track[]> {
|
|
88
|
-
const
|
|
89
|
-
this
|
|
90
|
-
return this.createTracks(stream);
|
|
96
|
+
const mediaStreamTracks = await this.#mediaStreamTrackManager.createUserMediaTracks(constraints);
|
|
97
|
+
return this.createTracks({ constraints, mediaStreamTracks });
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
async createDisplayMediaTracks(constraints: MediaStreamConstraints): Promise<Track[]> {
|
|
94
|
-
const
|
|
95
|
-
return this.createTracks(
|
|
101
|
+
const mediaStreamTracks = await this.#mediaStreamTrackManager.createDisplayMediaTracks(constraints);
|
|
102
|
+
return this.createTracks({ constraints, mediaStreamTracks });
|
|
96
103
|
}
|
|
97
104
|
|
|
98
105
|
deleteTrack(track: Track) {
|
|
@@ -5,27 +5,30 @@ import {
|
|
|
5
5
|
EncoderConfig,
|
|
6
6
|
LogLevel,
|
|
7
7
|
SocketResponse,
|
|
8
|
-
TrackLabel,
|
|
8
|
+
TrackLabel,
|
|
9
|
+
TrackOutboundStats,
|
|
9
10
|
TrackProduceParams,
|
|
10
11
|
} from '../../../types/common';
|
|
11
12
|
import Logger from '../../Logger';
|
|
12
13
|
import Engine from '../../index';
|
|
13
14
|
import PeerConsumer from '../../PeerConsumer';
|
|
14
15
|
import { PRODUCER_CHECK_STATE_TIMEOUT } from '../../../constants/common';
|
|
15
|
-
import
|
|
16
|
-
import { MEDIASOUP_EVENTS, INTERNAL_CLIENT_EVENTS, CLIENT_EVENTS } from '../../../constants/events';
|
|
16
|
+
import { CLIENT_EVENTS, INTERNAL_CLIENT_EVENTS, MEDIASOUP_EVENTS } from '../../../constants/events';
|
|
17
17
|
import EnhancedEventEmitter from '../../../EnhancedEventEmitter';
|
|
18
18
|
import filterStatsCodecs from '../../../helpers/filterStatsCodecs';
|
|
19
|
+
import MediaStreamTrackManager from './MediaStreamTrackManager';
|
|
19
20
|
|
|
20
21
|
export type BaseTrackConstructorParams = {
|
|
21
22
|
mediaStreamTrack: MediaStreamTrack,
|
|
22
23
|
logLevel: LogLevel,
|
|
23
24
|
engine: Engine,
|
|
24
25
|
clientEventEmitter: EnhancedEventEmitter,
|
|
26
|
+
constraints: MediaStreamConstraints;
|
|
27
|
+
mediaStreamTrackManager: MediaStreamTrackManager;
|
|
25
28
|
};
|
|
26
29
|
|
|
27
30
|
class BaseTrack {
|
|
28
|
-
|
|
31
|
+
#mediaStreamTrack: MediaStreamTrack;
|
|
29
32
|
|
|
30
33
|
protected encoderConfig: EncoderConfig = {};
|
|
31
34
|
|
|
@@ -39,7 +42,7 @@ class BaseTrack {
|
|
|
39
42
|
|
|
40
43
|
#selfConsumer?: PeerConsumer;
|
|
41
44
|
|
|
42
|
-
#checkStateTimeout?: Timeout;
|
|
45
|
+
#checkStateTimeout?: NodeJS.Timeout;
|
|
43
46
|
|
|
44
47
|
#producerRestarted = false;
|
|
45
48
|
|
|
@@ -47,13 +50,19 @@ class BaseTrack {
|
|
|
47
50
|
|
|
48
51
|
#closed = false;
|
|
49
52
|
|
|
53
|
+
readonly #constraints: MediaStreamConstraints;
|
|
54
|
+
|
|
55
|
+
readonly #mediaStreamTrackManager: MediaStreamTrackManager;
|
|
56
|
+
|
|
50
57
|
constructor(params: BaseTrackConstructorParams) {
|
|
51
58
|
const {
|
|
52
|
-
mediaStreamTrack, logLevel, engine, clientEventEmitter,
|
|
59
|
+
mediaStreamTrack, logLevel, engine, clientEventEmitter, constraints, mediaStreamTrackManager,
|
|
53
60
|
} = params;
|
|
54
61
|
this.#mediaStreamTrack = mediaStreamTrack;
|
|
55
62
|
this.#engine = engine;
|
|
56
63
|
this.#clientEventEmitter = clientEventEmitter;
|
|
64
|
+
this.#constraints = constraints;
|
|
65
|
+
this.#mediaStreamTrackManager = mediaStreamTrackManager;
|
|
57
66
|
this.logger = new Logger({
|
|
58
67
|
namespace: 'Track',
|
|
59
68
|
logLevel,
|
|
@@ -366,6 +375,7 @@ class BaseTrack {
|
|
|
366
375
|
await this.cancelProducerCheckState();
|
|
367
376
|
await this.pauseRemoteProducer(this.producer.id);
|
|
368
377
|
this.producer.pause();
|
|
378
|
+
this.#mediaStreamTrack.stop();
|
|
369
379
|
this.clientEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackPaused, this);
|
|
370
380
|
this.logger.debug('pause()', { track: this });
|
|
371
381
|
} catch (error) {
|
|
@@ -381,6 +391,12 @@ class BaseTrack {
|
|
|
381
391
|
}
|
|
382
392
|
|
|
383
393
|
try {
|
|
394
|
+
const track = await this.#mediaStreamTrackManager.createMediaStreamTrack({
|
|
395
|
+
label: this.label,
|
|
396
|
+
constraints: this.#constraints,
|
|
397
|
+
});
|
|
398
|
+
this.#mediaStreamTrack = track;
|
|
399
|
+
await this.producer.replaceTrack({ track });
|
|
384
400
|
await this.resumeRemoteProducer(this.producer.id);
|
|
385
401
|
this.producer.resume();
|
|
386
402
|
this.clientEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackResumed, this);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { LogLevel, TrackLabel } from '../../../types/common';
|
|
2
|
+
import Logger from '../../Logger';
|
|
3
|
+
|
|
4
|
+
export type GetMediaStreamTrackParams = {
|
|
5
|
+
label: TrackLabel;
|
|
6
|
+
constraints: MediaStreamConstraints;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
class MediaStreamTrackManager {
|
|
10
|
+
readonly #logger: Logger;
|
|
11
|
+
|
|
12
|
+
constructor(logLevel: LogLevel) {
|
|
13
|
+
this.#logger = new Logger({
|
|
14
|
+
namespace: 'MediaStreamTrackManager',
|
|
15
|
+
logLevel,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async createMediaStreamTrack({ label, constraints }: GetMediaStreamTrackParams): Promise<MediaStreamTrack> {
|
|
20
|
+
if (MediaStreamTrackManager.isDisplayMedia(label)) {
|
|
21
|
+
const [track] = await this.createDisplayMediaTracks(constraints);
|
|
22
|
+
return track;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const [track] = await this.createUserMediaTracks(constraints);
|
|
26
|
+
return track;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private static isDisplayMedia(label: TrackLabel): boolean {
|
|
30
|
+
return [TrackLabel.ScreenVideo, TrackLabel.ScreenAudio].includes(label);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async createUserMediaTracks(constraints: MediaStreamConstraints): Promise<MediaStreamTrack[]> {
|
|
34
|
+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
35
|
+
this.#logger.debug('createUserMediaTracks() stream created', { streamId: stream.id });
|
|
36
|
+
return stream.getTracks();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async createDisplayMediaTracks(constraints: MediaStreamConstraints): Promise<MediaStreamTrack[]> {
|
|
40
|
+
const stream = await navigator.mediaDevices.getDisplayMedia(constraints);
|
|
41
|
+
this.#logger.debug('getDisplayMediaTracks() stream created', { streamId: stream.id });
|
|
42
|
+
return stream.getTracks();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default MediaStreamTrackManager;
|
package/src/types/common.ts
CHANGED
|
@@ -350,6 +350,11 @@ export type UpdatePeerAppDataPayload = {
|
|
|
350
350
|
appData: Record<string, unknown>,
|
|
351
351
|
};
|
|
352
352
|
|
|
353
|
+
export type CreateTracksPayload = {
|
|
354
|
+
mediaStreamTracks: MediaStreamTrack[],
|
|
355
|
+
constraints: MediaStreamConstraints,
|
|
356
|
+
};
|
|
357
|
+
|
|
353
358
|
export type TrackPublishParams = {
|
|
354
359
|
keyFrameRequestDelay?: number;
|
|
355
360
|
};
|