livekit-client 2.13.4 → 2.13.6

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 (52) 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 +11 -3
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +329 -76
  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 +5 -5
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/connectionHelper/checks/publishVideo.d.ts.map +1 -1
  12. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  13. package/dist/src/e2ee/types.d.ts +1 -0
  14. package/dist/src/e2ee/types.d.ts.map +1 -1
  15. package/dist/src/e2ee/worker/FrameCryptor.d.ts +2 -1
  16. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  17. package/dist/src/room/PCTransport.d.ts +3 -2
  18. package/dist/src/room/PCTransport.d.ts.map +1 -1
  19. package/dist/src/room/PCTransportManager.d.ts +3 -3
  20. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  21. package/dist/src/room/RTCEngine.d.ts +8 -0
  22. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  23. package/dist/src/room/Room.d.ts +1 -1
  24. package/dist/src/room/Room.d.ts.map +1 -1
  25. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  26. package/dist/src/utils/dataPacketBuffer.d.ts +15 -0
  27. package/dist/src/utils/dataPacketBuffer.d.ts.map +1 -0
  28. package/dist/src/utils/ttlmap.d.ts +20 -0
  29. package/dist/src/utils/ttlmap.d.ts.map +1 -0
  30. package/dist/ts4.2/src/api/SignalClient.d.ts +5 -5
  31. package/dist/ts4.2/src/e2ee/types.d.ts +1 -0
  32. package/dist/ts4.2/src/e2ee/worker/FrameCryptor.d.ts +2 -1
  33. package/dist/ts4.2/src/room/PCTransport.d.ts +3 -2
  34. package/dist/ts4.2/src/room/PCTransportManager.d.ts +3 -3
  35. package/dist/ts4.2/src/room/RTCEngine.d.ts +8 -0
  36. package/dist/ts4.2/src/room/Room.d.ts +1 -1
  37. package/dist/ts4.2/src/utils/dataPacketBuffer.d.ts +15 -0
  38. package/dist/ts4.2/src/utils/ttlmap.d.ts +20 -0
  39. package/package.json +8 -8
  40. package/src/api/SignalClient.ts +12 -10
  41. package/src/connectionHelper/checks/publishVideo.ts +1 -0
  42. package/src/e2ee/E2eeManager.ts +3 -0
  43. package/src/e2ee/types.ts +1 -0
  44. package/src/e2ee/worker/FrameCryptor.ts +15 -0
  45. package/src/e2ee/worker/e2ee.worker.ts +2 -0
  46. package/src/room/PCTransport.ts +30 -4
  47. package/src/room/PCTransportManager.ts +10 -7
  48. package/src/room/RTCEngine.ts +78 -9
  49. package/src/room/Room.ts +11 -11
  50. package/src/room/track/LocalVideoTrack.ts +14 -15
  51. package/src/utils/dataPacketBuffer.ts +52 -0
  52. package/src/utils/ttlmap.ts +96 -0
@@ -7,12 +7,11 @@ import {
7
7
  } from '@livekit/protocol';
8
8
  import type { SignalClient } from '../../api/SignalClient';
9
9
  import type { StructuredLogger } from '../../logger';
10
- import { getBrowser } from '../../utils/browserParser';
11
10
  import { ScalabilityMode } from '../participant/publishUtils';
12
11
  import type { VideoSenderStats } from '../stats';
13
12
  import { computeBitrate, monitorFrequency } from '../stats';
14
13
  import type { LoggerOptions } from '../types';
15
- import { compareVersions, isFireFox, isMobile, isSVCCodec, isWeb } from '../utils';
14
+ import { isFireFox, isMobile, isSVCCodec, isWeb } from '../utils';
16
15
  import LocalTrack from './LocalTrack';
17
16
  import { Track, VideoQuality } from './Track';
18
17
  import type { VideoCaptureOptions, VideoCodec } from './options';
@@ -459,15 +458,18 @@ async function setPublishingLayersForSender(
459
458
  }
460
459
 
461
460
  let hasChanged = false;
462
- const browser = getBrowser();
463
- const closableSpatial =
464
- browser?.name === 'Chrome' && compareVersions(browser?.version, '133') > 0;
461
+
462
+ /* disable closable spatial layer as it has video blur / frozen issue with current server / client
463
+ 1. chrome 113: when switching to up layer with scalability Mode change, it will generate a
464
+ low resolution frame and recover very quickly, but noticable
465
+ 2. livekit sfu: additional pli request cause video frozen for a few frames, also noticable */
466
+ const closableSpatial = false;
465
467
  /* @ts-ignore */
