livekit-client 2.22.3 → 2.22.4

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 (214) hide show
  1. package/README.md +35 -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 +2 -1
  5. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  6. package/dist/livekit-client.esm.mjs +602 -247
  7. package/dist/livekit-client.esm.mjs.map +1 -1
  8. package/dist/livekit-client.fm.worker.js +1 -1
  9. package/dist/livekit-client.fm.worker.js.map +1 -1
  10. package/dist/livekit-client.fm.worker.mjs +2 -1
  11. package/dist/livekit-client.fm.worker.mjs.map +1 -1
  12. package/dist/livekit-client.umd.js +1 -1
  13. package/dist/livekit-client.umd.js.map +1 -1
  14. package/dist/src/api/SignalClient.d.ts +4 -2
  15. package/dist/src/api/SignalClient.d.ts.map +1 -1
  16. package/dist/src/options.d.ts +14 -0
  17. package/dist/src/options.d.ts.map +1 -1
  18. package/dist/src/room/PCTransport.d.ts +78 -7
  19. package/dist/src/room/PCTransport.d.ts.map +1 -1
  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/defaults.d.ts.map +1 -1
  26. package/dist/src/room/errors.d.ts +18 -0
  27. package/dist/src/room/errors.d.ts.map +1 -1
  28. package/dist/src/room/events.d.ts +3 -2
  29. package/dist/src/room/events.d.ts.map +1 -1
  30. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  31. package/dist/src/room/rpc/client/RpcClientManager.d.ts.map +1 -1
  32. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  33. package/dist/src/room/track/LocalVideoTrack.d.ts +2 -0
  34. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  35. package/dist/src/room/track/utils.d.ts +13 -0
  36. package/dist/src/room/track/utils.d.ts.map +1 -1
  37. package/dist/src/room/utils.d.ts +32 -0
  38. package/dist/src/room/utils.d.ts.map +1 -1
  39. package/dist/src/test/compressionStreamStubs.d.ts +12 -0
  40. package/dist/src/test/compressionStreamStubs.d.ts.map +1 -0
  41. package/dist/ts4.2/api/SignalClient.d.ts +187 -185
  42. package/dist/ts4.2/api/SignalClientStateMachine.d.ts +85 -85
  43. package/dist/ts4.2/api/WebSocketStream.d.ts +33 -33
  44. package/dist/ts4.2/api/utils.d.ts +9 -9
  45. package/dist/ts4.2/connectionHelper/ConnectionCheck.d.ts +30 -30
  46. package/dist/ts4.2/connectionHelper/checks/Checker.d.ts +62 -62
  47. package/dist/ts4.2/connectionHelper/checks/cloudRegion.d.ts +18 -18
  48. package/dist/ts4.2/connectionHelper/checks/connectionProtocol.d.ts +20 -20
  49. package/dist/ts4.2/connectionHelper/checks/publishAudio.d.ts +6 -6
  50. package/dist/ts4.2/connectionHelper/checks/publishVideo.d.ts +7 -7
  51. package/dist/ts4.2/connectionHelper/checks/reconnect.d.ts +6 -6
  52. package/dist/ts4.2/connectionHelper/checks/turn.d.ts +6 -6
  53. package/dist/ts4.2/connectionHelper/checks/webrtc.d.ts +6 -6
  54. package/dist/ts4.2/connectionHelper/checks/websocket.d.ts +6 -6
  55. package/dist/ts4.2/e2ee/E2eeManager.d.ts +111 -111
  56. package/dist/ts4.2/e2ee/KeyProvider.d.ts +54 -54
  57. package/dist/ts4.2/e2ee/constants.d.ts +21 -21
  58. package/dist/ts4.2/e2ee/errors.d.ts +12 -12
  59. package/dist/ts4.2/e2ee/events.d.ts +39 -39
  60. package/dist/ts4.2/e2ee/index.d.ts +6 -6
  61. package/dist/ts4.2/e2ee/types.d.ts +231 -231
  62. package/dist/ts4.2/e2ee/utils.d.ts +32 -32
  63. package/dist/ts4.2/e2ee/worker/DataCryptor.d.ts +16 -16
  64. package/dist/ts4.2/e2ee/worker/ErrorRateLimiter.d.ts +21 -21
  65. package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +209 -209
  66. package/dist/ts4.2/e2ee/worker/ParticipantKeyHandler.d.ts +81 -84
  67. package/dist/ts4.2/e2ee/worker/e2ee.worker.d.ts +2 -2
  68. package/dist/ts4.2/e2ee/worker/naluUtils.d.ts +28 -28
  69. package/dist/ts4.2/e2ee/worker/sifPayload.d.ts +23 -23
  70. package/dist/ts4.2/frameMetadata/FrameMetadataManager.d.ts +53 -53
  71. package/dist/ts4.2/frameMetadata/frameMetadata.d.ts +33 -33
  72. package/dist/ts4.2/frameMetadata/types.d.ts +62 -62
  73. package/dist/ts4.2/frameMetadata/utils.d.ts +9 -9
  74. package/dist/ts4.2/frameMetadata/worker/frameMetadata.worker.d.ts +2 -2
  75. package/dist/ts4.2/index.d.ts +76 -76
  76. package/dist/ts4.2/logger.d.ts +66 -66
  77. package/dist/ts4.2/options.d.ts +163 -149
  78. package/dist/ts4.2/room/BackOffStrategy.d.ts +27 -27
  79. package/dist/ts4.2/room/DefaultReconnectPolicy.d.ts +8 -8
  80. package/dist/ts4.2/room/DeviceManager.d.ts +12 -12
  81. package/dist/ts4.2/room/PCTransport.d.ts +246 -175
  82. package/dist/ts4.2/room/PCTransportManager.d.ts +77 -77
  83. package/dist/ts4.2/room/RTCEngine.d.ts +269 -262
  84. package/dist/ts4.2/room/ReconnectPolicy.d.ts +24 -24
  85. package/dist/ts4.2/room/RegionUrlProvider.d.ts +36 -36
  86. package/dist/ts4.2/room/Room.d.ts +354 -365
  87. package/dist/ts4.2/room/attribute-typings.d.ts +35 -35
  88. package/dist/ts4.2/room/data-channel/DataChannelManager.d.ts +62 -62
  89. package/dist/ts4.2/room/data-channel/FlowControlledDataChannel.d.ts +94 -95
  90. package/dist/ts4.2/room/data-channel/LossyDataChannel.d.ts +41 -41
  91. package/dist/ts4.2/room/data-channel/ReliableDataChannel.d.ts +57 -57
  92. package/dist/ts4.2/room/data-channel/types.d.ts +12 -12
  93. package/dist/ts4.2/room/data-stream/compression.d.ts +49 -49
  94. package/dist/ts4.2/room/data-stream/constants.d.ts +18 -18
  95. package/dist/ts4.2/room/data-stream/incoming/IncomingDataStreamManager.d.ts +29 -29
  96. package/dist/ts4.2/room/data-stream/incoming/StreamReader.d.ts +80 -80
  97. package/dist/ts4.2/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts +73 -73
  98. package/dist/ts4.2/room/data-stream/outgoing/StreamWriter.d.ts +16 -16
  99. package/dist/ts4.2/room/data-stream/outgoing/header-utils.d.ts +18 -18
  100. package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +79 -80
  101. package/dist/ts4.2/room/data-track/RemoteDataTrack.d.ts +50 -50
  102. package/dist/ts4.2/room/data-track/depacketizer.d.ts +59 -59
  103. package/dist/ts4.2/room/data-track/frame.d.ts +22 -22
  104. package/dist/ts4.2/room/data-track/handle.d.ts +27 -27
  105. package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +124 -124
  106. package/dist/ts4.2/room/data-track/incoming/errors.d.ts +24 -24
  107. package/dist/ts4.2/room/data-track/incoming/pipeline.d.ts +41 -41
  108. package/dist/ts4.2/room/data-track/incoming/types.d.ts +20 -20
  109. package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +126 -126
  110. package/dist/ts4.2/room/data-track/outgoing/errors.d.ts +74 -74
  111. package/dist/ts4.2/room/data-track/outgoing/pipeline.d.ts +23 -23
  112. package/dist/ts4.2/room/data-track/outgoing/types.d.ts +48 -48
  113. package/dist/ts4.2/room/data-track/packet/constants.d.ts +20 -20
  114. package/dist/ts4.2/room/data-track/packet/errors.d.ts +40 -40
  115. package/dist/ts4.2/room/data-track/packet/extensions.d.ts +69 -69
  116. package/dist/ts4.2/room/data-track/packet/index.d.ts +98 -98
  117. package/dist/ts4.2/room/data-track/packet/serializable.d.ts +13 -13
  118. package/dist/ts4.2/room/data-track/packetizer.d.ts +43 -43
  119. package/dist/ts4.2/room/data-track/track-interfaces.d.ts +23 -23
  120. package/dist/ts4.2/room/data-track/types.d.ts +22 -22
  121. package/dist/ts4.2/room/data-track/utils.d.ts +60 -60
  122. package/dist/ts4.2/room/debounce.d.ts +11 -11
  123. package/dist/ts4.2/room/defaults.d.ts +9 -9
  124. package/dist/ts4.2/room/errors.d.ts +180 -162
  125. package/dist/ts4.2/room/events.d.ts +638 -637
  126. package/dist/ts4.2/room/participant/LocalParticipant.d.ts +287 -287
  127. package/dist/ts4.2/room/participant/Participant.d.ts +142 -144
  128. package/dist/ts4.2/room/participant/ParticipantTrackPermission.d.ts +26 -26
  129. package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +85 -86
  130. package/dist/ts4.2/room/participant/publishUtils.d.ts +53 -53
  131. package/dist/ts4.2/room/rpc/client/RpcClientManager.d.ts +43 -43
  132. package/dist/ts4.2/room/rpc/client/events.d.ts +8 -8
  133. package/dist/ts4.2/room/rpc/index.d.ts +7 -7
  134. package/dist/ts4.2/room/rpc/server/RpcServerManager.d.ts +44 -44
  135. package/dist/ts4.2/room/rpc/server/events.d.ts +8 -8
  136. package/dist/ts4.2/room/rpc/utils.d.ts +131 -131
  137. package/dist/ts4.2/room/stats.d.ts +71 -71
  138. package/dist/ts4.2/room/statsSummary.d.ts +13 -13
  139. package/dist/ts4.2/room/timers.d.ts +12 -12
  140. package/dist/ts4.2/room/token-source/TokenSource.d.ts +82 -82
  141. package/dist/ts4.2/room/token-source/types.d.ts +70 -70
  142. package/dist/ts4.2/room/token-source/utils.d.ts +8 -8
  143. package/dist/ts4.2/room/track/FrameMetadataExtractor.d.ts +19 -19
  144. package/dist/ts4.2/room/track/LocalAudioTrack.d.ts +39 -42
  145. package/dist/ts4.2/room/track/LocalTrack.d.ts +125 -125
  146. package/dist/ts4.2/room/track/LocalTrackPublication.d.ts +42 -42
  147. package/dist/ts4.2/room/track/LocalVideoTrack.d.ts +102 -100
  148. package/dist/ts4.2/room/track/RemoteAudioTrack.d.ts +55 -55
  149. package/dist/ts4.2/room/track/RemoteTrack.d.ts +38 -38
  150. package/dist/ts4.2/room/track/RemoteTrackPublication.d.ts +72 -75
  151. package/dist/ts4.2/room/track/RemoteVideoTrack.d.ts +73 -76
  152. package/dist/ts4.2/room/track/Track.d.ts +156 -166
  153. package/dist/ts4.2/room/track/TrackPublication.d.ts +75 -81
  154. package/dist/ts4.2/room/track/create.d.ts +25 -25
  155. package/dist/ts4.2/room/track/facingMode.d.ts +41 -41
  156. package/dist/ts4.2/room/track/options.d.ts +403 -403
  157. package/dist/ts4.2/room/track/processor/types.d.ts +31 -31
  158. package/dist/ts4.2/room/track/record.d.ts +13 -13
  159. package/dist/ts4.2/room/track/types.d.ts +28 -28
  160. package/dist/ts4.2/room/track/utils.d.ts +60 -47
  161. package/dist/ts4.2/room/types.d.ts +127 -127
  162. package/dist/ts4.2/room/utils.d.ts +246 -214
  163. package/dist/ts4.2/test/MockMediaStreamTrack.d.ts +26 -26
  164. package/dist/ts4.2/test/compressionStreamStubs.d.ts +12 -0
  165. package/dist/ts4.2/test/mocks.d.ts +12 -12
  166. package/dist/ts4.2/test/promiseState.d.ts +12 -12
  167. package/dist/ts4.2/test/signalToken.d.ts +26 -26
  168. package/dist/ts4.2/type-polyfills/non-shared-typed-arrays.d.ts +2 -2
  169. package/dist/ts4.2/utils/AsyncQueue.d.ts +23 -23
  170. package/dist/ts4.2/utils/TypedPromise.d.ts +17 -17
  171. package/dist/ts4.2/utils/abort-signal-polyfill.d.ts +13 -13
  172. package/dist/ts4.2/utils/browserParser.d.ts +13 -13
  173. package/dist/ts4.2/utils/camelToSnakeCase.d.ts +8 -8
  174. package/dist/ts4.2/utils/cloneDeep.d.ts +2 -2
  175. package/dist/ts4.2/utils/dataPacketBuffer.d.ts +34 -34
  176. package/dist/ts4.2/utils/deferrable-map.d.ts +32 -32
  177. package/dist/ts4.2/utils/machineInspector.d.ts +54 -54
  178. package/dist/ts4.2/utils/serializer.d.ts +48 -48
  179. package/dist/ts4.2/utils/subscribeToEvents.d.ts +15 -15
  180. package/dist/ts4.2/utils/ttlmap.d.ts +20 -20
  181. package/dist/ts4.2/version.d.ts +15 -15
  182. package/package.json +5 -4
  183. package/src/api/SignalClient.e2e.test.ts +1 -3
  184. package/src/api/SignalClient.test.ts +160 -10
  185. package/src/api/SignalClient.ts +75 -54
  186. package/src/options.ts +16 -0
  187. package/src/room/PCTransport.test.ts +183 -7
  188. package/src/room/PCTransport.ts +197 -36
  189. package/src/room/PCTransportManager.ts +3 -1
  190. package/src/room/RTCEngine.test.ts +84 -0
  191. package/src/room/RTCEngine.ts +24 -5
  192. package/src/room/Room.test.ts +32 -6
  193. package/src/room/Room.ts +26 -6
  194. package/src/room/data-stream/incoming/IncomingDataStreamManager.test.ts +16 -20
  195. package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +5 -5
  196. package/src/room/data-stream/outgoing/OutgoingDataStreamManager.test.ts +60 -39
  197. package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +4 -4
  198. package/src/room/defaults.ts +1 -0
  199. package/src/room/errors.test.ts +36 -0
  200. package/src/room/errors.ts +27 -0
  201. package/src/room/events.ts +2 -1
  202. package/src/room/participant/publishUtils.ts +0 -19
  203. package/src/room/rpc/client/RpcClientManager.test.ts +51 -0
  204. package/src/room/rpc/client/RpcClientManager.ts +32 -15
  205. package/src/room/track/LocalTrack.ts +18 -7
  206. package/src/room/track/LocalVideoTrack.ts +10 -3
  207. package/src/room/track/RemoteAudioTrack.ts +3 -3
  208. package/src/room/track/RemoteVideoTrack.test.ts +210 -0
  209. package/src/room/track/RemoteVideoTrack.ts +29 -3
  210. package/src/room/track/utils.test.ts +201 -2
  211. package/src/room/track/utils.ts +88 -0
  212. package/src/room/utils.test.ts +124 -0
  213. package/src/room/utils.ts +70 -0
  214. package/src/test/compressionStreamStubs.ts +53 -0
