@livedigital/client 2.0.1 → 2.2.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.
@@ -15,11 +15,24 @@ export declare type ProduceParams = {
15
15
  rtpParameters: RtpParameters;
16
16
  appData: Record<string, unknown>;
17
17
  };
18
+ export declare type TrackTransformParams = {
19
+ width?: number;
20
+ height?: number;
21
+ };
18
22
  export declare type ProducerData = {
19
23
  id: string;
20
24
  kind: MediaKind;
21
25
  peerId: string;
22
26
  label: TrackLabel;
27
+ encodings: RtpEncodingParameters[];
28
+ trackTransformParams: TrackTransformParams;
29
+ maxSpatialLayer: number;
30
+ };
31
+ export declare type ConsumerData = {
32
+ producerData: ProducerData;
33
+ peerId: string;
34
+ appId: string;
35
+ channelId: string;
23
36
  };
24
37
  export declare type Role = 'audience' | 'host';
25
38
  export declare type PeerResponse = {
@@ -185,4 +198,17 @@ export declare type CreateVideoTrackParams = {
185
198
  };
186
199
  };
187
200
  encoderConfig: VideoEncoderConfig;
201
+ transformParams: TransformParams;
202
+ };
203
+ export declare type SpatialLayerParams = RtpEncodingParameters & TransformParams;
204
+ export declare type ProducerRequestMaxSpatialLayer = {
205
+ producerId: string;
206
+ spatialLayer: number;
207
+ };
208
+ export declare type ProducerSetMaxSpatialLayer = ProducerRequestMaxSpatialLayer & {
209
+ peerId: string;
210
+ };
211
+ export declare type TransformParams = {
212
+ width?: number;
213
+ height?: number;
188
214
  };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@livedigital/client",
3
3
  "author": "vlprojects",
4
4
  "license": "MIT",
5
- "version": "2.0.1",
5
+ "version": "2.2.0",
6
6
  "private": false,
