@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.
@@ -2,11 +2,13 @@ import {
2
2
  ChangePreferredLayersParams,
3
3
  ConsumerScoreChangedPayload,
4
4
  ProducerData,
5
- ProducerScoreChangedPayload,
5
+ ProducerRequestMaxSpatialLayer,
6
+ ProducerScoreChangedPayload, ProducerSetMaxSpatialLayer,
6
7
  } from '../../types/common';
7
8
  import Engine from '../index';
8
9
  import { MEDIASOUP_EVENTS } from '../../constants/events';
9
10
  import Logger from '../Logger';
11
+ import VideoTrack from '../media/tracks/VideoTrack';
10
12
 
11
13
  class MediaSoupEventHandler {
12
14
  private readonly engine: Engine;
@@ -108,6 +110,83 @@ class MediaSoupEventHandler {
108
110
 
109
111
  peer.observer.safeEmit(MEDIASOUP_EVENTS.producerScoreChanged, payload);
110
112
  });
113
+
114
+ connection.on(MEDIASOUP_EVENTS.producerRequestMaxSpatialLayer, async ({
115
+ producerId,
116
+ spatialLayer,
117
+ }: ProducerRequestMaxSpatialLayer) => {
118
+ const track = this.engine.media.getAllTracks().find((t) => t.getProducer()?.id === producerId);
119
+ if (!track) {
120
+ this.logger.warn('producerRequestMaxSpatialLayer()', { message: 'Producer not found' });
121
+ return;
122
+ }
123
+
124
+ if (!(track instanceof VideoTrack)) {
125
+ this.logger.warn('producerRequestMaxSpatialLayer()', { message: 'Wrong producer kind' });
126
+ return;
127
+ }
128
+
129
+ const currentMaxSpatialLayer = track.getMaxSpatialLayer();
130
+ if (currentMaxSpatialLayer === spatialLayer) {
131
+ this.logger.debug('producerRequestMaxSpatialLayer()', {
132
+ message: 'Skip set max spatial layer',
133
+ requestedSpatialLayer: spatialLayer,
134
+ currentMaxSpatialLayer,
135
+ });
136
+ return;
137
+ }
138
+
139
+ await track.setMaxSpatialLayer(spatialLayer);
140
+ await this.engine.network.socket.request(MEDIASOUP_EVENTS.producerSetMaxSpatialLayer, {
141
+ producerId,
142
+ maxSpatialLayer: spatialLayer,
143
+ });
144
+ });
145
+
146
+ connection.on(MEDIASOUP_EVENTS.producerSetMaxSpatialLayer, async ({
147
+ peerId,
148
+ producerId,
149
+ spatialLayer,
150
+ }: ProducerSetMaxSpatialLayer) => {
151
+ const peer = this.engine.peers.find((item) => item.id === peerId);
152
+ if (!peer || peer.isMe) {
153
+ return;
154
+ }
155
+
156
+ const consumer = peer.getConsumerByProducerId(producerId);
157
+ if (!consumer) {
158
+ this.logger.warn('producerSetMaxSpatialLayer()', { message: 'Consumer not found' });
159
+ return;
160
+ }
161
+
162
+ consumer.setCurrentMaxSpatialLayer(spatialLayer);
163
+ this.logger.debug('producerSetMaxSpatialLayer()', {
164
+ producerId,
165
+ consumerId: consumer.id,
166
+ spatialLayer,
167
+ });
168
+
169
+ if (consumer.requestedSpatialLayer !== spatialLayer) {
170
+ this.logger.debug('producerSetMaxSpatialLayer()', {
171
+ message: 'No need to request new preferred layer',
172
+ currentMaxSpatialLayer: spatialLayer,
173
+ requestedMaxSpatialLayer: consumer.requestedSpatialLayer,
174
+ });
175
+
176
+ return;
177
+ }
178
+
179
+ await this.engine.network.socket.request(MEDIASOUP_EVENTS.consumerChangePreferredLayers, {
180
+ consumerId: consumer.id,
181
+ spatialLayer,
182
+ });
183
+
184
+ this.logger.debug('requestVideoPreferredLayers()', {
185
+ producerId,
186
+ consumerId: consumer.id,
187
+ spatialLayer,
188
+ });
189
+ });
111
190
  }
112
191
  }
113
192
 
