livekit-client 2.0.1 → 2.0.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.
Files changed (49) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +4 -4
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +29 -21
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/room/Room.d.ts.map +1 -1
  10. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  11. package/dist/src/room/track/LocalAudioTrack.d.ts +8 -7
  12. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  13. package/dist/src/room/track/LocalTrack.d.ts +10 -9
  14. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  15. package/dist/src/room/track/LocalTrackPublication.d.ts +2 -2
  16. package/dist/src/room/track/LocalVideoTrack.d.ts +3 -3
  17. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  18. package/dist/src/room/track/RemoteAudioTrack.d.ts +2 -1
  19. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  20. package/dist/src/room/track/RemoteTrack.d.ts +2 -2
  21. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  22. package/dist/src/room/track/RemoteVideoTrack.d.ts +2 -1
  23. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  24. package/dist/src/room/track/Track.d.ts +3 -3
  25. package/dist/src/room/track/Track.d.ts.map +1 -1
  26. package/dist/src/room/track/processor/types.d.ts +4 -0
  27. package/dist/src/room/track/processor/types.d.ts.map +1 -1
  28. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +8 -7
  29. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +10 -9
  30. package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +2 -2
  31. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +3 -3
  32. package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +2 -1
  33. package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +2 -2
  34. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +2 -1
  35. package/dist/ts4.2/src/room/track/Track.d.ts +3 -3
  36. package/dist/ts4.2/src/room/track/processor/types.d.ts +4 -0
  37. package/package.json +1 -1
  38. package/src/api/SignalClient.ts +1 -1
  39. package/src/e2ee/worker/e2ee.worker.ts +8 -4
  40. package/src/room/Room.ts +3 -0
  41. package/src/room/participant/LocalParticipant.ts +0 -1
  42. package/src/room/track/LocalAudioTrack.ts +8 -11
  43. package/src/room/track/LocalTrack.ts +36 -23
  44. package/src/room/track/LocalVideoTrack.ts +3 -3
  45. package/src/room/track/RemoteAudioTrack.ts +1 -1
  46. package/src/room/track/RemoteTrack.ts +4 -2
  47. package/src/room/track/RemoteVideoTrack.ts +1 -1
  48. package/src/room/track/Track.ts +5 -3
  49. package/src/room/track/processor/types.ts +4 -0
package/src/room/Room.ts CHANGED
@@ -1776,7 +1776,10 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
1776
1776
  };
1777
1777
 
