livekit-client 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) 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 +1 -0
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +90 -26
  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/api/SignalClient.d.ts.map +1 -1
  10. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  11. package/dist/src/e2ee/types.d.ts +2 -0
  12. package/dist/src/e2ee/types.d.ts.map +1 -1
  13. package/dist/src/index.d.ts +2 -2
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/logger.d.ts +2 -0
  16. package/dist/src/logger.d.ts.map +1 -1
  17. package/dist/src/room/DeviceManager.d.ts.map +1 -1
  18. package/dist/src/room/RTCEngine.d.ts +1 -0
  19. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  20. package/dist/src/room/Room.d.ts.map +1 -1
  21. package/dist/src/room/events.d.ts +2 -1
  22. package/dist/src/room/events.d.ts.map +1 -1
  23. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  24. package/dist/src/room/track/LocalTrack.d.ts +3 -1
  25. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  27. package/dist/src/room/track/options.d.ts +10 -0
  28. package/dist/src/room/track/options.d.ts.map +1 -1
  29. package/dist/src/room/track/types.d.ts +4 -0
  30. package/dist/src/room/track/types.d.ts.map +1 -1
  31. package/dist/ts4.2/src/e2ee/types.d.ts +2 -0
  32. package/dist/ts4.2/src/index.d.ts +2 -2
  33. package/dist/ts4.2/src/logger.d.ts +2 -0
  34. package/dist/ts4.2/src/room/RTCEngine.d.ts +1 -0
  35. package/dist/ts4.2/src/room/events.d.ts +2 -1
  36. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -1
  37. package/dist/ts4.2/src/room/track/options.d.ts +10 -0
  38. package/dist/ts4.2/src/room/track/types.d.ts +4 -0
  39. package/package.json +1 -1
  40. package/src/api/SignalClient.ts +1 -0
  41. package/src/e2ee/E2eeManager.ts +2 -1
  42. package/src/e2ee/types.ts +2 -0
  43. package/src/e2ee/worker/e2ee.worker.ts +1 -0
  44. package/src/index.ts +2 -1
  45. package/src/logger.ts +2 -0
  46. package/src/room/DeviceManager.ts +10 -1
  47. package/src/room/RTCEngine.ts +14 -0
  48. package/src/room/Room.ts +11 -0
  49. package/src/room/events.ts +1 -0
  50. package/src/room/participant/LocalParticipant.ts +4 -4
  51. package/src/room/track/LocalAudioTrack.ts +10 -0
  52. package/src/room/track/LocalTrack.ts +20 -3
  53. package/src/room/track/LocalVideoTrack.ts +10 -0
  54. package/src/room/track/options.ts +41 -8
  55. package/src/room/track/types.ts +5 -0
@@ -491,6 +491,7 @@ export enum EngineEvent {
491
491
  RemoteMute = 'remoteMute',
492
492
  SubscribedQualityUpdate = 'subscribedQualityUpdate',
493
493
  LocalTrackUnpublished = 'localTrackUnpublished',
494
+ Offline = 'offline',
494
495
  }
495
496
 
