@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/dist/engine/media/index.d.ts +1 -1
- package/dist/engine/media/tracks/BaseTrack.d.ts +1 -0
- package/dist/engine/media/tracks/PeerTrack.d.ts +2 -2
- package/dist/index.es.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -1
- package/src/engine/Peer.ts +2 -2
- package/src/engine/media/index.ts +8 -2
- package/src/engine/media/tracks/BaseTrack.ts +17 -0
- package/src/engine/media/tracks/PeerTrack.ts +63 -46
- package/src/engine/system/index.ts +2 -2
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.
|
|
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",
|
package/src/engine/Peer.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
106
|
-
this
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
if (this.#paused) {
|
|
116
|
+
this.#logger.debug('pause()', { message: 'Already paused', peer: this, consumer: this.consumer });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
115
119
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
131
|
-
this
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
146
|
+
if (!this.#paused) {
|
|
147
|
+
this.#logger.debug('resume()', { message: 'Already playing', track: this, peer: this });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
141
150
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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 (
|
|
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 (
|
|
118
|
+
if (![DeviceErrors.NotFoundError, DeviceErrors.NotAllowedError].includes(errorAudioOnly.message)) {
|
|
119
119
|
throw errorAudioOnly;
|
|
120
120
|
}
|
|
121
121
|
|