1778
1778
  private onLocalTrackPublished = async (pub: LocalTrackPublication) => {
1779
+ pub.track?.getProcessor()?.onPublish?.(this);
1780
+
1779
1781
  this.emit(RoomEvent.LocalTrackPublished, pub, this.localParticipant);
1782
+
1780
1783
  if (pub.track instanceof LocalAudioTrack) {
1781
1784
  const trackIsSilent = await pub.track.checkForSilence();
1782
1785
  if (trackIsSilent) {
@@ -888,7 +888,6 @@ export default class LocalParticipant extends Participant {
888
888
  }
889
889
 
890
890
  this.addTrackPublication(publication);
891
-
892
891
  // send event for publication
893
892
  this.emit(ParticipantEvent.LocalTrackPublished, publication);
894
893
  return publication;
@@ -6,17 +6,17 @@ import { isWeb, unwrapConstraint } from '../utils';
6
6
  import LocalTrack from './LocalTrack';
7
7
  import { Track } from './Track';
8
8
  import type { AudioCaptureOptions } from './options';
9
- import type { TrackProcessor } from './processor/types';
9
+ import type { AudioProcessorOptions, TrackProcessor } from './processor/types';
10
10
  import { constraintsForOptions, detectSilence } from './utils';
11
11
 
12
- export default class LocalAudioTrack extends LocalTrack {
12
+ export default class LocalAudioTrack extends LocalTrack<Track.Kind.Audio> {
13
13
  /** @internal */
14
14
  stopOnMute: boolean = false;
15
15
 
16
- private audioContext?: AudioContext;
17
-
18
16
  private prevStats?: AudioSenderStats;
19
17
 
18
+ protected processor?: TrackProcessor<Track.Kind.Audio, AudioProcessorOptions> | undefined;
19
+
20
20
  /**
21
21
  *
22
22
  * @param mediaTrack
@@ -48,7 +48,7 @@ export default class LocalAudioTrack extends LocalTrack {
48
48
  );
49
49
  }
50
50
 
51
- async mute(): Promise<LocalAudioTrack> {
51
+ async mute(): Promise<typeof this> {
52
52
  const unlock = await this.muteLock.lock();
53
53
  try {
54
54
  // disabled special handling as it will cause BT headsets to switch communication modes
@@ -64,7 +64,7 @@ export default class LocalAudioTrack extends LocalTrack {
64
64
  }
65
65
  }
66
66
 
67
- async unmute(): Promise<LocalAudioTrack> {
67
+ async unmute(): Promise<typeof this> {
68
68
  const unlock = await this.muteLock.lock();
69
69
  try {
70
70
  const deviceHasChanged =
@@ -99,7 +99,7 @@ export default class LocalAudioTrack extends LocalTrack {
99
99
  await this.restart(constraints);
100
100
  }
101
101
 
102
- protected async restart(constraints?: MediaTrackConstraints): Promise<LocalTrack> {
102
+ protected async restart(constraints?: MediaTrackConstraints): Promise<typeof this> {
103
103
  const track = await super.restart(constraints);
104
104
  this.checkForSilence();
105
105
  return track;
@@ -139,7 +139,7 @@ export default class LocalAudioTrack extends LocalTrack {
139
139
  this.prevStats = stats;
140
140
  };
141
141
 
142
- async setProcessor(processor: TrackProcessor<this['kind']>) {
142
+ async setProcessor(processor: TrackProcessor<Track.Kind.Audio, AudioProcessorOptions>) {
143
143
  const unlock = await this.processorLock.lock();
144
144
  try {
145
145
  if (!this.audioContext) {
@@ -150,9 +150,6 @@ export default class LocalAudioTrack extends LocalTrack {
150
150
  if (this.processor) {
151
151
  await this.stopProcessor();
152
152
  }
153
- if (this.kind === 'unknown') {
154
- throw TypeError('cannot set processor on track of unknown kind');
155
- }
156
153
 
157
154
  const processorOptions = {
158
155
  kind: this.kind,
@@ -11,7 +11,9 @@ import type { TrackProcessor } from './processor/types';
11
11
 
12
12
  const defaultDimensionsTimeout = 1000;
13
13
 
14
- export default abstract class LocalTrack extends Track {
14
+ export default abstract class LocalTrack<
15
+ TrackKind extends Track.Kind = Track.Kind,
16
+ > extends Track<TrackKind> {
15
17
  /** @internal */
16
18
  sender?: RTCRtpSender;
17
19
 
@@ -34,10 +36,12 @@ export default abstract class LocalTrack extends Track {
34
36
 
35
37
  protected processorElement?: HTMLMediaElement;
36
38
 
37
- protected processor?: TrackProcessor<this['kind']>;
39
+ protected processor?: TrackProcessor<TrackKind, any>;
38
40
 
39
41
  protected processorLock: Mutex;
40
42
 
43
+ protected audioContext?: AudioContext;
44
+
41
45
  /**
42
46
  *
43
47
  * @param mediaTrack
@@ -47,7 +51,7 @@ export default abstract class LocalTrack extends Track {
47
51
  */
48
52
  protected constructor(
49
53
  mediaTrack: MediaStreamTrack,
50
- kind: Track.Kind,
54
+ kind: TrackKind,
51
55
  constraints?: MediaTrackConstraints,
52
56
  userProvidedTrack = false,
53
57
  loggerOptions?: LoggerOptions,
@@ -128,21 +132,28 @@ export default abstract class LocalTrack extends Track {
128
132
  this._constraints = newTrack.getConstraints();
129
133
  }
130
134
  let processedTrack: MediaStreamTrack | undefined;
131
- if (this.processor && newTrack && this.processorElement) {
132
- this.log.debug('restarting processor', this.logContext);
133
- if (this.kind === 'unknown') {
134
- throw TypeError('cannot set processor on track of unknown kind');
135
- }
135
+ if (this.processor && newTrack) {
136
+ const unlock = await this.processorLock.lock();
137
+ try {
138
+ this.log.debug('restarting processor', this.logContext);
139
+ if (this.kind === 'unknown') {
140
+ throw TypeError('cannot set processor on track of unknown kind');
141
+ }
136
142
 
137
- attachToElement(newTrack, this.processorElement);
138
- // ensure the processorElement itself stays muted
139
- this.processorElement.muted = true;
140
- await this.processor.restart({
141
- track: newTrack,
142
- kind: this.kind,
143
- element: this.processorElement,
144
- });
145
- processedTrack = this.processor.processedTrack;
143
+ if (this.processorElement) {
144
+ attachToElement(newTrack, this.processorElement);
145
+ // ensure the processorElement itself stays muted
146
+ this.processorElement.muted = true;
147
+ }
148
+ await this.processor.restart({
149
+ track: newTrack,
150
+ kind: this.kind,
151
+ element: this.processorElement,
152
+ });
153
+ processedTrack = this.processor.processedTrack;
154
+ } finally {
155
+ unlock();
156
+ }
146
157
  }
147
158
  if (this.sender) {
148
159
  await this.sender.replaceTrack(processedTrack ?? newTrack);
@@ -200,17 +211,17 @@ export default abstract class LocalTrack extends Track {
200
211
  return DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId);
201
212
  }
202
213
 
203
- async mute(): Promise<LocalTrack> {
214
+ async mute() {
204
215
  this.setTrackMuted(true);
205
216
  return this;
206
217
  }
207
218
 
208
- async unmute(): Promise<LocalTrack> {
219
+ async unmute() {
209
220
  this.setTrackMuted(false);
210
221
  return this;
211
222
  }
212
223
 
213
- async replaceTrack(track: MediaStreamTrack, userProvidedTrack = true): Promise<LocalTrack> {
224
+ async replaceTrack(track: MediaStreamTrack, userProvidedTrack = true) {
214
225
  if (!this.sender) {
215
226
  throw new TrackInvalidError('unable to replace an unpublished track');
216
227
  }
@@ -227,7 +238,7 @@ export default abstract class LocalTrack extends Track {
227
238
  return this;
228
239
  }
229
240
 
230
- protected async restart(constraints?: MediaTrackConstraints): Promise<LocalTrack> {
241
+ protected async restart(constraints?: MediaTrackConstraints) {
231
242
  if (!constraints) {
232
243
  constraints = this._constraints;
233
244
  }
@@ -408,7 +419,7 @@ export default abstract class LocalTrack extends Track {
408
419
  * @param showProcessedStreamLocally
409
420
  * @returns
410
421
  */
411
- async setProcessor(processor: TrackProcessor<this['kind']>, showProcessedStreamLocally = true) {
422
+ async setProcessor(processor: TrackProcessor<TrackKind>, showProcessedStreamLocally = true) {
412
423
  const unlock = await this.processorLock.lock();
413
424
  try {
414
425
  this.log.debug('setting up processor', this.logContext);
@@ -418,7 +429,8 @@ export default abstract class LocalTrack extends Track {
418
429
  if (this.kind === 'unknown') {
419
430
  throw TypeError('cannot set processor on track of unknown kind');
420
431
  }
421
- this.processorElement = this.processorElement ?? document.createElement(this.kind);
432
+ this.processorElement =
433
+ this.processorElement ?? (document.createElement(this.kind) as HTMLMediaElement);
422
434
 
423
435
  attachToElement(this._mediaStreamTrack, this.processorElement);
424
436
  this.processorElement.muted = true;
@@ -433,6 +445,7 @@ export default abstract class LocalTrack extends Track {
433
445
  kind: this.kind,
434
446
  track: this._mediaStreamTrack,
435
447
  element: this.processorElement,
448
+ audioContext: this.audioContext,
436
449
  };
437
450
 
438
451
  await processor.init(processorOptions);
@@ -30,7 +30,7 @@ export class SimulcastTrackInfo {
30
30
 
31
31
  const refreshSubscribedCodecAfterNewCodec = 5000;
32
32
 
33
- export default class LocalVideoTrack extends LocalTrack {
33
+ export default class LocalVideoTrack extends LocalTrack<Track.Kind.Video> {
34
34
  /* @internal */
35
35
  signalClient?: SignalClient;
36
36
 
@@ -115,7 +115,7 @@ export default class LocalVideoTrack extends LocalTrack {
115
115
  }
116
116
  }
117
117
 
118
- async mute(): Promise<LocalVideoTrack> {
118
+ async mute(): Promise<typeof this> {
119
119
  const unlock = await this.muteLock.lock();
120
120
  try {
121
121
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
@@ -130,7 +130,7 @@ export default class LocalVideoTrack extends LocalTrack {
130
130
  }
131
131
  }
132
132
 
133
- async unmute(): Promise<LocalVideoTrack> {
133
+ async unmute(): Promise<typeof this> {
134
134
  const unlock = await this.muteLock.lock();
135
135
  try {
136
136
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
@@ -7,7 +7,7 @@ import RemoteTrack from './RemoteTrack';
7
7
  import { Track } from './Track';
8
8
  import type { AudioOutputOptions } from './options';
9
9
 
10
- export default class RemoteAudioTrack extends RemoteTrack {
10
+ export default class RemoteAudioTrack extends RemoteTrack<Track.Kind.Audio> {
11
11
  private prevStats?: AudioReceiverStats;
12
12
 
13
13
  private elementVolume: number | undefined;
@@ -3,14 +3,16 @@ import { monitorFrequency } from '../stats';
3
3
  import type { LoggerOptions } from '../types';
4
4
  import { Track } from './Track';
5
5
 
6
- export default abstract class RemoteTrack extends Track {
6
+ export default abstract class RemoteTrack<
7
+ TrackKind extends Track.Kind = Track.Kind,
8
+ > extends Track<TrackKind> {
7
9
  /** @internal */
8
10
  receiver?: RTCRtpReceiver;
9
11
 
10
12
  constructor(
11
13
  mediaTrack: MediaStreamTrack,
12
14
  sid: string,
13
- kind: Track.Kind,
15
+ kind: TrackKind,
14
16
  receiver?: RTCRtpReceiver,
15
17
  loggerOptions?: LoggerOptions,
16
18
  ) {
@@ -12,7 +12,7 @@ import type { AdaptiveStreamSettings } from './types';
12
12
 
13
13
  const REACTION_DELAY = 100;
14
14
 
15
- export default class RemoteVideoTrack extends RemoteTrack {
15
+ export default class RemoteVideoTrack extends RemoteTrack<Track.Kind.Video> {
16
16
  private prevStats?: VideoReceiverStats;
17
17
 
18
18
  private elementInfos: ElementInfo[] = [];
@@ -24,8 +24,10 @@ export enum VideoQuality {
24
24
  MEDIUM = ProtoQuality.MEDIUM,
25
25
  HIGH = ProtoQuality.HIGH,
26
26
  }
27
- export abstract class Track extends (EventEmitter as new () => TypedEventEmitter<TrackEventCallbacks>) {
28
- kind: Track.Kind;
27
+ export abstract class Track<
28
+ TrackKind extends Track.Kind = Track.Kind,
29
+ > extends (EventEmitter as new () => TypedEventEmitter<TrackEventCallbacks>) {
30
+ readonly kind: TrackKind;
29
31
 
30
32
  attachedElements: HTMLMediaElement[] = [];
31
33
 
@@ -67,7 +69,7 @@ export abstract class Track extends (EventEmitter as new () => TypedEventEmitter
67
69
 
68
70
  protected constructor(
69
71
  mediaTrack: MediaStreamTrack,
70
- kind: Track.Kind,
72
+ kind: TrackKind,
71
73
  loggerOptions: LoggerOptions = {},
72
74
  ) {
73
75
  super();
@@ -1,3 +1,4 @@
1
+ import type Room from '../../Room';
1
2
  import type { Track } from '../Track';
2
3
 
3
4
  /**
@@ -7,6 +8,7 @@ export type ProcessorOptions<T extends Track.Kind> = {
7
8
  kind: T;
8
9
  track: MediaStreamTrack;
9
10
  element?: HTMLMediaElement;
11
+ audioContext?: AudioContext;
10
12
  };
11
13
 
12
14
  /**
@@ -33,4 +35,6 @@ export interface TrackProcessor<
33
35
  restart: (opts: U) => Promise<void>;
34
36
  destroy: () => Promise<void>;
35
37
  processedTrack?: MediaStreamTrack;
38
+ onPublish?: (room: Room) => Promise<void>;
39
+ onUnpublish?: () => Promise<void>;
36
40
  }