@@ -8,7 +8,6 @@ import {
8
8
  PeerResponse,
9
9
  Role,
10
10
  SocketResponse,
11
- StartTrackPayload,
12
11
  Track,
13
12
  TrackLabel,
14
13
  } from '../types/common';
@@ -23,6 +22,9 @@ import Logger from './Logger';
23
22
  import {
24
23
  CHANNEL_EVENTS, CLIENT_EVENTS, MEDIASOUP_EVENTS, PEER_EVENTS, SocketIOEvents,
25
24
  } from '../constants/events';
25
+ import VideoTrack from './media/tracks/VideoTrack';
26
+ import AudioTrack from './media/tracks/AudioTrack';
27
+ import PeerTrack from './media/tracks/PeerTrack';
26
28
 
27
29
  type EngineParams = {
28
30
  clientEventEmitter: EnhancedEventEmitter,
@@ -219,8 +221,11 @@ class Engine {
219
221
  video: trackParams.videoTrackOptions,
220
222
  });
221
223
 
222
- track.setLabel(TrackLabel.Camera);
223
- track.setEncoderConfig(trackParams.encoderConfig);
224
+ if (track instanceof VideoTrack) {
225
+ track.setLabel(TrackLabel.Camera);
226
+ track.setEncoderConfig(trackParams.encoderConfig);
227
+ track.setTransformParams(trackParams.transformParams);
228
+ }
224
229
 
225
230
  this.logger.debug('createCameraVideoTrack()', { trackParams, track });
226
231
  return track;
@@ -265,9 +270,10 @@ class Engine {
265
270
  this.unpublish(track);
266
271
  });
267
272
 