@@ -268,6 +268,14 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
268
268
  /** timestamp (ms) the primary transport entered `CONNECTING`, used to bound how long we tolerate it */
269
269
  private transportConnectingSince?: number;
270
270
 
271
+ /**
272
+ * Abort handlers for the in-flight `negotiate()` calls, which a single central
273
+ * Closing/Restarting listener pair fans out to. Registering a listener pair per call instead
274
+ * accumulates them on the engine emitter and trips its max-listener warning under
275
+ * renegotiation bursts.
276
+ */
277
+ private pendingNegotiationAborts = new Set<() => void>();
278
+
271
279
  constructor(private options: InternalRoomOptions) {
272
280
  super();
273
281
  this.log = getLogger(options.loggerName ?? LoggerNames.Engine, () => this.logContext);
@@ -308,6 +316,15 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
308
316
  this.client.onParticipantUpdate = (updates) =>
309
317
  this.emit(EngineEvent.ParticipantUpdate, updates);
310
318
  this.client.onJoined = (joinResponse) => this.emit(EngineEvent.Joined, joinResponse);
319
+
320
+ const abortPendingNegotiations = () => {
321
+ // Iterate a copy: each handler removes itself from the set as its negotiation settles.
322
+ for (const abort of Array.from(this.pendingNegotiationAborts)) {
323
+ abort();
324
+ }
325
+ };
326
+ this.on(EngineEvent.Closing, abortPendingNegotiations);
327
+ this.on(EngineEvent.Restarting, abortPendingNegotiations);
311
328
  }
