@livedigital/client 2.32.0 → 2.32.2

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@livedigital/client",
3
3
  "author": "vlprojects",
4
4
  "license": "MIT",
5
- "version": "2.32.0",
5
+ "version": "2.32.2",
6
6
  "private": false,
7
7
  "bugs": {
8
8
  "url": "https://github.com/vlprojects/livedigital-sdk/issues"
@@ -40,6 +40,7 @@
40
40
  ]
41
41
  },
42
42
  "dependencies": {
43
+ "async-mutex": "^0.3.2",
43
44
  "awaitqueue": "^2.4.0",
44
45
  "axios": "^0.21.4",
45
46
  "debug": "^4.3.1",
@@ -228,7 +228,7 @@ class Peer {
228
228
  }
229
229
 
230
230
  track.setIsTrackProducerPaused(true);
231
- await track.pause();
231
+ await track.pause(false);
232
232
  });
233
233
 
234
234
  this.observer.on(MEDIASOUP_EVENTS.resumeConsumer, async (consumerId) => {
@@ -238,7 +238,7 @@ class Peer {
238
238
  }
239
239
 
240
240
  track.setIsTrackProducerPaused(false);
241
- await track.resume();
241
+ await track.resume(false);
242
242
  });
243
243
 
244
244
  // set outgoing connection quality for remote peer
@@ -117,8 +117,14 @@ class Media {
117
117
  return Array.from(this.tracks.values());
118
118
  }
119
119
 