268
- if (track.kind === 'video') {
273
+ if (track instanceof VideoTrack) {
269
274
  track.setLabel(TrackLabel.ScreenVideo);
270
275
  track.setEncoderConfig(videoTrackParams.encoderConfig);
276
+ track.setTransformParams(videoTrackParams.transformParams);
271
277
  this.logger.debug('createScreenMediaTrack()', { trackParams: videoTrackParams, track });
272
278
  return;
273
279
  }
@@ -303,6 +309,19 @@ class Engine {
303
309
  ? track.getCodecOptions()
304
310
  : undefined;
305
311
 
312
+ const maxSpatialLayer = encodings && encodings.length >= 1 ? 1 : 0;
313
+ const appData = {
314
+ peerId: this.mySocketId,
315
+ label: track.getLabel(),
316
+ trackTransformParams: {},
317
+ maxSpatialLayer: 0,
318
+ };
319
+
320
+ if (track instanceof VideoTrack) {
321
+ appData.maxSpatialLayer = maxSpatialLayer;
322
+ appData.trackTransformParams = track.transformParams;
323
+ }
324
+
306
325
  const producer = await this.network.sendTransport?.produce({
307
326
  track: track.mediaStreamTrack,
308
327
  encodings,
@@ -311,10 +330,7 @@ class Engine {
311
330
  stopTracks: true,
312
331
  disableTrackOnPause: true,
313
332
  zeroRtpOnPause: true,
314
- appData: {
315
- peerId: this.mySocketId,
316
- label: track.getLabel(),
317
- },
333
+ appData,
318
334
  });
319
335
 
320
336
  if (!producer) {
@@ -322,12 +338,31 @@ class Engine {
322
338
  }
323
339
 
324
340
  track.setProducer(producer);
341
+
342
+ if (track instanceof VideoTrack) {
343
+ await track.setMaxSpatialLayer(maxSpatialLayer);
344
+ await this.network.socket.request(MEDIASOUP_EVENTS.producerSetMaxSpatialLayer, {
345
+ producerId: track.getProducer()?.id,
346
+ maxSpatialLayer,
347
+ });
348
+ }
349
+
350
+ if (track instanceof AudioTrack) {
351
+ await track.setPriority('high');
352
+ }
353
+
325
354
  const myPeer = this.peersRepository.get(<string> this.mySocketId);
326
- myPeer?.observer.safeEmit(PEER_EVENTS.trackStart, {
327
- producerId: producer.id,
328
- track: track.mediaStreamTrack,
355
+ if (!myPeer) {
356
+ return;
357
+ }
358
+
359
+ const peerTrack = new PeerTrack({
360
+ mediaStreamTrack: track.mediaStreamTrack,
329
361
  label: track.getLabel(),
330
- } as StartTrackPayload);
362
+ engine: this,
363
+ });
364
+ myPeer.tracks.set(peerTrack.label, peerTrack);
365
+ myPeer.observer.safeEmit(PEER_EVENTS.trackStart, peerTrack);
331
366
 
332
367
  this.logger.debug('publish()', { track, encodings, codecOptions });
333
368
  });
@@ -93,6 +93,10 @@ class Media {
93
93
  width: { ideal: options?.width || VIDEO_CONSTRAINS.fullhd.width },
94
94
  height: { ideal: options?.height || VIDEO_CONSTRAINS.fullhd.height },
95
95
  },
96
+ transformParams: {
97
+ width: options?.width || VIDEO_CONSTRAINS.hd.width,
98
+ height: options?.height || VIDEO_CONSTRAINS.hd.height,
99
+ },
96
100
  encoderConfig: options?.encoderConfig || {
97
101
  encodings: SCREEN_SHARING_SIMULCAST_ENCODINGS,
98
102
  },
@@ -107,6 +111,10 @@ class Media {
107
111
  width: { ideal: options?.width || VIDEO_CONSTRAINS.hd.width },
108
112
  height: { ideal: options?.height || VIDEO_CONSTRAINS.hd.height },
109
113
  },
114
+ transformParams: {
115
+ width: options?.width || VIDEO_CONSTRAINS.hd.width,
116
+ height: options?.height || VIDEO_CONSTRAINS.hd.height,
117
+ },
110
118
  encoderConfig: options?.encoderConfig || {
111
119
  encodings: WEBCAM_SIMULCAST_ENCODINGS,
112
120
  },
@@ -1,6 +1,7 @@
1
1
  import { Producer } from 'mediasoup-client/lib/Producer';
2
2
  import { MediaKind } from 'mediasoup-client/lib/RtpParameters';
3
3
  import { EncoderConfig, TrackLabel } from '../../../types/common';
4
+ import Logger from '../../Logger';
4
5
 
5
6
  class BaseTrack {
6
7
  readonly #mediaStreamTrack: MediaStreamTrack;
@@ -11,6 +12,8 @@ class BaseTrack {
11
12
 
12
13
  private label: TrackLabel = TrackLabel.Unknown;
13
14
 
15
+ protected logger = new Logger('Track');
16
+
14
17
  constructor(mediaStreamTrack: MediaStreamTrack) {
15
18
  this.#mediaStreamTrack = mediaStreamTrack;
16
19
  }
@@ -65,6 +68,19 @@ class BaseTrack {
65
68
  this.producer?.close();
66
69
  this.producer = undefined;
67
70
  }
71
+
72
+ async setPriority(priority: RTCPriorityType): Promise<void> {
73
+ if (!this.producer) {
74
+ this.logger.warn('setPriority()', 'Not published yet');
75
+ return;
76
+ }
77
+
78
+ await this.producer.setRtpEncodingParameters({ priority });
79
+ this.logger.debug('setPriority()', {
80
+ label: this.getLabel(),
81
+ priority,
82
+ });
83
+ }
68
84
  }
69
85
 
70
86
  export default BaseTrack;
@@ -0,0 +1,214 @@
1
+ import {
2
+ PreferredLayersParams, SetConsumerPriorityParams, SocketResponse,
3
+ SpatialLayerParams,
4
+ TrackLabel,
5
+ } from '../../../types/common';
6
+ import Logger from '../../Logger';
7
+ import { MEDIASOUP_EVENTS } from '../../../constants/events';
8
+ import PeerConsumer from '../../PeerConsumer';
9
+ import Engine from '../../index';
10
+
11
+ interface PeerTrackConstructor {
12
+ mediaStreamTrack: MediaStreamTrack,
13
+ label: TrackLabel,
14
+ consumer?: PeerConsumer,
15
+ engine: Engine,
16
+ }
17
+
18
+ class PeerTrack {
19
+ public readonly mediaStreamTrack: MediaStreamTrack;
20
+
21
+ public readonly label: TrackLabel = TrackLabel.Unknown;
22
+
23
+ readonly consumer?: PeerConsumer;
24
+
25
+ readonly #engine: Engine;
26
+
27
+ readonly #logger = new Logger('PeerTrack');
28
+
29
+ constructor(payload: PeerTrackConstructor) {
30
+ this.mediaStreamTrack = payload.mediaStreamTrack;
31
+ this.label = payload.label;
32
+ this.consumer = payload.consumer;
33
+ this.#engine = payload.engine;
34
+ }
35
+
36
+ get consumerId(): string | undefined {
37
+ return this.consumer?.id;
38
+ }
39
+
40
+ get currentSpatialLayer(): number {
41
+ return this.consumer?.currentSpatialLayer || 0;
42
+ }
43
+
44
+ public close(): void {
45
+ this.consumer?.close();
46
+ }
47
+
48
+ public async pause(): Promise<void> {
49
+ if (!this.consumer) {
50
+ return;
51
+ }
52
+
53
+ if (this.consumer.paused) {
54
+ this.#logger.warn('pause()', { message: 'Already paused', peer: this, consumer: this.consumer });
55
+ return;
56
+ }
57
+
58
+ try {
59
+ await this.pauseRemoteConsumer(this.consumer.id);
60
+ this.consumer.pause();
61
+ this.#logger.debug('pause()', { peer: this, consumer: this.consumer });
62
+ } catch (err) {
63
+ this.#logger.error('pause()', err);
64
+ }
65
+ }
66
+
67
+ public async resume(): Promise<void> {
68
+ if (!this.consumer) {
69
+ return;
70
+ }
71
+
72
+ if (!this.consumer.paused) {
73
+ this.#logger.warn('resume()', { message: 'Already playing', peer: this, consumer: this.consumer });
74
+ return;
75
+ }
76
+
77
+ try {
78
+ await this.resumeRemoteConsumer(this.consumer.id);
79
+ this.consumer.resume();
80
+ this.#logger.debug('resume()', { peer: this });
81
+ } catch (err) {
82
+ this.#logger.error('resume()', err);
83
+ }
84
+ }
85
+
86
+ public async setPriority(priority: number): Promise<void> {
87
+ if (!this.consumer) {
88
+ return;
89
+ }
90
+
91
+ await this.setConsumerPriority({ consumerId: this.consumer.id, priority });
92
+ }
93
+
94
+ private async setConsumerPriority(params: SetConsumerPriorityParams): Promise<void> {
95
+ try {
96
+ await this.#engine.network.socket.request(MEDIASOUP_EVENTS.setConsumerPriority, params);
97
+ this.#logger.debug('setConsumerPriority()', { peer: this, params });
98
+ } catch (err) {
99
+ this.#logger.error('setConsumerPriority()', { peer: this, params });
100
+ throw new Error('Can`t change stream priority');
101
+ }
102
+ }
103
+
104
+ private async pauseRemoteConsumer(consumerId: string): Promise<SocketResponse> {
105
+ return this.#engine.network.socket.request(MEDIASOUP_EVENTS.pauseConsumer, { consumerId });
106
+ }
107
+
108
+ private async resumeRemoteConsumer(consumerId: string): Promise<SocketResponse> {
109
+ return this.#engine.network.socket.request(MEDIASOUP_EVENTS.resumeConsumer, { consumerId });
110
+ }
111
+
112
+ public async requestVideoPreferredLayers({ spatialLayer, temporalLayer }: PreferredLayersParams): Promise<void> {
113
+ if (!this.consumer) {
114
+ return;
115
+ }
116
+
117
+ try {
118
+ if (this.consumer.isAudio) {
119
+ this.#logger.warn('requestVideoPreferredLayers()', { message: 'Only video consumers support' });
120
+ return;
121
+ }
122
+
123
+ if (spatialLayer === this.consumer.currentSpatialLayer) {
124
+ return;
125
+ }
126
+
127
+ if (spatialLayer > this.consumer.spatialLayers) {
128
+ this.#logger.warn('requestVideoPreferredLayers()', { message: 'Invalid spatial layer' });
129
+ return;
130
+ }
131
+
132
+ if (spatialLayer > this.consumer.currentMaxSpatialLayer) {
133
+ await this.requestMaxSpatialLayer(this.consumer.id, spatialLayer);
134
+ return;
135
+ }
136
+
137
+ await this.#engine.network.socket.request(MEDIASOUP_EVENTS.consumerChangePreferredLayers, {
138
+ consumerId: this.consumer.id,
139
+ spatialLayer,
140
+ temporalLayer,
141
+ });
142
+
143
+ this.#logger.debug('requestVideoPreferredLayers()', {
144
+ peer: this,
145
+ consumer: this.consumer,
146
+ spatialLayer,
147
+ temporalLayer,
148
+ });
149
+ } catch (err) {
150
+ this.#logger.error('requestVideoPreferredLayers()', {
151
+ peer: this,
152
+ consumerId: this.consumer.id,
153
+ error: err,
154
+ });
155
+ throw new Error('Error request preferred layers');
156
+ }
157
+ }
158
+
159
+ public getVideoAvailableLayers(): SpatialLayerParams[] | undefined {
160
+ if (!this.consumer) {
161
+ return undefined;
162
+ }
163
+
164
+ if (this.consumer.isAudio) {
165
+ this.#logger.warn('getVideoAvailableLayers()', { message: 'Only video consumers support' });
166
+ return undefined;
167
+ }
168
+
169
+ return this.consumer.availableSpatialLayers;
170
+ }
171
+
172
+ private async requestMaxSpatialLayer(consumerId: string, spatialLayer: number): Promise<void> {
173
+ try {
174
+ if (!this.consumer) {
175
+ return;
176
+ }
177
+
178
+ const cantRequest = this.consumer.isAudio
179
+ || this.consumer.spatialLayers === 0
180
+ || this.consumer.currentMaxSpatialLayer === spatialLayer
181
+ || spatialLayer < this.consumer.currentMaxSpatialLayer;
182
+
183
+ if (cantRequest) {
184
+ this.#logger.warn('requestMaxSpatialLayer()', {
185
+ message: 'Can`t request this spatial layer',
186
+ consumerId,
187
+ spatialLayer,
188
+ });
189
+
190
+ return;
191
+ }
192
+
193
+ this.consumer.setRequestedSpatialLayer(spatialLayer);
194
+ await this.#engine.network.socket.request(MEDIASOUP_EVENTS.producerRequestMaxSpatialLayer, {
195
+ producerId: this.consumer.producerId,
196
+ spatialLayer,
197
+ });
198
+
199
+ this.#logger.debug('requestMaxSpatialLayer()', {
200
+ consumerId,
201
+ spatialLayer,
202
+ });
203
+ } catch (error) {
204
+ this.#logger.warn('requestMaxSpatialLayer()', {
205
+ message: 'Error request spatial layer',
206
+ consumerId,
207
+ spatialLayer,
208
+ error,
209
+ });
210
+ }
211
+ }
212
+ }
213
+
214
+ export default PeerTrack;
@@ -7,6 +7,8 @@ import TrackWithCodecOptions from './TrackWithCodecOptions';
7
7
  import TrackWithEncodings from './TrackWithEncodings';
