livekit-client 1.1.6 → 1.1.9

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.
Files changed (48) hide show
  1. package/README.md +1 -0
  2. package/dist/livekit-client.esm.mjs +535 -120
  3. package/dist/livekit-client.esm.mjs.map +1 -1
  4. package/dist/livekit-client.umd.js +1 -1
  5. package/dist/livekit-client.umd.js.map +1 -1
  6. package/dist/src/api/SignalClient.d.ts +2 -1
  7. package/dist/src/api/SignalClient.d.ts.map +1 -1
  8. package/dist/src/index.d.ts +4 -3
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/proto/livekit_models.d.ts +234 -0
  11. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  12. package/dist/src/proto/livekit_rtc.d.ts +944 -6
  13. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  14. package/dist/src/room/RTCEngine.d.ts +2 -2
  15. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  16. package/dist/src/room/Room.d.ts +2 -2
  17. package/dist/src/room/Room.d.ts.map +1 -1
  18. package/dist/src/room/participant/LocalParticipant.d.ts +3 -1
  19. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  20. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  21. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  22. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  23. package/dist/src/room/track/LocalTrack.d.ts +2 -0
  24. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  25. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  27. package/dist/src/room/track/Track.d.ts +7 -0
  28. package/dist/src/room/track/Track.d.ts.map +1 -1
  29. package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
  30. package/package.json +3 -1
  31. package/src/api/SignalClient.ts +19 -6
  32. package/src/index.ts +6 -2
  33. package/src/proto/livekit_models.ts +179 -4
  34. package/src/proto/livekit_rtc.ts +14 -1
  35. package/src/room/RTCEngine.ts +4 -2
  36. package/src/room/Room.ts +32 -9
  37. package/src/room/participant/LocalParticipant.ts +30 -2
  38. package/src/room/participant/Participant.ts +2 -0
  39. package/src/room/participant/RemoteParticipant.ts +4 -0
  40. package/src/room/track/LocalAudioTrack.ts +16 -12
  41. package/src/room/track/LocalTrack.ts +37 -25
  42. package/src/room/track/LocalVideoTrack.ts +15 -11
  43. package/src/room/track/RemoteTrack.ts +1 -0
  44. package/src/room/track/Track.ts +12 -0
  45. package/src/room/track/TrackPublication.ts +2 -0
  46. package/dist/src/api/RequestQueue.d.ts +0 -13
  47. package/dist/src/api/RequestQueue.d.ts.map +0 -1
  48. package/src/api/RequestQueue.ts +0 -53
@@ -1,9 +1,10 @@
1
+ import Queue from 'async-await-queue';
1
2
  import log from '../../logger';
2
3
  import DeviceManager from '../DeviceManager';
3
4
  import { TrackInvalidError } from '../errors';
4
5
  import { TrackEvent } from '../events';
5
- import { VideoCodec } from './options';
6
6
  import { getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, isMobile } from '../utils';
7
+ import { VideoCodec } from './options';
7
8
  import { attachToElement, detachTrack, Track } from './Track';
8
9
 