312
329
 
313
330
  /** @internal */
@@ -669,6 +686,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
669
686
  this.midToTrackId = midToTrackId;
670
687
  }
671
688
  await this.pcManager.setPublisherAnswer(sd, offerId);
689
+ this.emit(EngineEvent.RequestSubscribedCodecRefresh);
672
690
  };
673
691
 
674
692
  // add candidate on trickle
@@ -738,7 +756,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
738
756
 
739
757
  this.client.onMediaSectionsRequirement = (requirement: MediaSectionsRequirement) => {
740
758
  this.addMediaSections(requirement.numAudios, requirement.numVideos);
741
- this.negotiate();
759
+ this.negotiate().catch((err) => {
760
+ this.log.error(err);
761
+ });
742
762
  };
743
763
 
744
764
  this.client.onPublishDataTrackResponse = (event: PublishDataTrackResponse) => {
@@ -1807,8 +1827,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1807
1827
  if (this.isClosed) {
1808
1828
  reject(new NegotiationError('cannot negotiate on closed engine'));
1809
1829
  }
1810
- this.on(EngineEvent.Closing, handleClosed);
1811
- this.on(EngineEvent.Restarting, handleClosed);
1830
+ this.pendingNegotiationAborts.add(handleClosed);
1812
1831
  this.pcManager.publisher.off(PCEvents.RTPVideoPayloadTypes, this.onRtpMapAvailable);
1813
1832
  this.pcManager.publisher.once(PCEvents.RTPVideoPayloadTypes, this.onRtpMapAvailable);
1814
1833
 
@@ -1832,8 +1851,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1832
1851
  reject(new Error(String(e)));
1833
1852
  }
