@livedigital/client 2.44.0-test-speaker.1 → 2.44.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.
@@ -157,6 +157,9 @@ export declare type PayloadOfPublishedMedia = {
157
157
  label: TrackLabel;
158
158
  paused: boolean;
159
159
  };
160
+ export declare type TrackForceClosedPayload = {
161
+ label: TrackLabel;
162
+ };
160
163
  export declare type SubscribeOptions = {
161
164
  producerId: string;
162
165
  muted?: boolean;
@@ -316,6 +319,10 @@ export declare type ChangeProducerStatePayload = {
316
319
  peerId: string;
317
320
  producerId: string;
318
321
  };
322
+ export declare type ForceCloseProducerPayload = {
323
+ peerId: string;
324
+ label: TrackLabel;
325
+ };
319
326
  export interface TrackWithEncodings {
320
327
  getCodecOptions(): ProducerCodecOptions;
321
328
  getEncodings(): RtpEncodingParameters[];
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@livedigital/client",
3
3
  "author": "vlprojects",
4
4
  "license": "MIT",
5
- "version": "2.44.0-test-speaker.1",
5
+ "version": "2.44.0",
6
6
  "private": false,
7
7
  "bugs": {
8
8
  "url": "https://github.com/vlprojects/livedigital-sdk/issues"
@@ -22,6 +22,7 @@ export const CLIENT_EVENTS = {
22
22
  devicesListUpdated: 'devices-list-updated',
23
23
  transportConnectionTimeout: 'transport-connection-timeout',
24
24
  trackPublishingFailed: 'track-publishing-failed',
25
+ trackForceClosed: 'track-force-closed',
25
26
  activeSpeakerChanged: 'active-speaker-changed',
26
27
  };
27
28
 
@@ -68,6 +69,7 @@ export const MEDIASOUP_EVENTS = {
68
69
  producerResume: 'producer.resume',
69
70
  producerPaused: 'producer.paused',
70
71
  producerResumed: 'producer.resumed',
72
+ producerForceClosed: 'producer.forceClosed',
71
73
  producerScoreChanged: 'producer.scoreChanged',
72
74
  producerSetMaxSpatialLayer: 'producer.setMaxSpatialLayer',
73
75
  producerRequestMaxSpatialLayer: 'producer.requestMaxSpatialLayer',
@@ -73,6 +73,7 @@ class ChannelAudioObserverEventHandler {
73
73
  private handleSilence(): void {
74
74
  const tracks = this.engine.peers.flatMap((peer) => Array.from(peer.tracks.values()));
75
75
  tracks.forEach((track) => track.setVolume(0));
76
+ this.engine.setActiveSpeakerPeer(undefined);
76
77
  }
77
78
 
78
79
  private static validateEventPayload(payload: AudioObserverEvents): void {
@@ -1,16 +1,18 @@
1
1
  import { AwaitQueue } from 'awaitqueue';
2
2
  import {
3
3
  ChangePreferredLayersParams, ChangeProducerStatePayload,
4
- ConsumerScoreChangedPayload,
4
+ ConsumerScoreChangedPayload, ForceCloseProducerPayload,
5
5
  LogMessageHandler, PayloadOfPublishedMedia,
6
6
  ProducerData,
7
7
  ProducerRequestMaxSpatialLayer,
8
8
  ProducerScoreChangedPayload,
9
- ProducerSetMaxSpatialLayer,
9
+ ProducerSetMaxSpatialLayer, TrackForceClosedPayload,
10
10
  TransportConnectionTimeoutPayload,
11
11
  } from '../../types/common';
12
12
  import Engine from '../index';
13
- import { CLIENT_EVENTS, MEDIASOUP_EVENTS, PEER_EVENTS } from '../../constants/events';
13
+ import {
14
+ CLIENT_EVENTS, INTERNAL_CLIENT_EVENTS, MEDIASOUP_EVENTS, PEER_EVENTS,
15
+ } from '../../constants/events';
14
16
  import Logger from '../Logger';
15
17
  import VideoTrack from '../media/tracks/VideoTrack';
16
18
 
@@ -40,7 +42,7 @@ class MediaSoupEventHandler {
40
42
 
41
43
  connection.on(MEDIASOUP_EVENTS.producerClose, (producer: ProducerData) => {
42
44
  const peer = this.engine.peers.find((item) => item.id === producer.peerId);
43
- if (!peer || peer.isMe) {
45
+ if (!peer) {
44
46
  return;
45
47
  }
46
48
 
@@ -199,6 +201,18 @@ class MediaSoupEventHandler {
199
201
  paused: producer.paused,
200
202
  } as PayloadOfPublishedMedia);
201
203
  });
204
+
205
+ connection.on(MEDIASOUP_EVENTS.producerForceClosed, async ({ label }: ForceCloseProducerPayload) => {
206
+ const track = this.engine.media.getTrack(label);
207
+ if (!track) {
208
+ return;
209
+ }
210
+
211
+ track.stopMediaStreamTrack();
212
+ this.engine.clientEventEmitter.safeEmit(INTERNAL_CLIENT_EVENTS.trackClosed, track);
213
+ this.engine.clientEventEmitter.emit(CLIENT_EVENTS.trackForceClosed, { label } as TrackForceClosedPayload);
214
+ await this.engine.media.deleteTrack(track);
215
+ });
202
216
  }
203
217
 
204
218
  private async handleProducerSetMaxSpatialLayer({
@@ -332,6 +332,7 @@ class Engine {
332
332
  }
333
333
  }
334
334
 
335
+ this.media.setTrack(track);
335
336
  this.logger.debug('createCameraVideoTrack()', { trackParams, track });
336
337
  return track;
337
338
  } catch (error) {
@@ -361,6 +362,7 @@ class Engine {
361
362
  }
362
363
  }
363
364
 
365
+ this.media.setTrack(track);
364
366
  this.logger.debug('createMicrophoneAudioTrack()', { options, track });
365
367
  return track;
366
368
  } catch (error) {
@@ -389,7 +391,7 @@ class Engine {
389
391
  track.setEncoderConfig(videoTrackParams.encoderConfig);
390
392
  const transformParams = Media.getVideoTrackTransformParams(track.mediaStreamTrack);
391
393
  track.setTransformParams(transformParams);
392
-
394
+ this.media.setTrack(track);
393
395
  this.logger.debug('createScreenMediaTrack()', {
394
396
  trackParams: videoTrackParams,
395
397
  transformParams,
@@ -403,6 +405,7 @@ class Engine {
403
405
  track.setEncoderConfig(options.audioEncoderConfig);
404
406
  }
405
407
 
408
+ this.media.setTrack(track);
406
409
  this.logger.debug('createScreenMediaTrack()', {
407
410
  trackParams: options?.audio,
408
411
  encoderConfig: options?.audioEncoderConfig,
@@ -9,6 +9,7 @@ import {
9
9
  CreateVideoTrackParams,
10
10
  LogLevel,
11
11
  Track,
12
+ TrackLabel,
12
13
  TransformParams,
13
14
  } from '../../types/common';
14
15
  import Logger from '../Logger';
@@ -26,7 +27,7 @@ class Media {
26
27
 
27
28
  private device?: Device;
28
29
 
29
- private tracks: Map<string, Track> = new Map();
30
+ private tracks: Map<TrackLabel, Track> = new Map();
30
31
 
31
32
  readonly #logger: Logger;
32
33
 
@@ -67,6 +68,10 @@ class Media {
67
68
  return !!this.#noiseSuppressor;
68
69
  }
69
70
 
71
+ getTrack(label: TrackLabel): Track | undefined {
72
+ return this.tracks.get(label);
73
+ }
74
+
70
75
  async loadDevice(routerRtpCapabilities: RtpCapabilities): Promise<void> {
71
76
  if (!this.isDeviceLoaded) {
72
77
  await this.mediasoupDevice.load({ routerRtpCapabilities });
@@ -111,7 +116,7 @@ class Media {
111
116
  const track = mediaStreamTrack.kind === 'audio'
112
117
  ? new AudioTrack({ ...params, noiseSuppressor: this.#noiseSuppressor })
113
118
  : new VideoTrack(params);
114
- this.tracks.set(track.id, track);
119
+
115
120
  this.#logger.debug('createTrack() track created', {
116
121
  trackId: track.id,
117
122
  kind: track.kind,
@@ -133,11 +138,16 @@ class Media {
133
138
 
134
139
  async deleteTrack(track: Track) {
135
140
  await track.closeProducer();
136
- track.mediaStreamTrack.stop();
137
141
  if ('disableNoiseSuppression' in track) {
138
142
  await track.disableNoiseSuppression();
139
143
  }
140
- this.tracks.delete(track.id);
144
+
145
+ if ('disableBlur' in track) {
146
+ await track.disableBlur();
147
+ }
148
+
149
+ track.stopMediaStreamTrack();
150
+ this.tracks.delete(track.getLabel());
141
151
  this.#logger.debug('deleteTrack() tack deleted', { trackId: track.id, kind: track.kind });
142
152
  }
143
153
 
@@ -155,6 +165,10 @@ class Media {
155
165
  }
156
166
  }
157
167
 
168
+ setTrack(track: Track): void {
169
+ this.tracks.set(track.getLabel(), track);
170
+ }
171
+
158
172
  static getVideoTrackTransformParams(track: MediaStreamTrack): TransformParams {
159
173
  const caps = track.getSettings();
160
174
  return {
@@ -141,11 +141,20 @@ class BaseTrack {
141
141
  return;
142
142
  }
143
143
 
144
- await this.#engine.network.closeRemoteProducer(this.producer.id);
144
+ try {
145
+ await this.#engine.network.closeRemoteProducer(this.producer.id);
146
+ } catch (error) {
147
+ this.logger.warn('closeProducer()', {
148
+ label: this.getLabel(),
149
+ producerId: this.producerId,
150
+ });
151
+ }
152
+
145
153
  this.producer.close();
146
154
  this.producer = undefined;
155
+
147
156
  if (stopTrack) {
148
- this.#mediaStreamTrack.stop();
157
+ this.stopMediaStreamTrack();
149
158
  }
150
159
  }
151
160
 
@@ -167,6 +176,7 @@ class BaseTrack {
167
176
 
168
177
  stopMediaStreamTrack(): void {
169
178
  this.mediaStreamTrack.stop();
179
+ this.mediaStreamTrack.dispatchEvent(new Event('ended'));
170
180
  }
171
181
 
172
182
  private async checkProducerState(): Promise<void> {
@@ -383,7 +393,7 @@ class BaseTrack {
383
393
 
384
394
  await this.cancelProducerCheckState();
385
395
  await this.closeProducer();
386
- this.#mediaStreamTrack.stop();
396
+ this.stopMediaStreamTrack();
387
397
  this.clientEventEmitter.emit(INTERNAL_CLIENT_EVENTS.trackUnproduced, this);
388
398
  this.#closed = true;
389
399
  this.logger.debug('unpublish()', { track: this });
@@ -193,6 +193,10 @@ export type PayloadOfPublishedMedia = {
193
193
  paused: boolean,
194
194
  };
195
195
 
196
+ export type TrackForceClosedPayload = {
197
+ label: TrackLabel,
198
+ };
199
+
196
200
  export type SubscribeOptions = {
197
201
  producerId: string,
198
202
  muted?: boolean,
@@ -383,6 +387,11 @@ export type ChangeProducerStatePayload = {
383
387
  producerId: string,
384
388
  };
385
389
 
390
+ export type ForceCloseProducerPayload = {
391
+ peerId: string,
392
+ label: TrackLabel,
393
+ };
394
+
386
395
  export interface TrackWithEncodings {
387
396
  getCodecOptions(): ProducerCodecOptions;
388
397
  getEncodings(): RtpEncodingParameters[];