496
497
  export enum TrackEvent {
@@ -513,6 +513,10 @@ export default class LocalParticipant extends Participant {
513
513
  track: LocalTrack | MediaStreamTrack,
514
514
  options?: TrackPublishOptions,
515
515
  ): Promise<LocalTrackPublication> {
516
+ if (track instanceof LocalAudioTrack) {
517
+ track.setAudioContext(this.audioContext);
518
+ }
519
+
516
520
  await this.reconnectFuture?.promise;
517
521
  if (track instanceof LocalTrack && this.pendingPublishPromises.has(track)) {
518
522
  await this.pendingPublishPromises.get(track);
@@ -566,10 +570,6 @@ export default class LocalParticipant extends Participant {
566
570
  });
567
571
  }
568
572
 
569
- if (track instanceof LocalAudioTrack) {
570
- track.setAudioContext(this.audioContext);
571
- }
572
-
573
573
  // is it already published? if so skip
574
574
  let existingPublication: LocalTrackPublication | undefined;
575
575
  this.trackPublications.forEach((publication) => {
@@ -51,6 +51,11 @@ export default class LocalAudioTrack extends LocalTrack<Track.Kind.Audio> {
51
51
  async mute(): Promise<typeof this> {
52
52
  const unlock = await this.muteLock.lock();
53
53
  try {
54
+ if (this.isMuted) {
55
+ this.log.debug('Track already muted', this.logContext);
56
+ return this;
57
+ }
58
+
54
59
  // disabled special handling as it will cause BT headsets to switch communication modes
55
60
  if (this.source === Track.Source.Microphone && this.stopOnMute && !this.isUserProvided) {
56
61
  this.log.debug('stopping mic track', this.logContext);
@@ -67,6 +72,11 @@ export default class LocalAudioTrack extends LocalTrack<Track.Kind.Audio> {
67
72
  async unmute(): Promise<typeof this> {
68
73
  const unlock = await this.muteLock.lock();
69
74
  try {
75
+ if (!this.isMuted) {
76
+ this.log.debug('Track already unmuted', this.logContext);
77
+ return this;
78
+ }
79
+
70
80
  const deviceHasChanged =
71
81
  this._constraints.deviceId &&
72
82
  this._mediaStreamTrack.getSettings().deviceId !==
@@ -8,6 +8,7 @@ import { Mutex, compareVersions, isMobile, sleep } from '../utils';
8
8
  import { Track, attachToElement, detachTrack } from './Track';
9
9
  import type { VideoCodec } from './options';
10
10
  import type { TrackProcessor } from './processor/types';
11
+ import type { ReplaceTrackOptions } from './types';
11
12
 
12
13
  const defaultDimensionsTimeout = 1000;
13
14
 
@@ -224,18 +225,34 @@ export default abstract class LocalTrack<
224
225
  return this;
225
226
  }
226
227
 
227
- async replaceTrack(track: MediaStreamTrack, userProvidedTrack = true) {
228
+ async replaceTrack(track: MediaStreamTrack, options?: ReplaceTrackOptions): Promise<typeof this>;
229
+ async replaceTrack(track: MediaStreamTrack, userProvidedTrack?: boolean): Promise<typeof this>;
230
+ async replaceTrack(
231
+ track: MediaStreamTrack,
232
+ userProvidedOrOptions: boolean | ReplaceTrackOptions | undefined,
233
+ ) {
228
234
  if (!this.sender) {
229
235
  throw new TrackInvalidError('unable to replace an unpublished track');
230
236
  }
231
237
 
238
+ let userProvidedTrack: boolean | undefined;
239
+ let stopProcessor: boolean | undefined;
240
+
241
+ if (typeof userProvidedOrOptions === 'boolean') {
242
+ userProvidedTrack = userProvidedOrOptions;
243
+ } else if (userProvidedOrOptions !== undefined) {
244
+ userProvidedTrack = userProvidedOrOptions.userProvidedTrack;
245
+ stopProcessor = userProvidedOrOptions.stopProcessor;
246
+ }
247
+
248
+ this.providedByUser = userProvidedTrack ?? true;
249
+
232
250
  this.log.debug('replace MediaStreamTrack', this.logContext);
233
251
  await this.setMediaStreamTrack(track);
234
252
  // this must be synced *after* setting mediaStreamTrack above, since it relies
235
253
  // on the previous state in order to cleanup
236
- this.providedByUser = userProvidedTrack;
237
254
 
238
- if (this.processor) {
255
+ if (stopProcessor && this.processor) {
239
256
  await this.stopProcessor();
240
257
  }
241
258
  return this;
@@ -118,6 +118,11 @@ export default class LocalVideoTrack extends LocalTrack<Track.Kind.Video> {
118
118
  async mute(): Promise<typeof this> {
119
119
  const unlock = await this.muteLock.lock();
120
120
  try {
121
+ if (this.isMuted) {
122
+ this.log.debug('Track already muted', this.logContext);
123
+ return this;
124
+ }
125
+
121
126
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
122
127
  this.log.debug('stopping camera track', this.logContext);
123
128
  // also stop the track, so that camera indicator is turned off
@@ -133,6 +138,11 @@ export default class LocalVideoTrack extends LocalTrack<Track.Kind.Video> {
133
138
  async unmute(): Promise<typeof this> {
134
139
  const unlock = await this.muteLock.lock();
135
140
  try {
141
+ if (!this.isMuted) {
142
+ this.log.debug('Track already unmuted', this.logContext);
143
+ return this;
144
+ }
145
+
136
146
  if (this.source === Track.Source.Camera && !this.isUserProvided) {
137
147
  this.log.debug('reacquiring camera track', this.logContext);
138
148
  await this.restartTrack();
@@ -257,6 +257,15 @@ export interface VideoEncoding {
257
257
  priority?: RTCPriorityType;
258
258
  }
259
259
 
260
+ export interface VideoPresetOptions {
261
+ width: number;
262
+ height: number;
263
+ aspectRatio?: number;
264
+ maxBitrate: number;
265
+ maxFramerate?: number;
266
+ priority?: RTCPriorityType;
267
+ }
268
+
260
269
  export class VideoPreset {
261
270
  encoding: VideoEncoding;
262
271
 
@@ -264,20 +273,44 @@ export class VideoPreset {
264
273
 
265
274
  height: number;
266
275
 
276
+ aspectRatio?: number;
277
+
278
+ constructor(videoPresetOptions: VideoPresetOptions);
267
279
  constructor(
268
280
  width: number,
269
281
  height: number,
270
282
  maxBitrate: number,
271
283
  maxFramerate?: number,
272
284
  priority?: RTCPriorityType,
285
+ );
286
+ constructor(
287
+ widthOrOptions: number | VideoPresetOptions,
288
+ height?: number,
289
+ maxBitrate?: number,
290
+ maxFramerate?: number,
291
+ priority?: RTCPriorityType,
273
292
  ) {
274
- this.width = width;
275
- this.height = height;
276
- this.encoding = {
277
- maxBitrate,
278
- maxFramerate,
279
- priority,
280
- };
293
+ if (typeof widthOrOptions === 'object') {
294
+ this.width = widthOrOptions.width;
295
+ this.height = widthOrOptions.height;
296
+ this.aspectRatio = widthOrOptions.aspectRatio;
297
+ this.encoding = {
298
+ maxBitrate: widthOrOptions.maxBitrate,
299
+ maxFramerate: widthOrOptions.maxFramerate,
300
+ priority: widthOrOptions.priority,
301
+ };
302
+ } else if (height !== undefined && maxBitrate !== undefined) {
303
+ this.width = widthOrOptions;
304
+ this.height = height;
305
+ this.aspectRatio = widthOrOptions / height;
306
+ this.encoding = {
307
+ maxBitrate,
308
+ maxFramerate,
309
+ priority,
310
+ };
311
+ } else {
312
+ throw new TypeError('Unsupported options: provide at least width, height and maxBitrate');
313
+ }
281
314
  }
282
315
 
283
316
  get resolution(): VideoResolution {
@@ -285,7 +318,7 @@ export class VideoPreset {
285
318
  width: this.width,
286
319
  height: this.height,
287
320
  frameRate: this.encoding.maxFramerate,
288
- aspectRatio: this.width / this.height,
321
+ aspectRatio: this.aspectRatio,
289
322
  };
290
323
  }
291
324
  }
@@ -23,3 +23,8 @@ export type AdaptiveStreamSettings = {
23
23
  */
24
24
  pauseVideoInBackground?: boolean;
25
25
  };
26
+
27
+ export interface ReplaceTrackOptions {
28
+ userProvidedTrack?: boolean;
29
+ stopProcessor?: boolean;
30
+ }