livekit-client 2.5.0 → 2.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. package/README.md +4 -0
  2. package/dist/livekit-client.e2ee.worker.js +1 -1
  3. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  4. package/dist/livekit-client.e2ee.worker.mjs +4 -2
  5. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  6. package/dist/livekit-client.esm.mjs +517 -269
  7. package/dist/livekit-client.esm.mjs.map +1 -1
  8. package/dist/livekit-client.umd.js +1 -1
  9. package/dist/livekit-client.umd.js.map +1 -1
  10. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  11. package/dist/src/room/PCTransport.d.ts.map +1 -1
  12. package/dist/src/room/PCTransportManager.d.ts +1 -0
  13. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  14. package/dist/src/room/Room.d.ts +8 -3
  15. package/dist/src/room/Room.d.ts.map +1 -1
  16. package/dist/src/room/events.d.ts +10 -2
  17. package/dist/src/room/events.d.ts.map +1 -1
  18. package/dist/src/room/participant/LocalParticipant.d.ts +4 -1
  19. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  20. package/dist/src/room/participant/Participant.d.ts +1 -0
  21. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  22. package/dist/src/room/timers.d.ts +4 -4
  23. package/dist/src/room/timers.d.ts.map +1 -1
  24. package/dist/src/room/track/LocalTrack.d.ts +1 -1
  25. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/create.d.ts +7 -0
  27. package/dist/src/room/track/create.d.ts.map +1 -1
  28. package/dist/src/room/track/options.d.ts +1 -1
  29. package/dist/src/room/types.d.ts +2 -0
  30. package/dist/src/room/types.d.ts.map +1 -1
  31. package/dist/src/room/utils.d.ts +1 -1
  32. package/dist/src/room/utils.d.ts.map +1 -1
  33. package/dist/ts4.2/src/room/PCTransportManager.d.ts +1 -0
  34. package/dist/ts4.2/src/room/Room.d.ts +8 -3
  35. package/dist/ts4.2/src/room/events.d.ts +10 -2
  36. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +4 -1
  37. package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -0
  38. package/dist/ts4.2/src/room/timers.d.ts +4 -4
  39. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +1 -1
  40. package/dist/ts4.2/src/room/track/create.d.ts +7 -0
  41. package/dist/ts4.2/src/room/track/options.d.ts +1 -1
  42. package/dist/ts4.2/src/room/types.d.ts +2 -0
  43. package/dist/ts4.2/src/room/utils.d.ts +1 -1
  44. package/package.json +9 -9
  45. package/src/connectionHelper/checks/Checker.ts +1 -1
  46. package/src/e2ee/worker/FrameCryptor.ts +3 -1
  47. package/src/room/PCTransport.ts +3 -1
  48. package/src/room/PCTransportManager.ts +12 -4
  49. package/src/room/RTCEngine.ts +1 -1
  50. package/src/room/Room.ts +69 -7
  51. package/src/room/events.ts +10 -0
  52. package/src/room/participant/LocalParticipant.ts +126 -84
  53. package/src/room/participant/Participant.ts +1 -0
  54. package/src/room/timers.ts +15 -6
  55. package/src/room/track/LocalTrack.ts +4 -2
  56. package/src/room/track/LocalVideoTrack.test.ts +60 -0
  57. package/src/room/track/LocalVideoTrack.ts +1 -1
  58. package/src/room/track/create.ts +27 -8
  59. package/src/room/track/options.ts +1 -1
  60. package/src/room/types.ts +2 -0
  61. package/src/room/utils.ts +10 -0
@@ -4,13 +4,22 @@
4
4
  * that the timer fires on time.
5
5
  */
6
6
  export default class CriticalTimers {
7
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
8
- static setTimeout = (...args: Parameters<typeof setTimeout>) => setTimeout(...args);
7
+ static setTimeout: (...args: Parameters<typeof setTimeout>) => ReturnType<typeof setTimeout> = (
8
+ ...args: Parameters<typeof setTimeout>
9
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
10
+ ) => setTimeout(...args);
9
11
 
10
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
11
- static setInterval = (...args: Parameters<typeof setInterval>) => setInterval(...args);
12
+ static setInterval: (...args: Parameters<typeof setInterval>) => ReturnType<typeof setInterval> =
13
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
14
+ (...args: Parameters<typeof setInterval>) => setInterval(...args);
12
15
 
13
- static clearTimeout = (...args: Parameters<typeof clearTimeout>) => clearTimeout(...args);
16
+ static clearTimeout: (
17
+ ...args: Parameters<typeof clearTimeout>
18
+ ) => ReturnType<typeof clearTimeout> = (...args: Parameters<typeof clearTimeout>) =>
19
+ clearTimeout(...args);
14
20
 
15
- static clearInterval = (...args: Parameters<typeof clearInterval>) => clearInterval(...args);
21
+ static clearInterval: (
22
+ ...args: Parameters<typeof clearInterval>
23
+ ) => ReturnType<typeof clearInterval> = (...args: Parameters<typeof clearInterval>) =>
24
+ clearInterval(...args);
16
25
  }