8
8
 
9
9
  class VideoTrack extends BaseTrack implements TrackWithCodecOptions, TrackWithEncodings {
10
+ public transformParams = {};
11
+
10
12
  getEncoderConfig(): VideoEncoderConfig {
11
13
  return this.encoderConfig;
12
14
  }
@@ -24,6 +26,34 @@ class VideoTrack extends BaseTrack implements TrackWithCodecOptions, TrackWithEn
24
26
  getEncodings(): RtpEncodingParameters[] {
25
27
  return this.getEncoderConfig().encodings || WEBCAM_SIMULCAST_ENCODINGS;
26
28
  }
29
+
30
+ setTransformParams(transformParams: { }) {
31
+ this.transformParams = transformParams;
32
+ }
33
+
34
+ async setMaxSpatialLayer(spatialLayer: number): Promise<void> {
35
+ const producer = this.getProducer();
36
+ if (!producer) {
37
+ this.logger.warn('setMaxSpatialLayer()', { message: 'Not produced yet' });
38
+ return;
39
+ }
40
+
41
+ await producer.setMaxSpatialLayer(spatialLayer);
42
+ this.logger.debug('setMaxSpatialLayer()', {
43
+ label: this.getLabel(),
44
+ spatialLayer,
45
+ });
46
+ }
47
+
48
+ getMaxSpatialLayer(): number | undefined {
49
+ const producer = this.getProducer();
50
+ if (!producer) {
51
+ this.logger.warn('getMaxSpatialLayer()', { message: 'Not produced yet' });
52
+ return undefined;
53
+ }
54
+
55
+ return producer.maxSpatialLayer;
56
+ }
27
57
  }
