@livedigital/client 1.14.1 → 2.0.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/Peer.d.ts +4 -2
- package/dist/engine/index.d.ts +6 -3
- package/dist/engine/media/index.d.ts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.es.js +1 -1
- package/dist/index.js +1 -1
- package/dist/types/common.d.ts +8 -1
- package/package.json +1 -1
- package/src/engine/Peer.ts +6 -0
- package/src/engine/index.ts +53 -42
- package/src/engine/media/index.ts +20 -15
- package/src/index.ts +8 -8
- package/src/types/common.ts +10 -1
package/dist/types/common.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare type ProducerData = {
|
|
|
21
21
|
peerId: string;
|
|
22
22
|
label: TrackLabel;
|
|
23
23
|
};
|
|
24
|
+
export declare type Role = 'audience' | 'host';
|
|
24
25
|
export declare type PeerResponse = {
|
|
25
26
|
id: string;
|
|
26
27
|
channelIds: string[];
|
|
@@ -28,6 +29,7 @@ export declare type PeerResponse = {
|
|
|
28
29
|
producers: ProducerData[];
|
|
29
30
|
uid?: string;
|
|
30
31
|
appData: Record<string, unknown>;
|
|
32
|
+
role: Role;
|
|
31
33
|
};
|
|
32
34
|
export declare type AvailableMediaDevices = {
|
|
33
35
|
video: MediaDeviceInfo[];
|
|
@@ -39,6 +41,7 @@ export declare type JoinChannelParams = {
|
|
|
39
41
|
sdkSecret: string;
|
|
40
42
|
uid?: string;
|
|
41
43
|
appData?: Record<string, unknown>;
|
|
44
|
+
role: Role;
|
|
42
45
|
};
|
|
43
46
|
export declare type ChannelEvent = {
|
|
44
47
|
eventName: string;
|
|
@@ -125,9 +128,13 @@ export declare type CreateScreenVideoTrackOptions = CreateVideoTrackOptions & {
|
|
|
125
128
|
export declare type CreateMicrophoneAudioTrackOptions = CreateTrackOptions & {
|
|
126
129
|
encoderConfig?: AudioEncoderConfig;
|
|
127
130
|
};
|
|
128
|
-
export declare type CreateScreenAudioTrackOptions =
|
|
131
|
+
export declare type CreateScreenAudioTrackOptions = CreateMicrophoneAudioTrackOptions & {
|
|
129
132
|
encoderConfig?: AudioEncoderConfig;
|
|
130
133
|
};
|
|
134
|
+
export declare type CreateScreenMediaOptions = {
|
|
135
|
+
video: CreateScreenVideoTrackOptions;
|
|
136
|
+
audio: CreateScreenAudioTrackOptions;
|
|
137
|
+
};
|
|
131
138
|
export declare type Track = VideoTrack | AudioTrack;
|
|
132
139
|
export declare enum TrackLabel {
|
|
133
140
|
Camera = "camera",
|
package/package.json
CHANGED
package/src/engine/Peer.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
PayloadOfPublishedMedia,
|
|
13
13
|
PayloadOfUnpublishedMedia,
|
|
14
14
|
ChangePreferredLayersPayload,
|
|
15
|
+
Role,
|
|
15
16
|
} from '../types/common';
|
|
16
17
|
import Consumer from './media/Consumer';
|
|
17
18
|
import VideoConsumer from './media/VideoConsumer';
|
|
@@ -33,6 +34,7 @@ interface PeerConstructor {
|
|
|
33
34
|
loginDate: Date;
|
|
34
35
|
uid?: string;
|
|
35
36
|
appData?: Record<string, unknown>,
|
|
37
|
+
role: Role,
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export enum ScoreThreshold {
|
|
@@ -54,6 +56,8 @@ class Peer {
|
|
|
54
56
|
|
|
55
57
|
public appData: Record<string, unknown>;
|
|
56
58
|
|
|
59
|
+
public role: Role;
|
|
60
|
+
|
|
57
61
|
private producers: Map<string, PeerProducer> = new Map();
|
|
58
62
|
|
|
59
63
|
private consumers: Map<string, Consumer | VideoConsumer> = new Map();
|
|
@@ -77,6 +81,7 @@ class Peer {
|
|
|
77
81
|
engine,
|
|
78
82
|
appData,
|
|
79
83
|
uid,
|
|
84
|
+
role,
|
|
80
85
|
}: PeerConstructor) {
|
|
81
86
|
this.id = id;
|
|
82
87
|
this.channelIds = channelIds;
|
|
@@ -84,6 +89,7 @@ class Peer {
|
|
|
84
89
|
this.loginDate = loginDate;
|
|
85
90
|
this.appData = appData || {};
|
|
86
91
|
this.uid = uid;
|
|
92
|
+
this.role = role;
|
|
87
93
|
this.engine = engine;
|
|
88
94
|
this.logger = new Logger('Peer');
|
|
89
95
|
producers.forEach(this.handleNewProducer.bind(this));
|
package/src/engine/index.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { RtpCapabilities } from 'mediasoup-client/lib/RtpParameters';
|
|
|
2
2
|
import {
|
|
3
3
|
CreateCameraVideoTrackOptions,
|
|
4
4
|
CreateMicrophoneAudioTrackOptions,
|
|
5
|
-
|
|
6
|
-
CreateScreenVideoTrackOptions,
|
|
5
|
+
CreateScreenMediaOptions,
|
|
7
6
|
EndTrackPayload,
|
|
8
7
|
JoinChannelParams,
|
|
9
8
|
PeerResponse,
|
|
9
|
+
Role,
|
|
10
10
|
SocketResponse,
|
|
11
11
|
StartTrackPayload,
|
|
12
12
|
Track,
|
|
@@ -126,6 +126,14 @@ class Engine {
|
|
|
126
126
|
return Array.from(this.peersRepository.values());
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
+
public get hostPeers(): Peer[] {
|
|
130
|
+
return this.peers.filter((peer) => peer.role === 'host');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
public get audiencePeers(): Peer[] {
|
|
134
|
+
return this.peers.filter((peer) => peer.role === 'audience');
|
|
135
|
+
}
|
|
136
|
+
|
|
129
137
|
public get mySocketId(): string | undefined {
|
|
130
138
|
return this.network.socket.id;
|
|
131
139
|
}
|
|
@@ -146,6 +154,15 @@ class Engine {
|
|
|
146
154
|
}
|
|
147
155
|
}
|
|
148
156
|
|
|
157
|
+
public async loadPeers(role?: Role): Promise<void> {
|
|
158
|
+
const { peers } = await this.network.socket
|
|
159
|
+
.request(CHANNEL_EVENTS.channelGetPeers, { role }) as { peers: PeerResponse[] };
|
|
160
|
+
|
|
161
|
+
peers
|
|
162
|
+
.filter((peer) => !this.peersRepository.has(peer.id))
|
|
163
|
+
.forEach((peer) => this.setPeer(peer));
|
|
164
|
+
}
|
|
165
|
+
|
|
149
166
|
public setPeer(peerData: PeerResponse): Peer {
|
|
150
167
|
const peer = new Peer({
|
|
151
168
|
...peerData,
|
|
@@ -197,7 +214,7 @@ class Engine {
|
|
|
197
214
|
async createCameraVideoTrack(options?: CreateCameraVideoTrackOptions): Promise<Track> {
|
|
198
215
|
const trackParams = Media.getCameraVideoTrackParams(options);
|
|
199
216
|
try {
|
|
200
|
-
const track = await this.media.
|
|
217
|
+
const [track] = await this.media.createUserMediaTracks({
|
|
201
218
|
audio: false,
|
|
202
219
|
video: trackParams.videoTrackOptions,
|
|
203
220
|
});
|
|
@@ -215,7 +232,7 @@ class Engine {
|
|
|
215
232
|
|
|
216
233
|
async createMicrophoneAudioTrack(options?: CreateMicrophoneAudioTrackOptions): Promise<Track> {
|
|
217
234
|
try {
|
|
218
|
-
const track = await this.media.
|
|
235
|
+
const [track] = await this.media.createUserMediaTracks({
|
|
219
236
|
video: false,
|
|
220
237
|
audio: {
|
|
221
238
|
deviceId: options?.deviceId,
|
|
@@ -235,54 +252,47 @@ class Engine {
|
|
|
235
252
|
}
|
|
236
253
|
}
|
|
237
254
|
|
|
238
|
-
async
|
|
239
|
-
const
|
|
255
|
+
async createScreenMediaTracks(options?: CreateScreenMediaOptions): Promise<Track[]> {
|
|
256
|
+
const videoTrackParams = Media.getScreenVideoTrackParams(options?.video);
|
|
240
257
|
try {
|
|
241
|
-
const
|
|
242
|
-
audio:
|
|
243
|
-
video:
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
track.mediaStreamTrack.addEventListener('ended', () => {
|
|
247
|
-
this.unpublish(track);
|
|
258
|
+
const tracks = await this.media.createDisplayMediaTracks({
|
|
259
|
+
audio: options?.audio,
|
|
260
|
+
video: videoTrackParams.videoTrackOptions,
|
|
248
261
|
});
|
|
249
262
|
|
|
250
|
-
|
|
251
|
-
|
|
263
|
+
tracks.forEach((track) => {
|
|
264
|
+
track.mediaStreamTrack.addEventListener('ended', () => {
|
|
265
|
+
this.unpublish(track);
|
|
266
|
+
});
|
|
252
267
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
268
|
+
if (track.kind === 'video') {
|
|
269
|
+
track.setLabel(TrackLabel.ScreenVideo);
|
|
270
|
+
track.setEncoderConfig(videoTrackParams.encoderConfig);
|
|
271
|
+
this.logger.debug('createScreenMediaTrack()', { trackParams: videoTrackParams, track });
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
260
274
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
audio: true,
|
|
266
|
-
});
|
|
275
|
+
track.setLabel(TrackLabel.ScreenAudio);
|
|
276
|
+
if (options?.audio) {
|
|
277
|
+
track.setEncoderConfig(options.audio);
|
|
278
|
+
}
|
|
267
279
|
|
|
268
|
-
|
|
269
|
-
this.unpublish(track);
|
|
280
|
+
this.logger.debug('createScreenMediaTrack()', { trackParams: options?.audio, track });
|
|
270
281
|
});
|
|
271
282
|
|
|
272
|
-
|
|
273
|
-
if (options?.encoderConfig) {
|
|
274
|
-
track.setEncoderConfig(options.encoderConfig);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
this.logger.debug('createScreenAudioTrack()', { options, track });
|
|
278
|
-
return track;
|
|
283
|
+
return tracks;
|
|
279
284
|
} catch (error) {
|
|
280
|
-
this.logger.error('
|
|
281
|
-
throw new Error(`Can not create screen
|
|
285
|
+
this.logger.error('createScreenMediaTrack()', { error, trackParams: videoTrackParams });
|
|
286
|
+
throw new Error(`Can not create screen media tracks: ${error.message}`);
|
|
282
287
|
}
|
|
283
288
|
}
|
|
284
289
|
|
|
285
290
|
public async publish(tracks: Track | Track[]): Promise<void> {
|
|
291
|
+
if (!this.cahPublish) {
|
|
292
|
+
this.logger.error('publish()', { message: 'Not enough access to publish' });
|
|
293
|
+
throw new Error('Not enough access to publish');
|
|
294
|
+
}
|
|
295
|
+
|
|
286
296
|
const tracksToPublish = Array.isArray(tracks) ? tracks : [tracks];
|
|
287
297
|
const actions = tracksToPublish.map(async (track) => {
|
|
288
298
|
const encodings = 'getEncodings' in track
|
|
@@ -409,9 +419,6 @@ class Engine {
|
|
|
409
419
|
try {
|
|
410
420
|
await this.network.socket.request(CHANNEL_EVENTS.channelJoin, params);
|
|
411
421
|
await this.initialize();
|
|
412
|
-
const { peers } = await this.network.socket
|
|
413
|
-
.request(CHANNEL_EVENTS.channelGetPeers) as { peers: PeerResponse[] };
|
|
414
|
-
peers.forEach((peer: PeerResponse) => this.setPeer(peer));
|
|
415
422
|
this.channelEventsHandler.subscribeToEvents();
|
|
416
423
|
this.mediaSoupEventsHandler.subscribeToEvents();
|
|
417
424
|
this.app = params.appId;
|
|
@@ -423,6 +430,10 @@ class Engine {
|
|
|
423
430
|
throw error;
|
|
424
431
|
}
|
|
425
432
|
}
|
|
433
|
+
|
|
434
|
+
get cahPublish(): boolean {
|
|
435
|
+
return this.peers.find((item) => item.isMe)?.role === 'host';
|
|
436
|
+
}
|
|
426
437
|
}
|
|
427
438
|
|
|
428
439
|
export default Engine;
|
|
@@ -46,28 +46,33 @@ class Media {
|
|
|
46
46
|
.find((c) => c.mimeType.toLowerCase() === `video/${track.getPreferredCodec()}`);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
private
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
private createTracks(stream: MediaStream): Track[] {
|
|
50
|
+
const mediaStreamTracks = stream.getTracks();
|
|
51
|
+
return mediaStreamTracks.map((mediaStreamTrack) => {
|
|
52
|
+
const track = mediaStreamTrack.kind === 'audio'
|
|
53
|
+
? new AudioTrack(mediaStreamTrack)
|
|
54
|
+
: new VideoTrack(mediaStreamTrack);
|
|
55
|
+
|
|
56
|
+
this.tracks.set(track.id, track);
|
|
57
|
+
this.#logger.debug('createTrack() track created', {
|
|
58
|
+
streamId: stream.id,
|
|
59
|
+
trackId: track.id,
|
|
60
|
+
kind: track.kind,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
return track;
|
|
64
|
+
});
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
async
|
|
67
|
+
async createUserMediaTracks(constraints: MediaStreamConstraints): Promise<Track[]> {
|
|
63
68
|
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
64
69
|
this.#logger.debug('createUserMediaTrack() stream created', { streamId: stream.id });
|
|
65
|
-
return this.
|
|
70
|
+
return this.createTracks(stream);
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
async
|
|
73
|
+
async createDisplayMediaTracks(constraints: MediaStreamConstraints): Promise<Track[]> {
|
|
69
74
|
const stream = await navigator.mediaDevices.getDisplayMedia(constraints);
|
|
70
|
-
return this.
|
|
75
|
+
return this.createTracks(stream);
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
deleteTrack(track: Track) {
|
package/src/index.ts
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
AvailableMediaDevices,
|
|
3
3
|
CreateCameraVideoTrackOptions,
|
|
4
4
|
CreateMicrophoneAudioTrackOptions,
|
|
5
|
-
|
|
6
|
-
CreateScreenVideoTrackOptions,
|
|
5
|
+
CreateScreenMediaOptions,
|
|
7
6
|
JoinChannelParams,
|
|
7
|
+
Role,
|
|
8
8
|
Track,
|
|
9
9
|
} from './types/common';
|
|
10
10
|
import EnhancedEventEmitter from './EnhancedEventEmitter';
|
|
@@ -96,17 +96,17 @@ class Client {
|
|
|
96
96
|
return this.engine.createMicrophoneAudioTrack(options);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
return this.engine.
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
createScreenAudioTrack(options?: CreateScreenAudioTrackOptions): Promise<Track> {
|
|
104
|
-
return this.engine.createScreenAudioTrack(options);
|
|
99
|
+
createScreenMediaTracks(options?: CreateScreenMediaOptions): Promise<Track[]> {
|
|
100
|
+
return this.engine.createScreenMediaTracks(options);
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
deleteTrack(track: Track): void {
|
|
108
104
|
return this.engine.deleteTrack(track);
|
|
109
105
|
}
|
|
106
|
+
|
|
107
|
+
loadPeers(role?: Role): Promise<void> {
|
|
108
|
+
return this.engine.loadPeers(role);
|
|
109
|
+
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
export default Client;
|
package/src/types/common.ts
CHANGED
|
@@ -30,6 +30,8 @@ export type ProducerData = {
|
|
|
30
30
|
label: TrackLabel,
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
export type Role = 'audience' | 'host';
|
|
34
|
+
|
|
33
35
|
export type PeerResponse = {
|
|
34
36
|
id: string,
|
|
35
37
|
channelIds: string[],
|
|
@@ -37,6 +39,7 @@ export type PeerResponse = {
|
|
|
37
39
|
producers: ProducerData[],
|
|
38
40
|
uid?: string,
|
|
39
41
|
appData: Record<string, unknown>,
|
|
42
|
+
role: Role,
|
|
40
43
|
};
|
|
41
44
|
|
|
42
45
|
export type AvailableMediaDevices = {
|
|
@@ -50,6 +53,7 @@ export type JoinChannelParams = {
|
|
|
50
53
|
sdkSecret: string,
|
|
51
54
|
uid?: string,
|
|
52
55
|
appData?: Record<string, unknown>,
|
|
56
|
+
role: Role,
|
|
53
57
|
};
|
|
54
58
|
|
|
55
59
|
export type ChannelEvent = {
|
|
@@ -152,10 +156,15 @@ export type CreateMicrophoneAudioTrackOptions = CreateTrackOptions & {
|
|
|
152
156
|
encoderConfig?: AudioEncoderConfig,
|
|
153
157
|
};
|
|
154
158
|
|
|
155
|
-
export type CreateScreenAudioTrackOptions =
|
|
159
|
+
export type CreateScreenAudioTrackOptions = CreateMicrophoneAudioTrackOptions & {
|
|
156
160
|
encoderConfig?: AudioEncoderConfig,
|
|
157
161
|
};
|
|
158
162
|
|
|
163
|
+
export type CreateScreenMediaOptions = {
|
|
164
|
+
video: CreateScreenVideoTrackOptions,
|
|
165
|
+
audio: CreateScreenAudioTrackOptions,
|
|
166
|
+
};
|
|
167
|
+
|
|
159
168
|
export type Track = VideoTrack | AudioTrack;
|
|
160
169
|
|
|
161
170
|
export enum TrackLabel {
|