@@ -215,7 +215,7 @@ export default abstract class LocalTrack<
215
215
  /**
216
216
  * @returns DeviceID of the device that is currently being used for this track
217
217
  */
218
- async getDeviceId(): Promise<string | undefined> {
218
+ async getDeviceId(normalize = true): Promise<string | undefined> {
219
219
  // screen share doesn't have a usable device id
220
220
  if (this.source === Track.Source.ScreenShare) {
221
221
  return;
@@ -223,7 +223,9 @@ export default abstract class LocalTrack<
223
223
  const { deviceId, groupId } = this._mediaStreamTrack.getSettings();
224
224
  const kind = this.kind === Track.Kind.Audio ? 'audioinput' : 'videoinput';
225
225
 
226
- return DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId);
226
+ return normalize
227
+ ? DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId)
228
+ : deviceId;
227
229
  }
228
230
 
229
231
  async mute() {
@@ -47,6 +47,66 @@ describe('videoLayersFromEncodings', () => {
47
47
  expect(layers[2].height).toBe(720);
48
48
  });
49
49
 
50
+ it('returns qualities starting from lowest for SVC', () => {
51
+ const layers = videoLayersFromEncodings(
52
+ 1280,
53
+ 720,
54
+ [
55
+ {
56
+ /** @ts-ignore */
57
+ scalabilityMode: 'L2T2',
58
+ },
59
+ ],
60
+ true,
61
+ );
62
+
63
+ expect(layers).toHaveLength(2);
64
+ expect(layers[0].quality).toBe(VideoQuality.MEDIUM);
65
+ expect(layers[0].width).toBe(1280);
66
+ expect(layers[1].quality).toBe(VideoQuality.LOW);
67
+ expect(layers[1].width).toBe(640);
68
+ });
69
+
70
+ it('returns qualities starting from lowest for SVC (three layers)', () => {
71
+ const layers = videoLayersFromEncodings(
72
+ 1280,
73
+ 720,
74
+ [
75
+ {
76
+ /** @ts-ignore */
77
+ scalabilityMode: 'L3T3',
78
+ },
79
+ ],
80
+ true,
81
+ );
82
+
83
+ expect(layers).toHaveLength(3);
84
+ expect(layers[0].quality).toBe(VideoQuality.HIGH);
85
+ expect(layers[0].width).toBe(1280);
86
+ expect(layers[1].quality).toBe(VideoQuality.MEDIUM);
87
+ expect(layers[1].width).toBe(640);
88
+ expect(layers[2].quality).toBe(VideoQuality.LOW);
89
+ expect(layers[2].width).toBe(320);
90
+ });
91
+
92
+ it('returns qualities starting from lowest for SVC (single layer)', () => {
93
+ const layers = videoLayersFromEncodings(
94
+ 1280,
95
+ 720,
96
+ [
97
+ {
98
+ /** @ts-ignore */
99
+ scalabilityMode: 'L1T2',
100
+ },
101
+ ],
102
+ true,
103
+ );
104
+
105
+ expect(layers).toHaveLength(1);
106
+ expect(layers[0].quality).toBe(VideoQuality.LOW);
107
+ expect(layers[0].width).toBe(1280);
108
+ });
109
+
50
110
  it('handles portrait', () => {
51
111
  const layers = videoLayersFromEncodings(720, 1280, [
52
112
  {
@@ -607,7 +607,7 @@ export function videoLayersFromEncodings(
607
607
  for (let i = 0; i < sm.spatial; i += 1) {
608
608
  layers.push(
609
609
  new VideoLayer({
610
- quality: VideoQuality.HIGH - i,
610
+ quality: Math.min(VideoQuality.HIGH, sm.spatial - 1) - i,
611
611
  width: Math.ceil(width / resRatio ** i),
612
612
  height: Math.ceil(height / resRatio ** i),
613
613
  bitrate: encodings[0].maxBitrate
@@ -14,13 +14,32 @@ import type {
14
14
  VideoCaptureOptions,
15
15
  } from './options';
16
16
  import { ScreenSharePresets } from './options';
17
- import type { TrackProcessor } from './processor/types';
17
+ import type {
18
+ AudioProcessorOptions,
19
+ TrackProcessor,
20
+ VideoProcessorOptions,
21
+ } from './processor/types';
18
22
  import {
19
23
  constraintsForOptions,
20
24
  mergeDefaultOptions,
21
25
  screenCaptureToDisplayMediaStreamOptions,
22
26
  } from './utils';
23
27
 
28
+ /** @internal */
29
+ export function extractProcessorsFromOptions(options: CreateLocalTracksOptions) {
30
+ let audioProcessor: TrackProcessor<Track.Kind.Audio, AudioProcessorOptions> | undefined;
31
+ let videoProcessor: TrackProcessor<Track.Kind.Video, VideoProcessorOptions> | undefined;
32
+
33
+ if (typeof options.audio === 'object' && options.audio.processor) {
34
+ audioProcessor = options.audio.processor;
35
+ }
36
+ if (typeof options.video === 'object' && options.video.processor) {
37
+ videoProcessor = options.video.processor;
38
+ }
39
+
40
+ return { audioProcessor, videoProcessor };
41
+ }
42
+
24
43
  /**
25
44
  * Creates a local video and audio track at the same time. When acquiring both
26
45
  * audio and video tracks together, it'll display a single permission prompt to
@@ -35,6 +54,7 @@ export async function createLocalTracks(
35
54
  options.audio ??= true;
36
55
  options.video ??= true;
37
56
 
57
+ const { audioProcessor, videoProcessor } = extractProcessorsFromOptions(options);
38
58
  const opts = mergeDefaultOptions(options, audioDefaults, videoDefaults);
39
59
  const constraints = constraintsForOptions(opts);
40
60
 
@@ -55,7 +75,7 @@ export async function createLocalTracks(
55
75
  return Promise.all(
56
76
  stream.getTracks().map(async (mediaStreamTrack) => {
57
77
  const isAudio = mediaStreamTrack.kind === 'audio';
58
- let trackOptions = isAudio ? options!.audio : options!.video;
78
+ let trackOptions = isAudio ? opts!.audio : opts!.video;
59
79
  if (typeof trackOptions === 'boolean' || !trackOptions) {
60
80
  trackOptions = {};
61
81
  }
@@ -80,13 +100,12 @@ export async function createLocalTracks(
80
100
  track.source = Track.Source.Microphone;
81
101
  }
82
102
  track.mediaStream = stream;
83
- if (trackOptions.processor) {
84
- if (track instanceof LocalAudioTrack) {
85
- await track.setProcessor(trackOptions.processor as TrackProcessor<Track.Kind.Audio>);
86
- } else if (track instanceof LocalVideoTrack) {
87
- await track.setProcessor(trackOptions.processor as TrackProcessor<Track.Kind.Video>);
88
- }
103
+ if (track instanceof LocalAudioTrack && audioProcessor) {
104
+ await track.setProcessor(audioProcessor);
105
+ } else if (track instanceof LocalVideoTrack && videoProcessor) {
106
+ await track.setProcessor(videoProcessor);
89
107
  }
108
+
90
109
  return track;
91
110
  }),
92
111
  );
@@ -64,7 +64,7 @@ export interface TrackPublishDefaults {
64
64
  simulcast?: boolean;
65
65
 
66
66
  /**
67
- * scalability mode for svc codecs, defaults to 'L3T3'.
67
+ * scalability mode for svc codecs, defaults to 'L3T3_KEY'.
68
68
  * for svc codecs, simulcast is disabled.
69
69
  */
70
70
  scalabilityMode?: ScalabilityMode;
package/src/room/types.ts CHANGED
@@ -65,4 +65,6 @@ export interface TranscriptionSegment {
65
65
  startTime: number;
66
66
  endTime: number;
67
67
  final: boolean;
68
+ firstReceivedTime: number;
69
+ lastReceivedTime: number;
68
70
  }
package/src/room/utils.ts CHANGED
@@ -532,8 +532,16 @@ export function toHttpUrl(url: string): string {
532
532
 
533
533
  export function extractTranscriptionSegments(
534
534
  transcription: TranscriptionModel,
535
+ firstReceivedTimesMap: Map<string, number>,
535
536
  ): TranscriptionSegment[] {
536
537
  return transcription.segments.map(({ id, text, language, startTime, endTime, final }) => {
538
+ const firstReceivedTime = firstReceivedTimesMap.get(id) ?? Date.now();
539
+ const lastReceivedTime = Date.now();
540
+ if (final) {
541
+ firstReceivedTimesMap.delete(id);
542
+ } else {
543
+ firstReceivedTimesMap.set(id, firstReceivedTime);
544
+ }
537
545
  return {
538
546
  id,
539
547
  text,
@@ -541,6 +549,8 @@ export function extractTranscriptionSegments(
541
549
  endTime: Number.parseInt(endTime.toString()),
542
550
  final,
543
551
  language,
552
+ firstReceivedTime,
553
+ lastReceivedTime,
544
554
  };
545
555
  });
546
556
  }