28
58
 
29
59
  export default VideoTrack;
@@ -23,11 +23,26 @@ export type ProduceParams = {
23
23
  appData: Record<string, unknown>,
24
24
  };
25
25
 
26
+ export type TrackTransformParams = {
27
+ width?: number,
28
+ height?: number,
29
+ };
30
+
26
31
  export type ProducerData = {
27
32
  id: string,
28
33
  kind: MediaKind,
29
34
  peerId: string,
30
35
  label: TrackLabel,
36
+ encodings: RtpEncodingParameters[],
37
+ trackTransformParams: TrackTransformParams,
38
+ maxSpatialLayer: number,
39
+ };
40
+
41
+ export type ConsumerData = {
42
+ producerData: ProducerData,
43
+ peerId: string,
44
+ appId: string,
45
+ channelId: string,
31
46
  };
32
47
 
33
48
  export type Role = 'audience' | 'host';
@@ -210,4 +225,21 @@ export type CreateVideoTrackParams = {
210
225
  frameRate?: { max?: number, min?: number, ideal?: number };
211
226
  },
212
227
  encoderConfig: VideoEncoderConfig,
228
+ transformParams: TransformParams,
229
+ };
230
+
231
+ export type SpatialLayerParams = RtpEncodingParameters & TransformParams;
232
+
233
+ export type ProducerRequestMaxSpatialLayer = {
234
+ producerId: string,
235
+ spatialLayer: number,
236
+ };
237
+
238
+ export type ProducerSetMaxSpatialLayer = ProducerRequestMaxSpatialLayer & {
239
+ peerId: string,
240
+ };
241
+
242
+ export type TransformParams = {
243
+ width?: number,
244
+ height?: number,
213
245
  };