9
10
  export default class LocalTrack extends Track {
@@ -21,6 +22,8 @@ export default class LocalTrack extends Track {
21
22
 
22
23
  protected providedByUser: boolean;
23
24
 
25
+ protected muteQueue: Queue;
26
+
24
27
  protected constructor(
25
28
  mediaTrack: MediaStreamTrack,
26
29
  kind: Track.Kind,
@@ -33,6 +36,7 @@ export default class LocalTrack extends Track {
33
36
  this.reacquireTrack = false;
34
37
  this.wasMuted = false;
35
38
  this.providedByUser = userProvidedTrack;
39
+ this.muteQueue = new Queue();
36
40
  }
37
41
 
38
42
  get id(): string {
@@ -101,7 +105,9 @@ export default class LocalTrack extends Track {
101
105
  // on Safari, the old audio track must be stopped before attempting to acquire
102
106
  // the new track, otherwise the new track will stop with
103
107
  // 'A MediaStreamTrack ended due to a capture failure`
104
- this._mediaStreamTrack.stop();
108
+ if (!this.providedByUser) {
109
+ this._mediaStreamTrack.stop();
110
+ }
105
111
 
106
112
  track.addEventListener('ended', this.handleEnded);
107
113
  log.debug('replace MediaStreamTrack');
@@ -170,6 +176,7 @@ export default class LocalTrack extends Track {
170
176
  }
171
177
 
172
178
  protected setTrackMuted(muted: boolean) {
179
+ log.debug(`setting ${this.kind} track ${muted ? 'muted' : 'unmuted'}`);
173
180
  if (this.isMuted === muted) {
174
181
  return;
175
182
  }
@@ -215,31 +222,36 @@ export default class LocalTrack extends Track {
215
222
  };
216
223
 
217
224
  async pauseUpstream() {
218
- if (this._isUpstreamPaused === true) {
219
- return;
220
- }
221
- if (!this.sender) {
222
- log.warn('unable to pause upstream for an unpublished track');
223
- return;
224
- }
225
- this._isUpstreamPaused = true;
226
- this.emit(TrackEvent.UpstreamPaused, this);
227
- const emptyTrack =
228
- this.kind === Track.Kind.Audio ? getEmptyAudioStreamTrack() : getEmptyVideoStreamTrack();
229
- await this.sender.replaceTrack(emptyTrack);
225
+ this.muteQueue.run(async () => {
226
+ if (this._isUpstreamPaused === true) {
227
+ return;
228
+ }
229
+ if (!this.sender) {
230
+ log.warn('unable to pause upstream for an unpublished track');
231
+ return;
232
+ }
233
+
234
+ this._isUpstreamPaused = true;
235
+ this.emit(TrackEvent.UpstreamPaused, this);
236
+ const emptyTrack =
237
+ this.kind === Track.Kind.Audio ? getEmptyAudioStreamTrack() : getEmptyVideoStreamTrack();
238
+ await this.sender.replaceTrack(emptyTrack);
239
+ });
230
240
  }
231
241
 
232
242
  async resumeUpstream() {
233
- if (this._isUpstreamPaused === false) {
234
- return;
235
- }
236
- if (!this.sender) {
237
- log.warn('unable to resume upstream for an unpublished track');
238
- return;
239
- }
240
- this._isUpstreamPaused = false;
241
- this.emit(TrackEvent.UpstreamResumed, this);
242
-
243
- await this.sender.replaceTrack(this._mediaStreamTrack);
243
+ this.muteQueue.run(async () => {
244
+ if (this._isUpstreamPaused === false) {
245
+ return;
246
+ }
247
+ if (!this.sender) {
248
+ log.warn('unable to resume upstream for an unpublished track');
249
+ return;
250
+ }
251
+ this._isUpstreamPaused = false;
252
+ this.emit(TrackEvent.UpstreamResumed, this);
253
+
254
+ await this.sender.replaceTrack(this._mediaStreamTrack);
255
+ });
244
256
  }
245
257
  }
@@ -86,21 +86,25 @@ export default class LocalVideoTrack extends LocalTrack {
86
86
  }
87
87
 
88
88
  async mute(): Promise<LocalVideoTrack> {
89
- if (this.source === Track.Source.Camera) {
90
- log.debug('stopping camera track');
91
- // also stop the track, so that camera indicator is turned off
92
- this._mediaStreamTrack.stop();
93
- }
94
- await super.mute();
89
+ await this.muteQueue.run(async () => {
90
+ if (this.source === Track.Source.Camera && !this.isUserProvided) {
91
+ log.debug('stopping camera track');
92
+ // also stop the track, so that camera indicator is turned off
93
+ this._mediaStreamTrack.stop();
94
+ }
95
+ await super.mute();
96
+ });
95
97
  return this;
96
98
  }
97
99
 
98
100
  async unmute(): Promise<LocalVideoTrack> {
99
- if (this.source === Track.Source.Camera && !this.isUserProvided) {
100
- log.debug('reacquiring camera track');
101
- await this.restartTrack();
102
- }
103
- await super.unmute();
101
+ await this.muteQueue.run(async () => {
102
+ if (this.source === Track.Source.Camera && !this.isUserProvided) {
103
+ log.debug('reacquiring camera track');
104
+ await this.restartTrack();
105
+ }
106
+ await super.unmute();
107
+ });
104
108
  return this;
105
109
  }
106
110
 
@@ -21,6 +21,7 @@ export default abstract class RemoteTrack extends Track {
21
21
  setMuted(muted: boolean) {
22
22
  if (this.isMuted !== muted) {
23
23
  this.isMuted = muted;
24
+ this._mediaStreamTrack.enabled = !muted;
24
25
  this.emit(muted ? TrackEvent.Muted : TrackEvent.Unmuted, this);
25
26
  }
26
27
  }
@@ -37,6 +37,8 @@ export class Track extends (EventEmitter as new () => TypedEventEmitter<TrackEve
37
37
 
38
38
  protected _mediaStreamTrack: MediaStreamTrack;
39
39
 
40
+ protected _mediaStreamID: string;
41
+
40
42
  protected isInBackground: boolean;
41
43
 
42
44
  private backgroundTimeout: ReturnType<typeof setTimeout> | undefined;
@@ -47,6 +49,7 @@ export class Track extends (EventEmitter as new () => TypedEventEmitter<TrackEve
47
49
  super();
48
50
  this.kind = kind;
49
51
  this._mediaStreamTrack = mediaTrack;
52
+ this._mediaStreamID = mediaTrack.id;
50
53
  this.source = Track.Source.Unknown;
51
54
  if (isWeb()) {
52
55
  this.isInBackground = document.visibilityState === 'hidden';
@@ -65,6 +68,15 @@ export class Track extends (EventEmitter as new () => TypedEventEmitter<TrackEve
65
68
  return this._mediaStreamTrack;
66
69
  }
67
70
 
71
+ /**
72
+ * @internal
73
+ * used for keep mediaStream's first id, since it's id might change
74
+ * if we disable/enable a track
75
+ */
76
+ get mediaStreamID(): string {
77
+ return this._mediaStreamID;
78
+ }
79
+
68
80
  /**
69
81
  * creates a new HTMLAudioElement or HTMLVideoElement, attaches to it, and returns it
70
82
  */
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from 'events';
2
+ import log from '../../logger';
2
3
  import { TrackInfo } from '../../proto/livekit_models';
3
4
  import { TrackEvent } from '../events';
4
5
  import LocalAudioTrack from './LocalAudioTrack';
@@ -108,6 +109,7 @@ export class TrackPublication extends EventEmitter {
108
109
  this.simulcasted = info.simulcast;
109
110
  }
110
111
  this.trackInfo = info;
112
+ log.trace('update publication info', { info });
111
113
  }
112
114
  }
113
115
 
@@ -1,13 +0,0 @@
1
- export default class Queue {
2
- private queue;
3
- private running;
4
- constructor();
5
- enqueue(cb: () => void): void;
6
- dequeue(): void;
7
- run(): Promise<void>;
8
- pause(): void;
9
- reset(): void;
10
- isRunning(): boolean;
11
- isEmpty(): boolean;
12
- }
13
- //# sourceMappingURL=RequestQueue.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RequestQueue.d.ts","sourceRoot":"","sources":["../../../src/api/RequestQueue.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,KAAK;IACxB,OAAO,CAAC,KAAK,CAAoB;IAEjC,OAAO,CAAC,OAAO,CAAU;;IAOzB,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI;IAKtB,OAAO;IAMD,GAAG;IAWT,KAAK;IAKL,KAAK;IAML,SAAS;IAIT,OAAO;CAGR"}
@@ -1,53 +0,0 @@
1
- import log from '../logger';
2
-
3
- export default class Queue {
4
- private queue: Array<() => void>;
5
-
6
- private running: boolean;
7
-
8
- constructor() {
9
- this.queue = [];
10
- this.running = false;
11
- }
12
-
13
- enqueue(cb: () => void) {
14
- log.trace('enqueuing request to fire later');
15
- this.queue.push(cb);
16
- }
17
-
18
- dequeue() {
19
- const evt = this.queue.shift();
20
- if (evt) evt();
21
- log.trace('firing request from queue');
22
- }
23
-
24
- async run() {
25
- if (this.running) return;
26
- log.trace('start queue');
27
- this.running = true;
28
- while (this.running && this.queue.length > 0) {
29
- this.dequeue();
30
- }
31
- this.running = false;
32
- log.trace('queue finished');
33
- }
34
-
35
- pause() {
36
- log.trace('pausing queue');
37
- this.running = false;
38
- }
39
-
40
- reset() {
41
- log.trace('resetting queue');
42
- this.running = false;
43
- this.queue = [];
44
- }
45
-
46
- isRunning() {
47
- return this.running;
48
- }
49
-
50
- isEmpty() {
51
- return this.queue.length === 0;
52
- }
53
- }