120
- clearTracks(): void {
121
- this.tracks.clear();
120
+ async clearTracks(): Promise<void> {
121
+ try {
122
+ this.getAllTracks().map((track) => track.stopMediaStreamTrack());
123
+ } catch (error) {
124
+ this.#logger.warn('clearTracks()', { error });
125
+ } finally {
126
+ this.tracks.clear();
127
+ }
122
128
  }
123
129
 
124
130
  static getScreenVideoTrackParams(options?: CreateScreenVideoTrackOptions): CreateVideoTrackParams {
@@ -1,5 +1,6 @@
1
1
  import { Producer } from 'mediasoup-client/lib/Producer';
2
2
  import { MediaKind } from 'mediasoup-client/lib/RtpParameters';
3
+ import { Mutex } from 'async-mutex';
3
4
  import {
4
5
  BaseTrackInfo,
5
6
  EncoderConfig,
@@ -56,6 +57,8 @@ class BaseTrack {
56
57
 
57
58
  #stopTrackOnPause = true;
58
59
 
60
+ #mutex = new Mutex();
61
+
59
62
  constructor(params: BaseTrackConstructorParams) {
60
63
  const {
61
64
  mediaStreamTrack, logLevel, engine, clientEventEmitter, constraints, mediaStreamTrackManager,
@@ -162,6 +165,10 @@ class BaseTrack {
162
165
  });
163
166
  }
164
167
 
168
+ stopMediaStreamTrack(): void {
169
+ this.mediaStreamTrack.stop();
170
+ }
171
+
165
172
  private async checkProducerState(): Promise<void> {
166
173
  try {
167
174
  if (this.#closed || this.kind === 'audio') {
@@ -379,6 +386,9 @@ class BaseTrack {
379
386
  }
380
387
 
381
388
  public async pause(): Promise<void> {
389
+ await this.#mutex.waitForUnlock();
390
+ const release = await this.#mutex.acquire();
391
+
382
392
  if (!this.producer) {
383
393
  this.logger.warn('pause()', { message: 'Track is not published', track: this });
384
394
  return;
@@ -400,10 +410,15 @@ class BaseTrack {
400
410
  } catch (error) {
401
411
  this.logger.error('pause()', { error, track: this });
402
412
  throw new Error('Can`t pause track');
413
+ } finally {
414
+ release();
403
415
  }
404
416
  }
405
417
 
406
418
  public async resume(): Promise<void> {
419
+ await this.#mutex.waitForUnlock();
420
+ const release = await this.#mutex.acquire();
421
+
407
422
  if (!this.producer) {
408
423
  this.logger.warn('resume()', { message: 'Track is not published', track: this });
409
424
  return;
@@ -423,6 +438,8 @@ class BaseTrack {
423
438
  } catch (error) {
424
439
  this.logger.error('resume()', { error, track: this });
425
440
  throw new Error('Can`t resume track');
441
+ } finally {
442
+ release();
426
443
  }
427
444
  }
428
445
 
@@ -1,4 +1,5 @@
1
1
  import { MediaKind } from 'mediasoup-client/lib/types';
2
+ import { AwaitQueue } from 'awaitqueue';
2
3
  import {
3
4
  PreferredLayersParams,
4
5
  SetConsumerPriorityParams,
@@ -50,6 +51,8 @@ class PeerTrack {
50
51
 
51
52
  #isTrackProducerPaused?: boolean;
52
53
 
54
+ #queue = new AwaitQueue();
55
+
53
56
  constructor(payload: PeerTrackConstructor) {
54
57
  this.#mediaStreamTrack = payload.mediaStreamTrack;
55
58
  this.label = payload.label;
@@ -101,59 +104,73 @@ class PeerTrack {
101
104
  this.clearCheckStateTimeout();
102
105
  }
103
106
 
104
- public async pause(): Promise<void> {
105
- if (!this.consumer) {
106
- this.#paused = true;
107
- this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackPaused, this);
108
- return;
109
- }
107
+ public async pause(pauseRemote = true): Promise<void> {
108
+ await this.#queue.push(async () => {
109
+ if (!this.consumer) {
110
+ this.#paused = true;
111
+ this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackPaused, this);
112
+ return;
113
+ }
110
114
 
111
- if (this.#paused) {
112
- this.#logger.debug('pause()', { message: 'Already paused', peer: this, consumer: this.consumer });
113
- return;
114
- }
115
+ if (this.#paused) {
116
+ this.#logger.debug('pause()', { message: 'Already paused', peer: this, consumer: this.consumer });
117
+ return;
118
+ }
115
119
 
116
- try {
117
- this.clearCheckStateTimeout();
118
- await this.#engine.network.pauseRemoteConsumer(this.consumer.id);
119
- this.consumer.pause();
120
- this.#paused = true;
121
- this.#consumerRestarted = false;
122
- this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackPaused, this);
123
- this.#logger.debug('pause()', { peer: this, consumer: this.consumer });
124
- } catch (error) {
125
- this.#logger.warn('pause()', { error });
126
- }
120
+ try {
121
+ this.clearCheckStateTimeout();
122
+ if (pauseRemote) {
123
+ await this.#engine.network.pauseRemoteConsumer(this.consumer.id);
124
+ }
125
+
126
+ this.consumer.pause();
127
+ this.#paused = true;
128
+ this.#consumerRestarted = false;
129
+ this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackPaused, this);
130
+ this.#logger.debug('pause()', { peer: this, consumer: this.consumer });
131
+ } catch (error) {
132
+ this.#logger.warn('pause()', { error });
133
+ }
134
+ });
127
135
  }
128
136
 
129
- public async resume(): Promise<void> {
130
- if (!this.consumer) {
131
- this.#paused = false;
132
- this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackResumed, this);
133
- this.#logger.debug('resume()', { track: this, peer: this });
134
- return;
135
- }
137
+ public async resume(resumeRemote = true): Promise<void> {
138
+ await this.#queue.push(async () => {
139
+ if (!this.consumer) {
140
+ this.#paused = false;
141
+ this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackResumed, this);
142
+ this.#logger.debug('resume()', { track: this, peer: this });
143
+ return;
144
+ }
136
145
 
137
- if (!this.#paused) {
138
- this.#logger.debug('resume()', { message: 'Already playing', track: this, peer: this });
139
- return;
140
- }
146
+ if (!this.#paused) {
147
+ this.#logger.debug('resume()', { message: 'Already playing', track: this, peer: this });
148
+ return;
149
+ }
141
150
 
142
- if (this.#isTrackProducerPaused) {
143
- this.#logger.debug('resume()', { message: 'Can not resume track, producer is paused', track: this, peer: this });
144
- return;
145
- }
151
+ if (this.#isTrackProducerPaused) {
152
+ this.#logger.debug('resume()', {
153
+ message: 'Can not resume track, producer is paused',
154
+ track: this,
155
+ peer: this,
156
+ });
157
+ return;
158
+ }
146
159
 
147
- try {
148
- await this.#engine.network.resumeRemoteConsumer(this.consumer.id);
149
- this.consumer.resume();
150
- this.#paused = false;
151
- this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackResumed, this);
152
- this.checkConsumerState();
153
- this.#logger.debug('resume()', { track: this, peer: this });
154
- } catch (error) {
155
- this.#logger.warn('resume()', { error });
156
- }
160
+ try {
161
+ if (resumeRemote) {
162
+ await this.#engine.network.resumeRemoteConsumer(this.consumer.id);
163
+ }
164
+
165
+ this.consumer.resume();
166
+ this.#paused = false;
167
+ this.#peerEventEmitter.safeEmit(PEER_EVENTS.trackResumed, this);
168
+ this.checkConsumerState();
169
+ this.#logger.debug('resume()', { track: this, peer: this });
170
+ } catch (error) {
171
+ this.#logger.warn('resume()', { error });
172
+ }
173
+ });
157
174
  }
158
175
 
159
176
  public async setPriority(priority: number): Promise<void> {
@@ -108,14 +108,14 @@ class System {
108
108
  try {
109
109
  await this.requestMediaDevicesAccess();
110
110
  } catch (errorVideoAndAudio) {
111
- if (errorVideoAndAudio.message !== DeviceErrors.NotFoundError) {
111
+ if (![DeviceErrors.NotFoundError, DeviceErrors.NotAllowedError].includes(errorVideoAndAudio.message)) {
112
112
  throw errorVideoAndAudio;
113
113
  }
114
114
 
115
115
  try {
116
116
  await this.requestMediaDevicesAccess({ audio: true });
117
117
  } catch (errorAudioOnly) {
118
- if (errorAudioOnly.message !== DeviceErrors.NotFoundError) {
118
+ if (![DeviceErrors.NotFoundError, DeviceErrors.NotAllowedError].includes(errorAudioOnly.message)) {
119
119
  throw errorAudioOnly;
120
120
  }
121
121