@@ -1,6 +0,0 @@
1
- import { Consumer as MediasoupConsumer } from 'mediasoup-client/lib/types';
2
- declare class Consumer extends MediasoupConsumer {
3
- score: number;
4
- producerScore: number;
5
- }
6
- export default Consumer;
@@ -1,14 +0,0 @@
1
- import { Consumer as MediasoupConsumer } from 'mediasoup-client/lib/types';
2
- import Consumer from './Consumer';
3
- declare class VideoConsumer extends Consumer {
4
- spatialLayers: number;
5
- temporalLayers: number;
6
- currentSpatialLayer: number;
7
- currentTemporalLayer: number;
8
- private readonly logger;
9
- constructor(consumer: MediasoupConsumer);
10
- parseScalabilityMode(): void;
11
- setCurrentSpatialLayer(currentSpatialLayer: number): void;
12
- setCurrentTemporalLayer(currentTemporalLayer: number): void;
13
- }
14
- export default VideoConsumer;
@@ -1,9 +0,0 @@
1
- import { Consumer as MediasoupConsumer } from 'mediasoup-client/lib/types';
2
-
3
- class Consumer extends MediasoupConsumer {
4
- public score = 10;
5
-
6
- public producerScore = 10;
7
- }
8
-
9
- export default Consumer;
@@ -1,48 +0,0 @@
1
- import { Consumer as MediasoupConsumer } from 'mediasoup-client/lib/types';
2
- import { parseScalabilityMode } from 'mediasoup-client';
3
- import Consumer from './Consumer';
4
- import Logger from '../Logger';
5
-
6
- class VideoConsumer extends Consumer {
7
- public spatialLayers = 0;
8
-
9
- public temporalLayers = 0;
10
-
11
- public currentSpatialLayer = 0;
12
-
13
- public currentTemporalLayer = 0;
14
-
15
- private readonly logger: Logger;
16
-
17
- constructor(consumer: MediasoupConsumer) {
18
- super(consumer);
19
- this.logger = new Logger('VideoConsumer');
20
- this.parseScalabilityMode();
21
- }
22
-
23
- parseScalabilityMode(): void {
24
- if (this.rtpParameters.encodings) {
25
- const { scalabilityMode } = this.rtpParameters.encodings[0];
26
- const { spatialLayers, temporalLayers } = parseScalabilityMode(scalabilityMode);
27
- this.spatialLayers = spatialLayers;
28
- this.temporalLayers = temporalLayers;
29
- this.logger.debug('parseScalabilityMode()', {
30
- scalabilityMode,
31
- spatialLayers,
32
- temporalLayers,
33
- });
34
- }
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
- }
46
- }
47
-
48
- export default VideoConsumer;