1834
1853
  } finally {
1835
- this.off(EngineEvent.Closing, handleClosed);
1836
- this.off(EngineEvent.Restarting, handleClosed);
1854
+ this.pendingNegotiationAborts.delete(handleClosed);
1837
1855
  }
1838
1856
  });
1839
1857
  }
@@ -2095,6 +2113,7 @@ export type EngineEventCallbacks = {
2095
2113
  joined: (joinResponse: JoinResponse) => void;
2096
2114
  tokenRefreshed: (token: string) => void;
2097
2115
  serverRegionsReported: (regions: RegionSettings) => void;
2116
+ requestSubscribedCodecRefresh: () => void;
2098
2117
  };
2099
2118
 
2100
2119
  export interface RegionStrategy {
@@ -10,6 +10,7 @@ import {
10
10
  } from '@livekit/protocol';
11
11
  import { afterEach, describe, expect, it, vi } from 'vitest';
12
12
  import MockMediaStreamTrack from '../test/MockMediaStreamTrack';
13
+ import { stubMissingDeflateRawSupport } from '../test/compressionStreamStubs';
13
14
  import Room, { ConnectionState } from './Room';
14
15
  import { roomConnectOptionDefaults, roomOptionDefaults } from './defaults';
15
16
  import { EngineEvent, ParticipantEvent, RoomEvent } from './events';
@@ -46,8 +47,8 @@ describe('Active device switch', () => {
46
47
  });
47
48
 
48
49
  describe('Room signaling options', () => {
49
- it('advertises packet trailer capability when E2EE can handle trailers', async () => {
50
- const room = new Room();
50
+ /** Drives `connectSignal` with E2EE enabled against a stub engine, returning the `join` mock. */
51
+ async function connectSignalWithE2EE(room: Room) {
51
52
  const join = vi.fn().mockResolvedValue({
52
53
  joinResponse: new JoinResponse({
53
54
  room: { name: 'test-room', sid: 'room-sid' },
@@ -91,19 +92,44 @@ describe('Room signaling options', () => {
91
92
  new AbortController(),
92
93
  );
93
94
 
95
+ return join;
96
+ }
97
+
98
+ function expectCapabilities(
99
+ join: ReturnType<typeof vi.fn>,
100
+ clientInfoCapabilities: Array<ClientInfo_Capability>,
101
+ ) {
94
102
  expect(join).toHaveBeenCalledWith(
95
103
  'wss://test.livekit.io',
96
104
  'test-token',
97
105
  expect.objectContaining({
98
- clientInfoCapabilities: [
99
- ClientInfo_Capability.CAP_PACKET_TRAILER,
100
- ClientInfo_Capability.CAP_COMPRESSION_DEFLATE_RAW,
101
- ],
106
+ clientInfoCapabilities,
102
107
  e2eeEnabled: true,
103
108
  }),
104
109
  expect.any(AbortSignal),
105
110
  false,
106
111
  );
112
+ }
113
+
114
+ it('advertises packet trailer capability when E2EE can handle trailers', async () => {
115
+ const join = await connectSignalWithE2EE(new Room());
116
+
117
+ expectCapabilities(join, [
118
+ ClientInfo_Capability.CAP_PACKET_TRAILER,
119
+ ClientInfo_Capability.CAP_COMPRESSION_DEFLATE_RAW,
120
+ ]);
121
+ });
122
+
123
+ it('does not advertise deflate-raw compression when the runtime cannot decompress it', async () => {
124
+ const restoreCompressionStreams = stubMissingDeflateRawSupport();
125
+ try {
126
+ const join = await connectSignalWithE2EE(new Room());
127
+
128
+ // Otherwise peers would compress what they send us and we'd have to drop it.
129
+ expectCapabilities(join, [ClientInfo_Capability.CAP_PACKET_TRAILER]);
130
+ } finally {
131
+ restoreCompressionStreams();
132
+ }
107
133
  });
108
134
  });
109
135
 
package/src/room/Room.ts CHANGED
@@ -77,6 +77,7 @@ import {
77
77
  ConnectionErrorReason,
78
78
  UnexpectedConnectionState,
79
79
  UnsupportedServer,
80
+ canFailOverToAnotherRegion,
80
81
  } from './errors';
81
82
  import { EngineEvent, ParticipantEvent, RoomEvent, TrackEvent } from './events';
82
83
  import LocalParticipant from './participant/LocalParticipant';
@@ -120,9 +121,10 @@ import {
120
121
  getEmptyAudioStreamTrack,
121
122
  isBrowserSupported,
122
123
  isCloud,
123
- isCompressionStreamSupported,
124
+ isDeflateRawCompressionSupported,
124
125
  isLocalAudioTrack,
125
126
  isLocalParticipant,
127
+ isLocalVideoTrack,
126
128
  isReactNative,
127
129
  isRemotePub,
128
130
  isSafariBased,
@@ -755,6 +757,13 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
755
757
  updatedAtInMs: Date.now(),
756
758
  maxAgeInMs: DEFAULT_MAX_AGE_MS,
757
759
  });
760
+ })
761
+ .on(EngineEvent.RequestSubscribedCodecRefresh, () => {
762
+ for (const videoPub of this.localParticipant.videoTrackPublications.values()) {
763
+ if (isLocalVideoTrack(videoPub.track)) {
764
+ videoPub.track.refreshSubscribedCodecs();
765
+ }
766
+ }
758
767
  });
759
768
 
760
769
  if (this.localParticipant) {
@@ -908,8 +917,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
908
917
  if (
909
918
  this.regionUrlProvider &&
910
919
  error instanceof ConnectionError &&
911
- error.reason !== ConnectionErrorReason.Cancelled &&
912
- error.reason !== ConnectionErrorReason.NotAllowed
920
+ canFailOverToAnotherRegion(error)
913
921
  ) {
914
922
  let nextUrl: string | null = null;
915
923
  try {
@@ -992,6 +1000,8 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
992
1000
  autoSubscribe: connectOptions.autoSubscribe,
993
1001
  adaptiveStream:
994
1002
  typeof roomOptions.adaptiveStream === 'object' ? true : roomOptions.adaptiveStream,
1003
+ disableIceLite: connectOptions.disableIceLite,
1004
+ subscriberAllowPause: connectOptions.subscriberAllowPause,
995
1005
  clientInfoCapabilities: this.getClientInfoCapabilities(roomOptions),
996
1006
  maxRetries: connectOptions.maxRetries,
997
1007
  e2eeEnabled: !!this.e2eeManager,
@@ -1211,8 +1221,9 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
1211
1221
  let req: SimulateScenario | undefined;
1212
1222
  switch (scenario) {
1213
1223
  case 'signal-reconnect':
1224
+ const reconnectDelay = typeof arg === 'number' ? arg : 0;
1214
1225
  // @ts-expect-error function is private
1215
- await this.engine.client.handleOnClose('simulate disconnect');
1226
+ await this.engine.client.handleOnClose('simulate disconnect', undefined, reconnectDelay);
1216
1227
  break;
1217
1228
  case 'fail-on-v1-path':
1218
1229
  this.engine.failNextV1Path();
@@ -2097,7 +2108,13 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
2097
2108
  // find the participant
2098
2109
  const participant = this.remoteParticipants.get(packet.participantIdentity);
2099
2110
  if (packet.value.case === 'user') {
2100
- this.handleUserPacket(participant, packet.value.value, packet.kind, encryptionType);
2111
+ this.handleUserPacket(
2112
+ participant,
2113
+ packet.value.value,
2114
+ packet.kind,
2115
+ encryptionType,
2116
+ packet.participantIdentity,
2117
+ );
2101
2118
  } else if (packet.value.case === 'transcription') {
2102
2119
  this.handleTranscription(participant, packet.value.value);
2103
2120
  } else if (packet.value.case === 'sipDtmf') {
@@ -2147,6 +2164,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
2147
2164
  userPacket: UserPacket,
2148
2165
  kind: DataPacket_Kind,
2149
2166
  encryptionType: Encryption_Type,
2167
+ participantIdentity: string,
2150
2168
  ) => {
2151
2169
  this.emit(
2152
2170
  RoomEvent.DataReceived,
@@ -2155,6 +2173,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
2155
2173
  kind,
2156
2174
  userPacket.topic,
2157
2175
  encryptionType,
2176
+ participantIdentity,
2158
2177
  );
2159
2178
 
2160
2179
  // also emit on the participant
@@ -2566,7 +2585,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
2566
2585
  }
2567
2586
  // Advertise deflate-raw decompression support so peers know they can send us compressed data
2568
2587
  // streams (gated separately from clientProtocol — see the data streams v2 spec).
2569
- if (isCompressionStreamSupported()) {
2588
+ if (isDeflateRawCompressionSupported()) {
2570
2589
  capabilities.push(ClientInfo_Capability.CAP_COMPRESSION_DEFLATE_RAW);
2571
2590
  }
2572
2591
  return capabilities;
@@ -3060,6 +3079,7 @@ export type RoomEventCallbacks = {
3060
3079
  kind?: DataPacket_Kind,
3061
3080
  topic?: string,
3062
3081
  encryptionType?: Encryption_Type,
3082
+ participantIdentity?: string,
3063
3083
  ) => void;
3064
3084
  sipDTMFReceived: (dtmf: SipDTMF, participant?: RemoteParticipant) => void;
3065
3085
  transcriptionReceived: (
@@ -9,6 +9,10 @@ import {
9
9
  Encryption_Type,
10
10
  } from '@livekit/protocol';
11
11
  import { describe, expect, it } from 'vitest';
12
+ import {
13
+ stubMissingCompressionStreams,
14
+ stubMissingDeflateRawSupport,
15
+ } from '../../../test/compressionStreamStubs';
12
16
  import { deflateRawCompress } from '../compression';
13
17
  import { STREAM_CHUNK_SIZE_BYTES } from '../constants';
14
18
  import IncomingDataStreamManager from './IncomingDataStreamManager';
@@ -907,18 +911,15 @@ describe('IncomingDataStreamManager', () => {
907
911
  expect(await reader.readAll()).toStrictEqual(text);
908
912
  });
909
913
 
910
- it(`should ignore a v2 TEXT data stream with compression if DecompressionStream doesn't exist`, async () => {
914
+ it.each([
915
+ [`DecompressionStream doesn't exist`, stubMissingCompressionStreams],
916
+ [`deflate-raw isn't a supported format`, stubMissingDeflateRawSupport],
917
+ ])(`should ignore a v2 TEXT data stream with compression if %s`, async (_label, stub) => {
911
918
  const text = 'hello world';
912
919
  const compressed = await deflateRawCompress(new TextEncoder().encode(text));
913
920
 
914
- let originalCompressionStream: typeof CompressionStream,
915
- originalDecompressionStream: typeof DecompressionStream;
921
+ const restoreCompressionStreams = stub();
916
922
  try {
917
- originalCompressionStream = CompressionStream;
918
- (globalThis as any).CompressionStream = undefined;
919
- originalDecompressionStream = DecompressionStream;
920
- (globalThis as any).DecompressionStream = undefined;
921
-
922
923
  const manager = new IncomingDataStreamManager();
923
924
  manager.setConnected(true);
924
925
 
@@ -977,23 +978,19 @@ describe('IncomingDataStreamManager', () => {
977
978
  Promise.race([readerPromise, Promise.resolve('still pending')]),
978
979
  ).resolves.toStrictEqual('still pending');
979
980
  } finally {
980
- (globalThis as any).CompressionStream = originalCompressionStream!;
981
- (globalThis as any).DecompressionStream = originalDecompressionStream!;
981
+ restoreCompressionStreams();
982
982
  }
983
983
  });
984
984
 
985
- it(`should ignore a v2 BYTES data stream with compression if DecompressionStream doesn't exist`, async () => {
985
+ it.each([
986
+ [`DecompressionStream doesn't exist`, stubMissingCompressionStreams],
987
+ [`deflate-raw isn't a supported format`, stubMissingDeflateRawSupport],
988
+ ])(`should ignore a v2 BYTES data stream with compression if %s`, async (_label, stub) => {
986
989
  const bytes = new Uint8Array([0x01, 0x02, 0x03]);
987
990
  const compressed = await deflateRawCompress(bytes);
988
991
 
989
- let originalCompressionStream: typeof CompressionStream,
990
- originalDecompressionStream: typeof DecompressionStream;
992
+ const restoreCompressionStreams = stub();
991
993
  try {
992
- originalCompressionStream = CompressionStream;
993
- (globalThis as any).CompressionStream = undefined;
994
- originalDecompressionStream = DecompressionStream;
995
- (globalThis as any).DecompressionStream = undefined;
996
-
997
994
  const manager = new IncomingDataStreamManager();
998
995
  manager.setConnected(true);
999
996
 
@@ -1052,8 +1049,7 @@ describe('IncomingDataStreamManager', () => {
1052
1049
  Promise.race([readerPromise, Promise.resolve('still pending')]),
1053
1050
  ).resolves.toStrictEqual('still pending');
1054
1051
  } finally {
1055
- (globalThis as any).CompressionStream = originalCompressionStream!;
1056
- (globalThis as any).DecompressionStream = originalDecompressionStream!;
1052
+ restoreCompressionStreams();
1057
1053
  }
1058
1054
  });
1059
1055
 
@@ -10,7 +10,7 @@ import log from '../../../logger';
10
10
  import { type NonSharedUint8Array } from '../../../type-polyfills/non-shared-typed-arrays';
11
11
  import { DataStreamError, DataStreamErrorReason } from '../../errors';
12
12
  import { type ByteStreamInfo, type StreamController, type TextStreamInfo } from '../../types';
13
- import { bigIntToNumber, isCompressionStreamSupported, numberToBigInt } from '../../utils';
13
+ import { bigIntToNumber, isDeflateRawCompressionSupported, numberToBigInt } from '../../utils';
14
14
  import { deflateRawDecompress, inflateRawTransform } from '../compression';
15
15
  import { DEFAULT_MAX_PAYLOAD_BYTE_LENGTH } from '../constants';
16
16
  import {
@@ -174,11 +174,11 @@ export default class IncomingDataStreamManager {
174
174
  let compressed;
175
175
  switch (streamHeader.compression) {
176
176
  case DataStream_CompressionType.DEFLATE_RAW:
177
- if (!isCompressionStreamSupported()) {
177
+ if (!isDeflateRawCompressionSupported()) {
178
178
  // NOTE: this shouldn't really ever happen, if this warning is logged then the sender
179
179
  // isn't properly abiding by the data streams v2 protocol.
180
180
  log.warn(
181
- `Data stream ${streamHeader.streamId} received with deflate-raw compression, but this browser does not have support for DecompressionStream. Dropping...`,
181
+ `Data stream ${streamHeader.streamId} received with deflate-raw compression, but this browser does not support deflate-raw decompression. Dropping...`,
182
182
  );
183
183
  return;
184
184
  }
@@ -279,11 +279,11 @@ export default class IncomingDataStreamManager {
279
279
  let compressed;
280
280
  switch (streamHeader.compression) {
281
281
  case DataStream_CompressionType.DEFLATE_RAW:
282
- if (!isCompressionStreamSupported()) {
282
+ if (!isDeflateRawCompressionSupported()) {
283
283
  // NOTE: this shouldn't really ever happen, if this warning is logged then the sender
284
284
  // isn't properly abiding by the data streams v2 protocol.
285
285
  log.warn(
286
- `Data stream ${streamHeader.streamId} received with deflate-raw compression, but this browser does not have support for DecompressionStream. Dropping...`,
286
+ `Data stream ${streamHeader.streamId} received with deflate-raw compression, but this browser does not support deflate-raw decompression. Dropping...`,
287
287
  );
288
288
  return;
289
289
  }
@@ -5,14 +5,19 @@ import {
5
5
  DataStream_CompressionType,
6
6
  type DataStream_TextHeader,
7
7
  } from '@livekit/protocol';
8
- import { beforeEach, describe, expect, it, vi } from 'vitest';
8
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
9
9
  import log from '../../../logger';
10
+ import {
11
+ stubMissingCompressionStreams,
12
+ stubMissingDeflateRawSupport,
13
+ } from '../../../test/compressionStreamStubs';
10
14
  import {
11
15
  CLIENT_PROTOCOL_DATA_STREAM_RPC,
12
16
  CLIENT_PROTOCOL_DATA_STREAM_V2,
13
17
  CLIENT_PROTOCOL_DEFAULT,
14
18
  } from '../../../version';
15
19
  import type RTCEngine from '../../RTCEngine';
20
+ import { STREAM_CHUNK_SIZE_BYTES } from '../constants';
16
21
  import OutgoingDataStreamManager from './OutgoingDataStreamManager';
17
22
 
18
23
  /** Builds a low quality random string of the given length. */
@@ -1195,7 +1200,7 @@ describe('OutgoingDataStreamManager', () => {
1195
1200
  // The split backs off below the MTU rather than bisecting the emoji, so each chunk decodes
1196
1201
  // independently.
1197
1202
  expect(first.content).toHaveLength(14_999);
1198
- const decode = (bytes: Uint8Array) => new TextDecoder('utf-8', { fatal: true }).decode(bytes);
1203
+ const decode = (bytes: Uint8Array) => new TextDecoder('utf-8').decode(bytes);
1199
1204
  expect(() => decode(first.content)).not.toThrow();
1200
1205
  expect(() => decode(second.content)).not.toThrow();
1201
1206
  expect(decode(first.content) + decode(second.content)).toStrictEqual(text);
@@ -1243,50 +1248,66 @@ describe('OutgoingDataStreamManager', () => {
1243
1248
  });
1244
1249
  });
1245
1250
 
1246
- describe('runtime without CompressionStream', () => {
1251
+ describe.each([
1252
+ ['a runtime without CompressionStream', stubMissingCompressionStreams],
1253
+ ['a runtime without deflate-raw support', stubMissingDeflateRawSupport],
1254
+ ])('on %s', (_label, stub) => {
1255
+ let restoreCompressionStreams: () => void;
1256
+
1257
+ beforeEach(() => {
1258
+ restoreCompressionStreams = stub();
1259
+ });
1260
+
1261
+ afterEach(() => {
1262
+ restoreCompressionStreams();
1263
+ });
1264
+
1247
1265
  it('should send raw inline even to compression-capable recipients when the runtime cannot compress', async () => {
1248
- const originalCompressionStream = CompressionStream;
1249
- try {
1250
- (globalThis as any).CompressionStream = undefined;
1266
+ const { manager, sentPackets } = createManager({ alice: CLIENT_PROTOCOL_DATA_STREAM_V2 });
1267
+ await manager.sendText('hello hello compressible world', {
1268
+ topic: 'my-topic',
1269
+ destinationIdentities: ['alice'],
1270
+ });
1251
1271
 
1252
- const { manager, sentPackets } = createManager({ alice: CLIENT_PROTOCOL_DATA_STREAM_V2 });
1253
- await manager.sendText('hello hello compressible world', {
1254
- topic: 'my-topic',
1255
- destinationIdentities: ['alice'],
1256
- });
1272
+ // Compression eligibility also requires a local compressor; without one, inline still
1273
+ // applies but the payload is sent raw.
1274
+ expect(sentPackets).toHaveLength(1);
1275
+ const header = headerOf(sentPackets[0]);
1276
+ expect(header.compression).toBe(DataStream_CompressionType.NONE);
1277
+ expect(header.inlineContent).toStrictEqual(
1278
+ new TextEncoder().encode('hello hello compressible world'),
1279
+ );
1280
+ });
1257
1281
 
1258
- // Compression eligibility also requires a local compressor; without one, inline still
1259
- // applies but the payload is sent raw.
1260
- expect(sentPackets).toHaveLength(1);
1261
- const header = headerOf(sentPackets[0]);
1262
- expect(header.compression).toBe(DataStream_CompressionType.NONE);
1263
- expect(header.inlineContent).toStrictEqual(
1264
- new TextEncoder().encode('hello hello compressible world'),
1265
- );
1266
- } finally {
1267
- (globalThis as any).CompressionStream = originalCompressionStream;
1268
- }
1282
+ it('should send BYTES uncompressed when the runtime cannot compress', async () => {
1283
+ const { manager, sentPackets } = createManager({ alice: CLIENT_PROTOCOL_DATA_STREAM_V2 });
1284
+ // Larger than the inline budget, so this takes the chunked path rather than riding along in
1285
+ // the header.
1286
+ const bytes = new Uint8Array(20_000).fill(0x07);
1287
+ await manager.sendBytes(bytes, {
1288
+ topic: 'my-topic',
1289
+ destinationIdentities: ['alice'],
1290
+ });
1291
+
1292
+ expect(sentPackets).toHaveLength(4);
1293
+ const header = headerOf(sentPackets[0]);
1294
+ expect(header.compression).toBe(DataStream_CompressionType.NONE);
1295
+ expect(chunkOf(sentPackets[1]).content).toHaveLength(STREAM_CHUNK_SIZE_BYTES);
1296
+ expect(chunkOf(sentPackets[2]).content).toHaveLength(20_000 - STREAM_CHUNK_SIZE_BYTES);
1269
1297
  });
1270
1298
 
1271
1299
  it('should send a FILE uncompressed when the runtime cannot compress', async () => {
1272
- const originalCompressionStream = CompressionStream;
1273
- try {
1274
- (globalThis as any).CompressionStream = undefined;
1275
-
1276
- const { manager, sentPackets } = createManager({ alice: CLIENT_PROTOCOL_DATA_STREAM_V2 });
1277
- const bytes = new Uint8Array(10_000).fill(0x07);
1278
- await manager.sendFile(new File([bytes as NonSharedUint8Array], 'text.txt'), {
1279
- topic: 'my-topic',
1280
- destinationIdentities: ['alice'],
1281
- });
1300
+ const { manager, sentPackets } = createManager({ alice: CLIENT_PROTOCOL_DATA_STREAM_V2 });
1301
+ const bytes = new Uint8Array(10_000).fill(0x07);
1302
+ await manager.sendFile(new File([bytes as NonSharedUint8Array], 'text.txt'), {
1303
+ topic: 'my-topic',
1304
+ destinationIdentities: ['alice'],
1305
+ });
1282
1306
 
1283
- expect(sentPackets).toHaveLength(3);
1284
- const header = headerOf(sentPackets[0]);
1285
- expect(header.compression).toBe(DataStream_CompressionType.NONE);
1286
- expect(chunkOf(sentPackets[1]).content).toHaveLength(10_000);
1287
- } finally {
1288
- (globalThis as any).CompressionStream = originalCompressionStream;
1289
- }
1307
+ expect(sentPackets).toHaveLength(3);
1308
+ const header = headerOf(sentPackets[0]);
1309
+ expect(header.compression).toBe(DataStream_CompressionType.NONE);
1310
+ expect(chunkOf(sentPackets[1]).content).toHaveLength(10_000);
1290
1311
  });
1291
1312
  });
1292
1313
  });
@@ -24,7 +24,7 @@ import type {
24
24
  TextStreamInfo,
25
25
  } from '../../types';
26
26
  import {
27
- isCompressionStreamSupported,
27
+ isDeflateRawCompressionSupported,
28
28
  numberToBigInt,
29
29
  readBytesInChunks,
30
30
  readableFromBytes,
@@ -101,7 +101,7 @@ export default class OutgoingDataStreamManager {
101
101
 
102
102
  const compressEligible =
103
103
  compress &&
104
- isCompressionStreamSupported() &&
104
+ isDeflateRawCompressionSupported() &&
105
105
  this.allRecipientsSupportV2(options?.destinationIdentities) &&
106
106
  this.allRecipientsSupportCompression(options?.destinationIdentities);
107
107
  let compressedStream = compressEligible
@@ -239,7 +239,7 @@ export default class OutgoingDataStreamManager {
239
239
 
240
240
  const compressEligible =
241
241
  compress &&
242
- isCompressionStreamSupported() &&
242
+ isDeflateRawCompressionSupported() &&
243
243
  this.allRecipientsSupportV2(destinationIdentities) &&
244
244
  this.allRecipientsSupportCompression(destinationIdentities);
245
245
  let compressedStream = compressEligible
@@ -463,7 +463,7 @@ export default class OutgoingDataStreamManager {
463
463
  const destinationIdentities = options?.destinationIdentities;
464
464
  const compress =
465
465
  (options?.compress ?? true) &&
466
- isCompressionStreamSupported() &&
466
+ isDeflateRawCompressionSupported() &&
467
467
  this.allRecipientsSupportV2(destinationIdentities) &&
468
468
  this.allRecipientsSupportCompression(destinationIdentities);
469
469
 
@@ -47,6 +47,7 @@ export const roomOptionDefaults: InternalRoomOptions = {
47
47
 
48
48
  export const roomConnectOptionDefaults: InternalRoomConnectOptions = {
49
49
  autoSubscribe: true,
50
+ disableIceLite: false,
50
51
  maxRetries: 1,
51
52
  peerConnectionTimeout: 15_000,
52
53
  websocketTimeout: 15_000,
@@ -0,0 +1,36 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { ConnectionError, canFailOverToAnotherRegion } from './errors';
3
+
4
+ describe('canFailOverToAnotherRegion', () => {
5
+ it('allows failover on 403, which LiveKit Cloud uses to signal region pinning', () => {
6
+ // The RTC paths 403 when the project is not allowed in the region the client geo-routed to.
7
+ // `/settings/regions` stays reachable so the client can discover where it is allowed.
8
+ expect(
9
+ canFailOverToAnotherRegion(
10
+ ConnectionError.notAllowed('project not allowed in this region.', 403),
11
+ ),
12
+ ).toBe(true);
13
+ });
14
+
15
+ it('does not allow failover on 401 — no other region will accept the same token', () => {
16
+ expect(canFailOverToAnotherRegion(ConnectionError.notAllowed('unauthorized', 401))).toBe(false);
17
+ });
18
+
19
+ it('does not allow failover when the room does not exist, reported as NotAllowed with 404', () => {
20
+ expect(
21
+ canFailOverToAnotherRegion(ConnectionError.notAllowed('requested room does not exist', 404)),
22
+ ).toBe(false);
23
+ });
24
+
25
+ it('does not allow failover on a cancelled attempt', () => {
26
+ expect(canFailOverToAnotherRegion(ConnectionError.cancelled('aborted'))).toBe(false);
27
+ });
28
+
29
+ it.each([
30
+ ['server unreachable', ConnectionError.serverUnreachable('unreachable')],
31
+ ['timeout', ConnectionError.timeout('timed out')],
32
+ ['internal', ConnectionError.internal('internal')],
33
+ ])('allows failover on a %s error', (_name, error) => {
34
+ expect(canFailOverToAnotherRegion(error)).toBe(true);
35
+ });
36
+ });
@@ -188,6 +188,33 @@ export class ConnectionError<
188
188
  }
189
189
  }
190
190
 
191
+ /**
192
+ * Whether a failed connection attempt may be retried against a different LiveKit Cloud region.
193
+ *
194
+ * LiveKit Cloud signals project-level region pinning by returning 403 on the RTC paths when the
195
+ * project is not allowed in the region the client geo-routed to. `/settings/regions` is
196
+ * deliberately left reachable so the client can discover its allowed regions and connect there, so
197
+ * a 403 must not be treated as terminal.
198
+ *
199
+ * A 401 stays terminal: no other region will accept a token this one rejected. So does the 404
200
+ * "requested room does not exist" case, which is also reported as `NotAllowed`.
201
+ *
202
+ * We key on the status rather than the server's error message because that message is an
203
+ * unversioned human-readable string; matching it would let a copy edit break already-shipped
204
+ * clients. If a 403 really was a permissions failure rather than region pinning, every region
205
+ * attempt fails the same way and the original error still surfaces — at the cost of one extra
206
+ * region lookup.
207
+ */
208
+ export function canFailOverToAnotherRegion(error: ConnectionError): boolean {
209
+ if (error.reason === ConnectionErrorReason.Cancelled) {
210
+ return false;
211
+ }
212
+ if (error.reason === ConnectionErrorReason.NotAllowed) {
213
+ return error.status === 403;
214
+ }
215
+ return true;
216
+ }
217
+
191
218
  export class DeviceUnsupportedError extends LivekitError {
192
219
  readonly name = 'DeviceUnsupportedError';
193
220
 
@@ -225,7 +225,7 @@ export enum RoomEvent {
225
225
  * Data packets provides the ability to use LiveKit to send/receive arbitrary payloads.
226
226
  * All participants in the room will receive the messages sent to the room.
227
227
  *
228
- * args: (payload: NonSharedUint8Array, participant: [[Participant]], kind: [[DataPacket_Kind]], topic?: string)
228
+ * args: (payload: NonSharedUint8Array, participant: [[Participant]] | undefined, kind: [[DataPacket_Kind]], topic?: string, encryptionType?: Encryption_Type, participantIdentity?: string)
229
229
  */
230
230
  DataReceived = 'dataReceived',
231
231
 
@@ -633,6 +633,7 @@ export enum EngineEvent {
633
633
  Joined = 'joined',
634
634
  TokenRefreshed = 'tokenRefreshed',
635
635
  ServerRegionsReported = 'serverRegionsReported',
636
+ RequestSubscribedCodecRefresh = 'requestSubscribedCodecRefresh',
636
637
  }
637
638
 
638
639
  export enum TrackEvent {
@@ -74,25 +74,6 @@ export const computeDefaultScreenShareSimulcastPresets = (fromPreset: VideoPrese
74
74
  );
75
75
  };
76
76
 
77
- // /**
78
- // *
79
- // * @internal
80
- // * @experimental
81
- // */
82
- // const computeDefaultMultiCodecSimulcastEncodings = (width: number, height: number) => {
83
- // // use vp8 as a default
84
- // const vp8 = determineAppropriateEncoding(false, width, height);
85
- // const vp9 = { ...vp8, maxBitrate: vp8.maxBitrate * 0.9 };
86
- // const h264 = { ...vp8, maxBitrate: vp8.maxBitrate * 1.1 };
87
- // const av1 = { ...vp8, maxBitrate: vp8.maxBitrate * 0.7 };
88
- // return {
89
- // vp8,
90
- // vp9,
91
- // h264,
92
- // av1,
93
- // };
94
- // };
95
-
96
77
  const videoRids = ['q', 'h', 'f'];
97
78
 
98
79
  /* @internal */