7
7
  "bugs": {
8
8
  "url": "https://github.com/vlprojects/livedigital-sdk/issues"
@@ -43,7 +43,7 @@
43
43
  "dependencies": {
44
44
  "axios": "^0.21.4",
45
45
  "debug": "^4.3.1",
46
- "mediasoup-client": "^3.6.42",
46
+ "mediasoup-client": "^3.6.50",
47
47
  "qs": "^6.9.6",
48
48
  "serialize-error": "^7.0.1",
49
49
  "socket.io-client": "^4.3.0"
@@ -36,6 +36,8 @@ export const MEDIASOUP_EVENTS = {
36
36
  pauseProducer: 'producer.pause',
37
37
  resumeProducer: 'producer.resume',
38
38
  producerScoreChanged: 'producer.scoreChanged',
39
+ producerSetMaxSpatialLayer: 'producer.setMaxSpatialLayer',
40
+ producerRequestMaxSpatialLayer: 'producer.requestMaxSpatialLayer',
39
41
  createConsumer: 'consumer.create',
40
42
  closeConsumer: 'consumer.close',
41
43
  pauseConsumer: 'consumer.pause',
@@ -1,10 +1,24 @@
1
1
  export const WEBCAM_SIMULCAST_ENCODINGS = [
2
- { scaleResolutionDownBy: 5, maxBitrate: 200000 },
3
- { scaleResolutionDownBy: 4, maxBitrate: 400000 },
4
- { scaleResolutionDownBy: 2, maxBitrate: 1500000 },
2
+ {
3
+ scaleResolutionDownBy: 4, // 320x180 0.15mbps 12fps by default
4
+ maxBitrate: 150000,
5
+ maxFramerate: 12,
6
+ },
7
+ {
8
+ scaleResolutionDownBy: 2, // 640x360 0.35mbps 18fps by default
9
+ maxBitrate: 350000,
10
+ maxFramerate: 18,
11
+ },
12
+ {
13
+ scaleResolutionDownBy: 1, // 1280x720 0.9mbps 24fps by default
14
+ maxBitrate: 900000,
15
+ maxFramerate: 24,
16
+ },
5
17
  ];
6
18
 
7
19
  export const SCREEN_SHARING_SIMULCAST_ENCODINGS = [
8
- { dtx: true, maxBitrate: 1500000 },
9
- { dtx: true, maxBitrate: 6000000 },
20
+ {
21
+ maxBitrate: 1000000, // 1920x1080 1mbps 30fps by default
22
+ dtx: true,
23
+ },
10
24
  ];
@@ -1,34 +1,30 @@
1
1
  import { ConsumerOptions } from 'mediasoup-client/lib/Consumer';
2
2
  import {
3
3
  ConsumerScoreChangedPayload,
4
- PreferredLayersParams,
5
4
  ProducerData,
6
5
  ProducerScoreChangedPayload,
7
- SetConsumerPriorityParams,
8
- SocketResponse,
9
6
  ConnectionQuality,
10
- StartTrackPayload,
11
7
  EndTrackPayload,
12
8
  PayloadOfPublishedMedia,
13
9
  PayloadOfUnpublishedMedia,
14
10
  ChangePreferredLayersPayload,
15
11
  Role,
16
12
  } from '../types/common';
17
- import Consumer from './media/Consumer';
18
- import VideoConsumer from './media/VideoConsumer';
19
13
  import EnhancedEventEmitter from '../EnhancedEventEmitter';
20
14
  import Engine from './index';
21
15
  import { MEDIASOUP_EVENTS, PEER_EVENTS } from '../constants/events';
22
16
  import Logger from './Logger';
23
17
  import PeerProducer from './PeerProducer';
18
+ import PeerConsumer from './PeerConsumer';
19
+ import PeerTrack from './media/tracks/PeerTrack';
24
20
 
25
21
  interface PeerConstructor {
26
22
  id: string;
27
23
  channelIds: string[];
28
24
  appId: string;
29
25
  producers: ProducerData[],
30
- videoConsumer?: VideoConsumer;
31
- audioConsumer?: Consumer;
26
+ videoConsumer?: PeerConsumer;
27
+ audioConsumer?: PeerConsumer;
32
28
  engine: Engine;
33
29
  soundLevel?: number;
34
30
  loginDate: Date;
@@ -60,7 +56,7 @@ class Peer {
60
56
 
61
57
  private producers: Map<string, PeerProducer> = new Map();
62
58
 
63
- private consumers: Map<string, Consumer | VideoConsumer> = new Map();
59
+ public readonly tracks: Map<string, PeerTrack> = new Map();
64
60
 
65
61
  private readonly engine: Engine;
66
62
 
@@ -128,105 +124,6 @@ class Peer {
128
124
  await this.createConsumer(producer);
129
125
  }
130
126
 
131
- public async setMinResolution(consumerId: string): Promise<void> {
132
- const consumer = this.consumers.get(consumerId);
133
- if (!(consumer instanceof VideoConsumer) || consumer.spatialLayers === 0) {
134
- return;
135
- }
136
-
137
- await this.changeConsumerPreferredLayers(consumer, { spatialLayer: 0 });
138
- }
139
-
140
- public async setMediumResolution(consumerId: string): Promise<void> {
141
- const consumer = this.consumers.get(consumerId);
142
- if (!(consumer instanceof VideoConsumer) || consumer.spatialLayers === 0) {
143
- return;
144
- }
145
-
146
- const mediumLayer = consumer.spatialLayers > 2
147
- ? consumer.spatialLayers - 2
148
- : consumer.spatialLayers;
149
- await this.changeConsumerPreferredLayers(consumer, { spatialLayer: mediumLayer });
150
- }
151
-
152
- public async setMaxResolution(consumerId: string): Promise<void> {
153
- const consumer = this.consumers.get(consumerId);
154
- if (!(consumer instanceof VideoConsumer) || consumer.spatialLayers === 0) {
155
- return;
156
- }
157
-
158
- await this.changeConsumerPreferredLayers(consumer, {
159
- spatialLayer: consumer.spatialLayers - 1,
160
- });
161
- }
162
-
163
- public async pause(consumerId: string): Promise<void> {
164
- const consumer = this.consumers.get(consumerId);
165
- if (!consumer) {
166
- this.logger.warn('pause()', { message: 'This peer has no consumer to pause', peer: this, consumerId });
167
- return;
168
- }
169
-
170
- if (consumer.paused) {
171
- this.logger.warn('pause()', { message: 'Already paused', peer: this, consumerId });
172
- return;
173
- }
174
-
175
- try {
176
- await this.pauseRemoteConsumer(consumer.id);
177
- consumer.pause();
178
- this.logger.debug('pause()', { peer: this, consumerId });
179
- } catch (err) {
180
- this.logger.error('pause()', err);
181
- }
182
- }
183
-
184
- public async resume(consumerId: string): Promise<void> {
185
- const consumer = this.consumers.get(consumerId);
186
- if (!consumer) {
187
- this.logger.warn('resume()', { message: 'This peer has no consumer to resume', peer: this, consumerId });
188
- return;
189
- }
190
-
191
- if (!consumer.paused) {
192
- this.logger.warn('resume()', { message: 'Already playing', peer: this, consumerId });
193
- return;
194
- }
195
-
196
- try {
197
- await this.resumeRemoteConsumer(consumer.id);
198
- consumer.resume();
199
- this.logger.debug('resume()', { peer: this });
200
- } catch (err) {
201
- this.logger.error('resume()', err);
202
- }
203
- }
204
-
205
- public async setPriority(consumerId: string, priority: number): Promise<void> {
206
- const consumer = this.consumers.get(consumerId);
207
- if (!consumer) {
208
- this.logger.warn('setPriority()', {
209
- message: 'This peer has no consumer to change priority',
210
- peer: this,
211
- consumerId,
212
- });
213
-
214
- return;
215
- }
216
-
217
- await this.setConsumerPriority({ consumerId, priority });
218
- }
219
-
220
- private async setConsumerPriority(params: SetConsumerPriorityParams): Promise<void> {
221
- try {
222
- await this.engine.network.socket.request(MEDIASOUP_EVENTS.setConsumerPriority, params);
223
- this.logger.debug('setConsumerPriority()', { peer: this, params });
224
- } catch (err) {
225
- this.logger.error('setConsumerPriority()', { peer: this, params });
226
- throw new Error('Can`t change stream priority');
227
- }
228
- }
229
-
230
127
  private async createConsumer(producer: PeerProducer): Promise<void> {
231
128
  const transport = this.engine.network.receiveTransport;
232
129
  if (!transport) {
@@ -250,62 +147,21 @@ class Peer {
250
147
  const consumer = await transport.consume(remoteConsumer);
251
148
  await this.engine.network.socket.request(MEDIASOUP_EVENTS.resumeConsumer, { consumerId: consumer.id });
252
149
 
253
- if (producer.kind === 'audio') {
254
- this.consumers.set(consumer.id, new Consumer(consumer));
255
- }
256
-
257
- if (producer.kind === 'video') {
258
- this.consumers.set(consumer.id, new VideoConsumer(consumer));
259
- }
260
-
261
150
  this.logger.debug(`Subscribed for ${producer.kind}`, { peer: this });
262
- this.observer.safeEmit(PEER_EVENTS.trackStart, {
263
- producerId: producer.id,
264
- consumerId: consumer.id,
265
- track: consumer.track,
151
+ const track = new PeerTrack({
152
+ mediaStreamTrack: consumer.track,
266
153
  label: producer.label,
267
- } as StartTrackPayload);
154
+ consumer: new PeerConsumer(consumer),
155
+ engine: this.engine,
156
+ });
157
+ this.tracks.set(track.label, track);
158
+ this.observer.safeEmit(PEER_EVENTS.trackStart, track);
268
159
  } catch (error) {
269
160
  this.logger.error('createConsumer()', producer, error);
270
161
  throw new Error('Error subscribe media');
271
162
  }
272
163
  }
273
164
 
274
- private async changeConsumerPreferredLayers(
275
- consumer: VideoConsumer,
276
- { spatialLayer, temporalLayer }: PreferredLayersParams,
277
- ): Promise<void> {
278
- try {
279
- await this.engine.network.socket.request(MEDIASOUP_EVENTS.consumerChangePreferredLayers, {
280
- consumerId: consumer.id,
281
- spatialLayer,
282
- temporalLayer,
283
- });
284
-
285
- this.logger.debug('changeConsumerPreferredLayers()', {
286
- peer: this,
287
- consumer,
288
- spatialLayer,
289
- temporalLayer,
290
- });
291
- } catch (err) {
292
- this.logger.error('changeConsumerPreferredLayers()', {
293
- peer: this,
294
- consumer,
295
- error: err,
296
- });
297
- throw new Error('Error change preferred layer');
298
- }
299
- }
300
-
301
- private async pauseRemoteConsumer(consumerId: string): Promise<SocketResponse> {
302
- return this.engine.network.socket.request(MEDIASOUP_EVENTS.pauseConsumer, { consumerId });
303
- }
304
-
305
- private async resumeRemoteConsumer(consumerId: string): Promise<SocketResponse> {
306
- return this.engine.network.socket.request(MEDIASOUP_EVENTS.resumeConsumer, { consumerId });
307
- }
308
-
309
165
  private handleNewProducer(producerData: ProducerData): void {
310
166
  if (this.producers.get(producerData.id)) {
311
167
  return;
@@ -335,13 +191,13 @@ class Peer {
335
191
  });
336
192
 
337
193
  this.observer.on(MEDIASOUP_EVENTS.closeConsumer, (consumerId) => {
338
- const consumer = this.consumers.get(consumerId);
194
+ const consumer = this.getConsumerById(consumerId);
339
195
  if (!consumer) {
340
196
  return;
341
197
  }
342
198
 
343
199
  consumer.close();
344
- this.consumers.delete(consumerId);
200
+ this.tracks.delete(consumer.appData.producerData.label);
345
201
  this.observer.safeEmit(PEER_EVENTS.trackEnd, {
346
202
  producerId: consumer.producerId,
347
203
  kind: consumer.kind,
@@ -351,7 +207,7 @@ class Peer {
351
207
  });
352
208
 
353
209
  this.observer.on(MEDIASOUP_EVENTS.pauseConsumer, (consumerId) => {
354
- const consumer = this.consumers.get(consumerId);
210
+ const consumer = this.getConsumerById(consumerId);
355
211
  if (!consumer) {
356
212
  return;
357
213
  }
@@ -361,7 +217,7 @@ class Peer {
361
217
  });
362
218
 
363
219
  this.observer.on(MEDIASOUP_EVENTS.resumeConsumer, (consumerId) => {
364
- const consumer = this.consumers.get(consumerId);
220
+ const consumer = this.getConsumerById(consumerId);
365
221
  if (!consumer) {
366
222
  return;
367
223
  }
@@ -376,7 +232,7 @@ class Peer {
376
232
  return;
377
233
  }
378
234
 
379
- const consumer = this.consumers.get(payload.consumerId);
235
+ const consumer = this.getConsumerById(payload.consumerId);
380
236
  if (!consumer) {
381
237
  return;
382
238
  }
@@ -426,6 +282,12 @@ class Peer {
426
282
  return;
427
283
  }
428
284
 
285
+ const track = this.engine.media.getAllTracks().find((t) => t.getProducer()?.id === payload.producerId);
286
+ if (!track) {
287
+ return;
288
+ }
289
+
290
+ const maxSpatialLayer = track.getProducer()?.maxSpatialLayer;
429
291
  const { scores } = payload;
430
292
  if (scores.length === 0) {
431
293
  return;
@@ -433,13 +295,18 @@ class Peer {
433
295
 
434
296
  let { score } = scores[0];
435
297
 
436
- if (scores.length > 1) {
298
+ if (scores.length > 1 && maxSpatialLayer !== 0) {
299
+ // don't count disabled layers if they were disabled recently
300
+ if (maxSpatialLayer) {
301
+ scores.splice(maxSpatialLayer + 1);
302
+ }
303
+
437
304
  // video with multiple encodings has personal score for each encoding
438
305
  const scoresSum = scores
439
306
  .map(({ score: currentScore }) => currentScore)
440
307
  .reduce((acc, curr) => acc + curr, 0);
441
308
 
442
- score = Math.floor(scoresSum / payload.scores.length);
309
+ score = Math.floor(scoresSum / scores.length);
443
310
  }
444
311
 
445
312
  this.outgoingConnectionQuality = Peer.getConnectionQualityByScore(score);
@@ -447,21 +314,30 @@ class Peer {
447
314
  });
448
315
 
449
316
  this.observer.on(MEDIASOUP_EVENTS.consumerChangePreferredLayers, (payload: ChangePreferredLayersPayload) => {
450
- const consumer = this.consumers.get(payload.consumerId);
451
- if (consumer instanceof VideoConsumer) {
317
+ const consumer = this.getConsumerById(payload.consumerId);
318
+ if (consumer?.isVideo) {
452
319
  consumer.setCurrentTemporalLayer(payload.temporalLayer);
453
320
  consumer.setCurrentSpatialLayer(payload.spatialLayer);
321
+ if (payload.spatialLayer === consumer.requestedSpatialLayer) {
322
+ consumer.setRequestedSpatialLayer(undefined);
323
+ }
324
+
325
+ this.logger.debug('consumerChangePreferredLayers()', { consumer, ...payload });
454
326
  }
455
327
  });
456
328
  }
457
329
 
458
330
  private emitConnectionQuality(): void {
459
- // pick connection (incoming or outgoing) with lower quality
460
- const connectionQuality = Math.min(this.outgoingConnectionQuality, this.incomingConnectionQuality);
331
+ // after the initialization a new layer, or new producer, scores of producers and consumers drop for a short time
332
+ setTimeout(() => {
333
+ // pick connection (incoming or outgoing) with lower quality
334
+ const connectionQuality = Math.min(this.outgoingConnectionQuality, this.incomingConnectionQuality);
335
+ this.observer.safeEmit(PEER_EVENTS.connectionQualityChanged, {
336
+ connectionQuality,
337
+ });
461
338
 
462
- this.observer.safeEmit(PEER_EVENTS.connectionQualityChanged, {
463
- connectionQuality,
464
- });
339
+ this.logger.debug('emitConnectionQuality()', { peer: this, connectionQuality });
340
+ }, 1000);
465
341
  }
466
342
 
467
343
  static getConnectionQualityByScore(score: number): ConnectionQuality {
@@ -476,13 +352,23 @@ class Peer {
476
352
  return ConnectionQuality.GOOD;
477
353
  }
478
354
 
479
- public getAllConsumers(): Consumer[] {
480
- return Array.from(this.consumers.values());
355
+ private getAllConsumers(): PeerConsumer[] {
356
+ return Array.from(this.tracks.values())
357
+ .map((track) => track.consumer)
358
+ .filter((item): item is PeerConsumer => !!item);
481
359
  }
482
360
 
483
361
  public getAllProducers(): PeerProducer[] {
484
362
  return Array.from(this.producers.values());
485
363
  }
364
+
365
+ public getConsumerByProducerId(producerId: string): PeerConsumer | undefined {
366
+ return this.getAllConsumers().find((consumer) => consumer.producerId === producerId);
367
+ }
368
+
369
+ public getConsumerById(id: string): PeerConsumer | undefined {
370
+ return this.getAllConsumers().find((consumer) => consumer.id === id);
371
+ }
486
372
  }
487
373
 
488
374
  export default Peer;
@@ -0,0 +1,144 @@
1
+ import { parseScalabilityMode } from 'mediasoup-client';
2
+ import { MediaKind, RtpEncodingParameters } from 'mediasoup-client/lib/RtpParameters';
3
+ import { Consumer as MediasoupConsumer } from 'mediasoup-client/lib/types';
4
+ import { ConsumerData, SpatialLayerParams } from '../types/common';
5
+ import Logger from './Logger';
6
+
7
+ class PeerConsumer {
8
+ public score = 10;
9
+
10
+ public producerScore = 10;
11
+
12
+ public spatialLayers = 0;
13
+
14
+ public temporalLayers = 0;
15
+
16
+ public currentSpatialLayer = 0;
17
+
18
+ public currentTemporalLayer = 0;
19
+
20
+ public requestedSpatialLayer?: number;
21
+
22
+ public currentMaxSpatialLayer: number;
23
+
24
+ public availableSpatialLayers: SpatialLayerParams[] = [];
25
+
26
+ public currentSpatialLayerParams?: SpatialLayerParams;
27
+
28
+ readonly id: string;
29
+
30
+ readonly kind: MediaKind;
31
+
32
+ readonly producerId: string;
33
+
34
+ readonly appData: ConsumerData;
35
+
36
+ private readonly consumer: MediasoupConsumer;
37
+
38
+ private readonly logger: Logger;
39
+
40
+ constructor(consumer: MediasoupConsumer) {
41
+ this.id = consumer.id;
42
+ this.kind = consumer.kind as MediaKind;
43
+ this.producerId = consumer.producerId;
44
+ this.appData = consumer.appData as ConsumerData;
45
+ this.consumer = consumer;
46
+ this.logger = new Logger('PeerConsumer');
47
+ this.currentMaxSpatialLayer = this.appData.producerData.maxSpatialLayer;
48
+ this.parseScalabilityMode();
49
+ this.setSpatialLayersParams();
50
+ this.setCurrentSpatialLayerParams();
51
+ }
52
+
53
+ get paused() {
54
+ return this.consumer.paused;
55
+ }
56
+
57
+ pause() {
58
+ return this.consumer.pause();
59
+ }
60
+
61
+ resume() {
62
+ return this.consumer.resume();
63
+ }
64
+
65
+ close() {
66
+ return this.consumer.close();
67
+ }
68
+
69
+ get isVideo(): boolean {
70
+ return this.kind === 'video';
71
+ }
72
+
73
+ get isAudio(): boolean {
74
+ return this.kind === 'audio';
75
+ }
76
+
77
+ parseScalabilityMode(): void {
78
+ if (this.consumer.rtpParameters.encodings) {
79
+ const { scalabilityMode } = this.consumer.rtpParameters.encodings[0];
80
+ const { spatialLayers, temporalLayers } = parseScalabilityMode(scalabilityMode);
81
+ this.spatialLayers = spatialLayers;
82
+ this.temporalLayers = temporalLayers;
83
+ this.logger.debug('parseScalabilityMode()', {
84
+ scalabilityMode,
85
+ spatialLayers,
86
+ temporalLayers,
87
+ });
88
+ }
89
+ }
90
+
91
+ setSpatialLayersParams(): void {
92
+ const { encodings } = this.appData.producerData;
93
+ this.availableSpatialLayers = encodings.map((encoding) => this.parseSpatialLayerParams(encoding));
94
+ }
95
+
96
+ setCurrentSpatialLayerParams(): void {
97
+ const { encodings } = this.appData.producerData;
98
+ this.currentSpatialLayerParams = this.parseSpatialLayerParams(encodings[this.currentSpatialLayer]);
99
+ this.logger.debug('setCurrentSpatialLayerParams()', { currentSpatialLayerParams: this.currentSpatialLayerParams });
100
+ }
101
+
102
+ parseSpatialLayerParams(encoding: RtpEncodingParameters): SpatialLayerParams {
103
+ const { trackTransformParams: { width, height } } = this.appData.producerData;
104
+ const coefficient = encoding.scaleResolutionDownBy || 1;
105
+ if (width && height) {
106
+ return {
107
+ width: width / coefficient,
108
+ height: height / coefficient,
109
+ ...encoding,
110
+ };
111
+ }
112
+
113
+ return encoding;
114
+ }
115
+
116
+ setCurrentSpatialLayer(currentSpatialLayer: number): void {
117
+ if (!this.isVideo) {
118
+ throw new Error('setCurrentSpatialLayer applies to video consumers only');
119
+ }
120
+
121
+ this.currentSpatialLayer = currentSpatialLayer;
122
+ this.logger.debug('setCurrentSpatialLayer()', { currentSpatialLayer });
123
+ this.setCurrentSpatialLayerParams();
124
+ }
125
+
126
+ setCurrentTemporalLayer(currentTemporalLayer: number): void {
127
+ if (!this.isVideo) {
128
+ throw new Error('setCurrentTemporalLayer applies to video consumers only');
129
+ }
130
+
131
+ this.currentTemporalLayer = currentTemporalLayer;
132
+ this.logger.debug('setCurrentTemporalLayer()', { currentTemporalLayer });
133
+ }
134
+
135
+ setRequestedSpatialLayer(spatialLayer: number | undefined): void {
136
+ this.requestedSpatialLayer = spatialLayer;
137
+ }
138
+
139
+ setCurrentMaxSpatialLayer(spatialLayer: number): void {
140
+ this.currentMaxSpatialLayer = spatialLayer;
141
+ }
142
+ }
143
+
144
+ export default PeerConsumer;
@@ -1,5 +1,6 @@
1
1
  import { MediaKind } from 'mediasoup-client/lib/RtpParameters';
2
- import { ProducerData, TrackLabel } from '../types/common';
2
+ import { RtpEncodingParameters } from 'mediasoup-client/lib/types';
3
+ import { ProducerData, TrackLabel, TrackTransformParams } from '../types/common';
3
4
 
4
5
  class PeerProducer {
5
6
  readonly id: string;
@@ -10,6 +11,12 @@ class PeerProducer {
10
11
 
11
12
  readonly label: TrackLabel;
12
13
 
14
+ readonly encodings: RtpEncodingParameters[];
15
+
16
+ readonly trackTransformParams: TrackTransformParams;
17
+
18
+ readonly maxSpatialLayer: number;
19
+
13
20
  public score = 10;
14
21
 
15
22
  constructor(params: ProducerData) {
@@ -21,6 +28,9 @@ class PeerProducer {
21
28
  this.kind = kind;
22
29
  this.peerId = peerId;
23
30
  this.label = label;
31
+ this.encodings = params.encodings;
32
+ this.trackTransformParams = params.trackTransformParams;
33
+ this.maxSpatialLayer = params.maxSpatialLayer;
24
34
  }
25
35
  }
26
36