466
468
  if (closableSpatial && encodings[0].scalabilityMode) {
467
469
  // svc dynacast encodings
468
470
  const encoding = encodings[0];
469
471
  /* @ts-ignore */
470
- const mode = new ScalabilityMode(encoding.scalabilityMode);
472
+ // const mode = new ScalabilityMode(encoding.scalabilityMode);
471
473
  let maxQuality = ProtoVideoQuality.OFF;
472
474
  qualities.forEach((q) => {
473
475
  if (q.enabled && (maxQuality === ProtoVideoQuality.OFF || q.quality > maxQuality)) {
@@ -480,25 +482,22 @@ async function setPublishingLayersForSender(
480
482
  encoding.active = false;
481
483
  hasChanged = true;
482
484
  }
483
- } else if (!encoding.active || mode.spatial !== maxQuality + 1) {
485
+ } else if (!encoding.active /* || mode.spatial !== maxQuality + 1*/) {
484
486
  hasChanged = true;
485
487
  encoding.active = true;
486
- /* @ts-ignore */
487
- const originalMode = new ScalabilityMode(senderEncodings[0].scalabilityMode);
488
+ /*
489
+ @ts-ignore
490
+ const originalMode = new ScalabilityMode(senderEncodings[0].scalabilityMode)
488
491
  mode.spatial = maxQuality + 1;
489
492
  mode.suffix = originalMode.suffix;
490
493
  if (mode.spatial === 1) {
491
494
  // no suffix for L1Tx
492
495
  mode.suffix = undefined;
493
496
  }
494
- /* @ts-ignore */
497
+ @ts-ignore
495
498
  encoding.scalabilityMode = mode.toString();
496
499
  encoding.scaleResolutionDownBy = 2 ** (2 - maxQuality);
497
- if (senderEncodings[0].maxBitrate) {
498
- encoding.maxBitrate =
499
- senderEncodings[0].maxBitrate /
500
- (encoding.scaleResolutionDownBy * encoding.scaleResolutionDownBy);
501
- }
500
+ */
502
501
  }
503
502
  } else {
504
503
  if (isSVC) {
@@ -0,0 +1,52 @@
1
+ export interface DataPacketItem {
2
+ data: Uint8Array;
3
+ sequence: number;
4
+ }
5
+
6
+ export class DataPacketBuffer {
7
+ private buffer: DataPacketItem[] = [];
8
+
9
+ private _totalSize = 0;
10
+
11
+ push(item: DataPacketItem) {
12
+ this.buffer.push(item);
13
+ this._totalSize += item.data.byteLength;
14
+ }
15
+
16
+ pop(): DataPacketItem | undefined {
17
+ const item = this.buffer.shift();
18
+ if (item) {
19
+ this._totalSize -= item.data.byteLength;
20
+ }
21
+ return item;
22
+ }
23
+
24
+ getAll(): DataPacketItem[] {
25
+ return this.buffer.slice();
26
+ }
27
+
28
+ popToSequence(sequence: number) {
29
+ while (this.buffer.length > 0) {
30
+ const first = this.buffer[0];
31
+ if (first.sequence <= sequence) {
32
+ this.pop();
33
+ } else {
34
+ break;
35
+ }
36
+ }
37
+ }
38
+
39
+ alignBufferedAmount(bufferedAmount: number) {
40
+ while (this.buffer.length > 0) {
41
+ const first = this.buffer[0];
42
+ if (this._totalSize - first.data.byteLength <= bufferedAmount) {
43
+ break;
44
+ }
45
+ this.pop();
46
+ }
47
+ }
48
+
49
+ get length(): number {
50
+ return this.buffer.length;
51
+ }
52
+ }
@@ -0,0 +1,96 @@
1
+ export class TTLMap<K, V> {
2
+ private _map = new Map<K, { value: V; expiresAt: number }>();
3
+
4
+ private ttl: number;
5
+
6
+ private _lastCleanup = 0;
7
+
8
+ /**
9
+ * @param ttl ttl of the key (ms)
10
+ */
11
+ constructor(ttl: number) {
12
+ this.ttl = ttl;
13
+ }
14
+
15
+ set(key: K, value: V) {
16
+ const now = Date.now();
17
+ if (now - this._lastCleanup > this.ttl / 2) {
18
+ this.cleanup();
19
+ }
20
+ const expiresAt = now + this.ttl;
21
+ this._map.set(key, { value, expiresAt });
22
+ return this;
23
+ }
24
+
25
+ get(key: K): V | undefined {
26
+ const entry = this._map.get(key);
27
+ if (!entry) return undefined;
28
+ if (entry.expiresAt < Date.now()) {
29
+ this._map.delete(key);
30
+ return undefined;
31
+ }
32
+ return entry.value;
33
+ }
34
+
35
+ has(key: K): boolean {
36
+ const entry = this._map.get(key);
37
+ if (!entry) return false;
38
+ if (entry.expiresAt < Date.now()) {
39
+ this._map.delete(key);
40
+ return false;
41
+ }
42
+ return true;
43
+ }
44
+
45
+ delete(key: K): boolean {
46
+ return this._map.delete(key);
47
+ }
48
+
49
+ clear() {
50
+ this._map.clear();
51
+ }
52
+
53
+ cleanup() {
54
+ const now = Date.now();
55
+ for (const [key, entry] of this._map.entries()) {
56
+ if (entry.expiresAt < now) {
57
+ this._map.delete(key);
58
+ }
59
+ }
60
+ this._lastCleanup = now;
61
+ }
62
+
63
+ get size() {
64
+ this.cleanup();
65
+ return this._map.size;
66
+ }
67
+
68
+ forEach(callback: (value: V, key: K, map: Map<K, V>) => void) {
69
+ this.cleanup();
70
+ for (const [key, entry] of this._map.entries()) {
71
+ if (entry.expiresAt >= Date.now()) {
72
+ callback(entry.value, key, this.asValueMap());
73
+ }
74
+ }
75
+ }
76
+
77
+ map<U>(callback: (value: V, key: K, map: Map<K, V>) => U): U[] {
78
+ this.cleanup();
79
+ const result: U[] = [];
80
+ const valueMap = this.asValueMap();
81
+ for (const [key, value] of valueMap.entries()) {
82
+ result.push(callback(value, key, valueMap));
83
+ }
84
+ return result;
85
+ }
86
+
87
+ private asValueMap(): Map<K, V> {
88
+ const result = new Map<K, V>();
89
+ for (const [key, entry] of this._map.entries()) {
90
+ if (entry.expiresAt >= Date.now()) {
91
+ result.set(key, entry.value);
92
+ }
93
+ }
94
+ return result;
95
+ }
96
+ }