livekit-client 2.18.8 → 2.18.10

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 (193) 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 +5609 -644
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +2898 -2431
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.pt.worker.js +2 -0
  8. package/dist/livekit-client.pt.worker.js.map +1 -0
  9. package/dist/livekit-client.pt.worker.mjs +5834 -0
  10. package/dist/livekit-client.pt.worker.mjs.map +1 -0
  11. package/dist/livekit-client.umd.js +1 -1
  12. package/dist/livekit-client.umd.js.map +1 -1
  13. package/dist/src/api/SignalClient.d.ts +2 -1
  14. package/dist/src/api/SignalClient.d.ts.map +1 -1
  15. package/dist/src/e2ee/E2eeManager.d.ts +8 -7
  16. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  17. package/dist/src/e2ee/types.d.ts +35 -8
  18. package/dist/src/e2ee/types.d.ts.map +1 -1
  19. package/dist/src/e2ee/utils.d.ts +5 -5
  20. package/dist/src/e2ee/utils.d.ts.map +1 -1
  21. package/dist/src/e2ee/worker/DataCryptor.d.ts +5 -5
  22. package/dist/src/e2ee/worker/DataCryptor.d.ts.map +1 -1
  23. package/dist/src/e2ee/worker/FrameCryptor.d.ts +21 -4
  24. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  25. package/dist/src/e2ee/worker/naluUtils.d.ts +1 -1
  26. package/dist/src/e2ee/worker/naluUtils.d.ts.map +1 -1
  27. package/dist/src/e2ee/worker/sifPayload.d.ts +7 -7
  28. package/dist/src/e2ee/worker/sifPayload.d.ts.map +1 -1
  29. package/dist/src/index.d.ts +4 -1
  30. package/dist/src/index.d.ts.map +1 -1
  31. package/dist/src/options.d.ts +7 -0
  32. package/dist/src/options.d.ts.map +1 -1
  33. package/dist/src/packetTrailer/PacketTrailerManager.d.ts +49 -0
  34. package/dist/src/packetTrailer/PacketTrailerManager.d.ts.map +1 -0
  35. package/dist/src/packetTrailer/packetTrailer.d.ts +32 -0
  36. package/dist/src/packetTrailer/packetTrailer.d.ts.map +1 -0
  37. package/dist/src/packetTrailer/types.d.ts +57 -0
  38. package/dist/src/packetTrailer/types.d.ts.map +1 -0
  39. package/dist/src/packetTrailer/utils.d.ts +9 -0
  40. package/dist/src/packetTrailer/utils.d.ts.map +1 -0
  41. package/dist/src/packetTrailer/worker/packetTrailer.worker.d.ts +2 -0
  42. package/dist/src/packetTrailer/worker/packetTrailer.worker.d.ts.map +1 -0
  43. package/dist/src/room/RTCEngine.d.ts +2 -1
  44. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  45. package/dist/src/room/Room.d.ts +3 -1
  46. package/dist/src/room/Room.d.ts.map +1 -1
  47. package/dist/src/room/data-track/LocalDataTrack.d.ts +2 -1
  48. package/dist/src/room/data-track/LocalDataTrack.d.ts.map +1 -1
  49. package/dist/src/room/data-track/RemoteDataTrack.d.ts +5 -1
  50. package/dist/src/room/data-track/RemoteDataTrack.d.ts.map +1 -1
  51. package/dist/src/room/data-track/depacketizer.d.ts +12 -4
  52. package/dist/src/room/data-track/depacketizer.d.ts.map +1 -1
  53. package/dist/src/room/data-track/frame.d.ts +3 -3
  54. package/dist/src/room/data-track/frame.d.ts.map +1 -1
  55. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts +3 -1
  56. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts.map +1 -1
  57. package/dist/src/room/data-track/incoming/pipeline.d.ts +4 -1
  58. package/dist/src/room/data-track/incoming/pipeline.d.ts.map +1 -1
  59. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +2 -2
  60. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts.map +1 -1
  61. package/dist/src/room/data-track/outgoing/types.d.ts +4 -3
  62. package/dist/src/room/data-track/outgoing/types.d.ts.map +1 -1
  63. package/dist/src/room/data-track/packet/extensions.d.ts +4 -4
  64. package/dist/src/room/data-track/packet/extensions.d.ts.map +1 -1
  65. package/dist/src/room/data-track/packet/index.d.ts +5 -5
  66. package/dist/src/room/data-track/packet/index.d.ts.map +1 -1
  67. package/dist/src/room/data-track/packet/serializable.d.ts +1 -1
  68. package/dist/src/room/data-track/packet/serializable.d.ts.map +1 -1
  69. package/dist/src/room/data-track/types.d.ts +7 -0
  70. package/dist/src/room/data-track/types.d.ts.map +1 -1
  71. package/dist/src/room/events.d.ts +2 -2
  72. package/dist/src/room/participant/LocalParticipant.d.ts +3 -1
  73. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  74. package/dist/src/room/participant/Participant.d.ts +1 -1
  75. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  76. package/dist/src/room/track/PacketTrailerExtractor.d.ts +19 -0
  77. package/dist/src/room/track/PacketTrailerExtractor.d.ts.map +1 -0
  78. package/dist/src/room/track/RemoteVideoTrack.d.ts +16 -0
  79. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  80. package/dist/src/room/track/Track.d.ts +1 -1
  81. package/dist/src/room/track/Track.d.ts.map +1 -1
  82. package/dist/src/room/track/create.d.ts.map +1 -1
  83. package/dist/src/room/track/options.d.ts +10 -0
  84. package/dist/src/room/track/options.d.ts.map +1 -1
  85. package/dist/src/room/track/utils.d.ts.map +1 -1
  86. package/dist/src/room/utils.d.ts +4 -3
  87. package/dist/src/room/utils.d.ts.map +1 -1
  88. package/dist/src/test/MockMediaStreamTrack.d.ts.map +1 -1
  89. package/dist/src/utils/dataPacketBuffer.d.ts +1 -1
  90. package/dist/src/utils/dataPacketBuffer.d.ts.map +1 -1
  91. package/dist/src/version.d.ts +1 -1
  92. package/dist/ts4.2/api/SignalClient.d.ts +2 -1
  93. package/dist/ts4.2/e2ee/E2eeManager.d.ts +8 -7
  94. package/dist/ts4.2/e2ee/types.d.ts +35 -8
  95. package/dist/ts4.2/e2ee/utils.d.ts +5 -5
  96. package/dist/ts4.2/e2ee/worker/DataCryptor.d.ts +5 -5
  97. package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +21 -4
  98. package/dist/ts4.2/e2ee/worker/naluUtils.d.ts +1 -1
  99. package/dist/ts4.2/e2ee/worker/sifPayload.d.ts +7 -7
  100. package/dist/ts4.2/index.d.ts +5 -1
  101. package/dist/ts4.2/options.d.ts +7 -0
  102. package/dist/ts4.2/packetTrailer/PacketTrailerManager.d.ts +49 -0
  103. package/dist/ts4.2/packetTrailer/packetTrailer.d.ts +32 -0
  104. package/dist/ts4.2/packetTrailer/types.d.ts +57 -0
  105. package/dist/ts4.2/packetTrailer/utils.d.ts +9 -0
  106. package/dist/ts4.2/packetTrailer/worker/packetTrailer.worker.d.ts +2 -0
  107. package/dist/ts4.2/room/RTCEngine.d.ts +2 -1
  108. package/dist/ts4.2/room/Room.d.ts +3 -1
  109. package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +2 -1
  110. package/dist/ts4.2/room/data-track/RemoteDataTrack.d.ts +5 -1
  111. package/dist/ts4.2/room/data-track/depacketizer.d.ts +12 -4
  112. package/dist/ts4.2/room/data-track/frame.d.ts +3 -3
  113. package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +3 -1
  114. package/dist/ts4.2/room/data-track/incoming/pipeline.d.ts +4 -1
  115. package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +2 -2
  116. package/dist/ts4.2/room/data-track/outgoing/types.d.ts +4 -3
  117. package/dist/ts4.2/room/data-track/packet/extensions.d.ts +4 -4
  118. package/dist/ts4.2/room/data-track/packet/index.d.ts +5 -5
  119. package/dist/ts4.2/room/data-track/packet/serializable.d.ts +1 -1
  120. package/dist/ts4.2/room/data-track/types.d.ts +7 -0
  121. package/dist/ts4.2/room/events.d.ts +2 -2
  122. package/dist/ts4.2/room/participant/LocalParticipant.d.ts +3 -1
  123. package/dist/ts4.2/room/participant/Participant.d.ts +1 -1
  124. package/dist/ts4.2/room/track/PacketTrailerExtractor.d.ts +19 -0
  125. package/dist/ts4.2/room/track/RemoteVideoTrack.d.ts +16 -0
  126. package/dist/ts4.2/room/track/Track.d.ts +1 -1
  127. package/dist/ts4.2/room/track/options.d.ts +10 -0
  128. package/dist/ts4.2/room/utils.d.ts +4 -3
  129. package/dist/ts4.2/utils/dataPacketBuffer.d.ts +1 -1
  130. package/dist/ts4.2/version.d.ts +1 -1
  131. package/package.json +24 -16
  132. package/src/api/SignalClient.test.ts +102 -10
  133. package/src/api/SignalClient.ts +4 -2
  134. package/src/api/WebSocketStream.test.ts +0 -1
  135. package/src/e2ee/E2eeManager.ts +82 -30
  136. package/src/e2ee/types.ts +37 -8
  137. package/src/e2ee/utils.ts +7 -6
  138. package/src/e2ee/worker/DataCryptor.ts +6 -6
  139. package/src/e2ee/worker/FrameCryptor.test.ts +177 -4
  140. package/src/e2ee/worker/FrameCryptor.ts +94 -14
  141. package/src/e2ee/worker/ParticipantKeyHandler.test.ts +4 -4
  142. package/src/e2ee/worker/e2ee.worker.ts +13 -5
  143. package/src/e2ee/worker/naluUtils.ts +4 -4
  144. package/src/e2ee/worker/sifPayload.ts +10 -8
  145. package/src/index.ts +7 -0
  146. package/src/options.ts +8 -0
  147. package/src/packetTrailer/PacketTrailerManager.test.ts +172 -0
  148. package/src/packetTrailer/PacketTrailerManager.ts +250 -0
  149. package/src/packetTrailer/packetTrailer.test.ts +174 -0
  150. package/src/packetTrailer/packetTrailer.ts +276 -0
  151. package/src/packetTrailer/types.ts +75 -0
  152. package/src/packetTrailer/utils.test.ts +105 -0
  153. package/src/packetTrailer/utils.ts +50 -0
  154. package/src/packetTrailer/worker/packetTrailer.worker.ts +155 -0
  155. package/src/packetTrailer/worker/tsconfig.json +14 -0
  156. package/src/room/BackOffStrategy.test.ts +1 -1
  157. package/src/room/RTCEngine.test.ts +219 -0
  158. package/src/room/RTCEngine.ts +86 -20
  159. package/src/room/Room.test.ts +62 -1
  160. package/src/room/Room.ts +28 -5
  161. package/src/room/data-track/LocalDataTrack.ts +15 -7
  162. package/src/room/data-track/RemoteDataTrack.ts +8 -1
  163. package/src/room/data-track/depacketizer.test.ts +433 -1
  164. package/src/room/data-track/depacketizer.ts +79 -61
  165. package/src/room/data-track/frame.ts +2 -2
  166. package/src/room/data-track/incoming/IncomingDataTrackManager.test.ts +194 -0
  167. package/src/room/data-track/incoming/IncomingDataTrackManager.ts +21 -1
  168. package/src/room/data-track/incoming/pipeline.ts +13 -2
  169. package/src/room/data-track/outgoing/OutgoingDataTrackManager.test.ts +350 -198
  170. package/src/room/data-track/outgoing/OutgoingDataTrackManager.ts +9 -3
  171. package/src/room/data-track/outgoing/types.ts +4 -3
  172. package/src/room/data-track/packet/extensions.ts +2 -2
  173. package/src/room/data-track/packet/index.ts +6 -6
  174. package/src/room/data-track/packet/serializable.ts +1 -1
  175. package/src/room/data-track/types.ts +8 -0
  176. package/src/room/events.ts +2 -2
  177. package/src/room/participant/LocalParticipant.test.ts +81 -0
  178. package/src/room/participant/LocalParticipant.ts +48 -7
  179. package/src/room/participant/Participant.ts +1 -1
  180. package/src/room/participant/publishUtils.ts +1 -1
  181. package/src/room/track/PacketTrailerExtractor.ts +43 -0
  182. package/src/room/track/RemoteVideoTrack.ts +23 -2
  183. package/src/room/track/Track.ts +1 -1
  184. package/src/room/track/create.ts +0 -4
  185. package/src/room/track/options.ts +11 -0
  186. package/src/room/track/record.ts +1 -1
  187. package/src/room/track/utils.ts +4 -1
  188. package/src/room/utils.test.ts +14 -1
  189. package/src/room/utils.ts +17 -3
  190. package/src/test/MockMediaStreamTrack.ts +0 -1
  191. package/src/type-polyfills/non-shared-typed-arrays.d.ts +6 -0
  192. package/src/utils/dataPacketBuffer.ts +1 -1
  193. package/src/version.ts +1 -1
@@ -148,6 +148,8 @@ export default class LocalParticipant extends Participant {
148
148
  private waitUntilEngineConnected;
149
149
  private hasPermissionsToPublish;
150
150
  private publish;
151
+ private canPublishPacketTrailer;
152
+ private normalizeRequestedPacketTrailerOptions;
151
153
  get isLocal(): boolean;
152
154
  /** @internal
153
155
  * publish additional codec to existing track
@@ -163,7 +165,7 @@ export default class LocalParticipant extends Participant {
163
165
  * @param data Uint8Array of the payload. To send string data, use TextEncoder.encode
164
166
  * @param options optionally specify a `reliable`, `topic` and `destination`
165
167
  */
166
- publishData(data: Uint8Array, options?: DataPublishOptions): Promise<void>;
168
+ publishData(data: NonSharedUint8Array, options?: DataPublishOptions): Promise<void>;
167
169
  /**
168
170
  * Publish SIP DTMF message to the room.
169
171
  *
@@ -124,7 +124,7 @@ export type ParticipantEventCallbacks = {
124
124
  localSenderCreated: (sender: RTCRtpSender, track: Track) => void;
125
125
  participantMetadataChanged: (prevMetadata: string | undefined, participant?: any) => void;
126
126
  participantNameChanged: (name: string) => void;
127
- dataReceived: (payload: Uint8Array, kind: DataPacket_Kind, encryptionType?: Encryption_Type) => void;
127
+ dataReceived: (payload: NonSharedUint8Array, kind: DataPacket_Kind, encryptionType?: Encryption_Type) => void;
128
128
  sipDTMFReceived: (dtmf: SipDTMF) => void;
129
129
  transcriptionReceived: (transcription: TranscriptionSegment[], publication?: TrackPublication) => void;
130
130
  isSpeakingChanged: (speaking: boolean) => void;
@@ -0,0 +1,19 @@
1
+ import type { PacketTrailerMetadata } from '../../packetTrailer/types';
2
+ /**
3
+ * Caches packet trailer metadata extracted from received video frames,
4
+ * keyed by RTP timestamp so it can be looked up when the frame is displayed.
5
+ *
6
+ * Metadata is populated either by the packet trailer worker managed by
7
+ * `PacketTrailerManager` (non-E2EE) or by the E2EE FrameCryptor worker
8
+ * after decryption (E2EE).
9
+ *
10
+ * @experimental
11
+ */
12
+ export declare class PacketTrailerExtractor {
13
+ private metadataMap;
14
+ private activeSsrc;
15
+ storeMetadata(rtpTimestamp: number, ssrc: number, metadata: PacketTrailerMetadata): void;
16
+ lookupMetadata(rtpTimestamp: number): PacketTrailerMetadata | undefined;
17
+ dispose(): void;
18
+ }
19
+ //# sourceMappingURL=PacketTrailerExtractor.d.ts.map
@@ -1,5 +1,7 @@
1
+ import type { PacketTrailerMetadata } from '../../packetTrailer/types';
1
2
  import type { VideoReceiverStats } from '../stats';
2
3
  import type { LoggerOptions } from '../types';
4
+ import type { PacketTrailerExtractor } from './PacketTrailerExtractor';
3
5
  import RemoteTrack from './RemoteTrack';
4
6
  import { Track } from './Track';
5
7
  import type { AdaptiveStreamSettings } from './types';
@@ -9,8 +11,22 @@ export default class RemoteVideoTrack extends RemoteTrack<Track.Kind.Video> {
9
11
  private adaptiveStreamSettings?;
10
12
  private lastVisible?;
11
13
  private lastDimensions?;
14
+ /** @internal */
15
+ packetTrailerExtractor?: PacketTrailerExtractor;
12
16
  constructor(mediaTrack: MediaStreamTrack, sid: string, receiver: RTCRtpReceiver, adaptiveStreamSettings?: AdaptiveStreamSettings, loggerOptions?: LoggerOptions);
13
17
  get isAdaptiveStream(): boolean;
18
+ /**
19
+ * Look up frame-level metadata for a given RTP timestamp.
20
+ * Use with the `TrackEvent.TimeSyncUpdate` event to correlate displayed frames
21
+ * with their capture-time metadata.
22
+ *
23
+ * Requires the room to be configured with the `packetTrailer` worker option
24
+ * and the publishing track to have packet trailer features enabled.
25
+ *
26
+ */
27
+ lookupFrameMetadata({ rtpTimestamp, }: {
28
+ rtpTimestamp: number;
29
+ }): PacketTrailerMetadata | undefined;
14
30
  setStreamState(value: Track.StreamState): void;
15
31
  /**
16
32
  * Note: When using adaptiveStream, you need to use remoteVideoTrack.attach() to add the track to a HTMLVideoElement, otherwise your video tracks might never start
@@ -148,7 +148,7 @@ export type TrackEventCallbacks = {
148
148
  timestamp: number;
149
149
  rtpTimestamp: number;
150
150
  }) => void;
151
- preConnectBufferFlushed: (buffer: Uint8Array[]) => void;
151
+ preConnectBufferFlushed: (buffer: NonSharedUint8Array[]) => void;
152
152
  cpuConstrained: () => void;
153
153
  };
154
154
  export {};
@@ -1,3 +1,4 @@
1
+ import type { PacketTrailerPublishOptions } from '../../packetTrailer/types';
1
2
  import type { Track } from './Track';
2
3
  import type { AudioProcessorOptions, TrackProcessor, VideoProcessorOptions } from './processor/types';
3
4
  export interface TrackPublishDefaults {
@@ -111,6 +112,15 @@ export interface TrackPublishDefaults {
111
112
  * Defaults to false.
112
113
  */
113
114
  preConnectBuffer?: boolean;
115
+ /**
116
+ * Packet trailer metadata to append to published video frames.
117
+ *
118
+ * Requires either room-level packet trailer worker configuration or E2EE,
119
+ * because encoded frame transforms are used to write the trailer.
120
+ *
121
+ * @experimental
122
+ */
123
+ packetTrailer?: PacketTrailerPublishOptions;
114
124
  }
115
125
  /**
116
126
  * Options when publishing tracks
@@ -1,4 +1,4 @@
1
- import { ChatMessage as ChatMessageModel, ClientInfo, DisconnectReason, Transcription as TranscriptionModel } from '@livekit/protocol';
1
+ import { ChatMessage as ChatMessageModel, ClientInfo, ClientInfo_Capability, DisconnectReason, Transcription as TranscriptionModel } from '@livekit/protocol';
2
2
  import type { Throws } from '@livekit/throws-transformer/throws';
3
3
  import TypedPromise from '../utils/TypedPromise';
4
4
  import type { BrowserDetails } from '../utils/browserParser';
@@ -40,6 +40,7 @@ export declare function supportsAudioOutputSelection(): boolean;
40
40
  export declare function isBrowserSupported(): boolean;
41
41
  export declare function isFireFox(): boolean;
42
42
  export declare function isChromiumBased(): boolean;
43
+ export declare function isScriptTransformSupportedForWorker(): boolean;
43
44
  export declare function isSafari(): boolean;
44
45
  export declare function isSafariBased(): boolean;
45
46
  export declare function isSafari17Based(): boolean;
@@ -67,7 +68,7 @@ export interface ObservableMediaElement extends HTMLMediaElement {
67
68
  handleResize: (entry: ResizeObserverEntry) => void;
68
69
  handleVisibilityChanged: (entry: IntersectionObserverEntry) => void;
69
70
  }
70
- export declare function getClientInfo(): ClientInfo;
71
+ export declare function getClientInfo(capabilities?: ClientInfo_Capability[]): ClientInfo;
71
72
  export declare function getEmptyVideoStreamTrack(): MediaStreamTrack;
72
73
  export declare function createDummyVideoStreamTrack(width?: number, height?: number, enabled?: boolean, paintContent?: boolean): MediaStreamTrack;
73
74
  export declare function getEmptyAudioStreamTrack(): MediaStreamTrack;
@@ -143,7 +144,7 @@ export declare function isLocalPub(pub: TrackPublication | undefined): pub is Lo
143
144
  export declare function isRemoteVideoTrack(track: Track | undefined): track is RemoteVideoTrack;
144
145
  export declare function isLocalParticipant(p: Participant): p is LocalParticipant;
145
146
  export declare function isRemoteParticipant(p: Participant): p is RemoteParticipant;
146
- export declare function splitUtf8(s: string, n: number): Uint8Array[];
147
+ export declare function splitUtf8(s: string, n: number): NonSharedUint8Array[];
147
148
  export declare function extractMaxAgeFromRequestHeaders(headers: Headers): number | undefined;
148
149
  export declare function isCompressionStreamSupported(): boolean;
149
150
  //# sourceMappingURL=utils.d.ts.map
@@ -1,5 +1,5 @@
1
1
  export interface DataPacketItem {
2
- data: Uint8Array;
2
+ data: NonSharedUint8Array;
3
3
  sequence: number;
4
4
  }
5
5
  export declare class DataPacketBuffer {
@@ -1,3 +1,3 @@
1
1
  export declare const version: string;
2
- export declare const protocolVersion = 16;
2
+ export declare const protocolVersion = 17;
3
3
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livekit-client",
3
- "version": "2.18.8",
3
+ "version": "2.18.10",
4
4
  "description": "JavaScript/TypeScript client SDK for LiveKit",
5
5
  "main": "./dist/livekit-client.umd.js",
6
6
  "unpkg": "./dist/livekit-client.umd.js",
@@ -15,6 +15,11 @@
15
15
  "types": "./dist/src/e2ee/worker/e2ee.worker.d.ts",
16
16
  "import": "./dist/livekit-client.e2ee.worker.mjs",
17
17
  "require": "./dist/livekit-client.e2ee.worker.js"
18
+ },
19
+ "./packet-trailer-worker": {
20
+ "types": "./dist/src/packetTrailer/worker/packetTrailer.worker.d.ts",
21
+ "import": "./dist/livekit-client.pt.worker.mjs",
22
+ "require": "./dist/livekit-client.pt.worker.js"
18
23
  }
19
24
  },
20
25
  "files": [
@@ -29,6 +34,9 @@
29
34
  ],
30
35
  "./dist/src/e2ee/worker/e2ee.worker.d.ts": [
31
36
  "./dist/ts4.2/e2ee/worker/e2ee.worker.d.ts"
37
+ ],
38
+ "./dist/src/packetTrailer/worker/packetTrailer.worker.d.ts": [
39
+ "./dist/ts4.2/packetTrailer/worker/packetTrailer.worker.d.ts"
32
40
  ]
33
41
  }
34
42
  },
@@ -37,7 +45,7 @@
37
45
  "license": "Apache-2.0",
38
46
  "dependencies": {
39
47
  "@livekit/mutex": "1.1.1",
40
- "@livekit/protocol": "1.45.3",
48
+ "@livekit/protocol": "1.45.8",
41
49
  "events": "^3.3.0",
42
50
  "jose": "^6.1.0",
43
51
  "loglevel": "^1.9.2",
@@ -51,28 +59,28 @@
51
59
  },
52
60
  "devDependencies": {
53
61
  "@babel/core": "7.29.0",
54
- "@babel/preset-env": "7.29.0",
62
+ "@babel/preset-env": "7.29.2",
55
63
  "@bufbuild/protoc-gen-es": "^1.10.0",
56
- "@changesets/cli": "2.29.8",
57
- "@eslint/js": "9.39.2",
64
+ "@changesets/cli": "2.31.0",
65
+ "@eslint/js": "10.0.1",
58
66
  "@livekit/changesets-changelog-github": "^0.0.4",
59
67
  "@livekit/throws-transformer": "^0.1.3",
60
68
  "@rollup/plugin-babel": "7.0.0",
61
- "@rollup/plugin-commonjs": "28.0.9",
69
+ "@rollup/plugin-commonjs": "29.0.2",
62
70
  "@rollup/plugin-json": "6.1.0",
63
71
  "@rollup/plugin-node-resolve": "16.0.3",
64
72
  "@rollup/plugin-terser": "^0.4.4",
65
73
  "@size-limit/file": "^11.2.0",
66
74
  "@size-limit/webpack": "^11.2.0",
67
- "@stylistic/eslint-plugin": "^3.1.0",
75
+ "@stylistic/eslint-plugin": "^5.10.0",
68
76
  "@trivago/prettier-plugin-sort-imports": "^5.0.0",
69
77
  "@types/events": "^3.0.3",
70
78
  "@types/sdp-transform": "2.15.0",
71
79
  "@types/ua-parser-js": "0.7.39",
72
- "@typescript-eslint/eslint-plugin": "7.18.0",
73
- "@typescript-eslint/parser": "7.18.0",
80
+ "@typescript-eslint/eslint-plugin": "8.59.2",
81
+ "@typescript-eslint/parser": "8.59.2",
74
82
  "downlevel-dts": "^0.11.0",
75
- "eslint": "9.39.2",
83
+ "eslint": "10.2.1",
76
84
  "eslint-config-airbnb-extended": "^2.3.2",
77
85
  "eslint-config-prettier": "10.1.8",
78
86
  "eslint-plugin-compat": "^6.0.2",
@@ -83,20 +91,20 @@
83
91
  "happy-dom": "^20.0.0",
84
92
  "jsdom": "^26.1.0",
85
93
  "prettier": "^3.4.2",
86
- "rollup": "4.59.0",
94
+ "rollup": "4.60.2",
87
95
  "rollup-plugin-delete": "^2.1.0",
88
- "rollup-plugin-typescript2": "0.36.0",
96
+ "rollup-plugin-typescript2": "0.37.0",
89
97
  "size-limit": "^11.2.0",
90
98
  "tsx": "^4.21.0",
91
- "typedoc": "0.28.16",
99
+ "typedoc": "0.28.19",
92
100
  "typedoc-plugin-no-inherit": "1.6.1",
93
- "typescript": "5.8.3",
101
+ "typescript": "5.9.3",
94
102
  "typescript-eslint": "^8.47.0",
95
- "vite": "7.3.1",
103
+ "vite": "7.3.2",
96
104
  "vitest": "^3.0.0"
97
105
  },
98
106
  "scripts": {
99
- "build": "rollup --config --bundleConfigAsCjs && rollup --config rollup.config.worker.js --bundleConfigAsCjs && pnpm downlevel-dts",
107
+ "build": "rollup --config --bundleConfigAsCjs && rollup --config rollup.config.worker.js --bundleConfigAsCjs && rollup --config rollup.config.pt-worker.js --bundleConfigAsCjs && pnpm downlevel-dts",
100
108
  "build:clean": "rm -rf ./dist && pnpm build",
101
109
  "build:watch": "rollup --watch --config --bundleConfigAsCjs",
102
110
  "build:worker:watch": "rollup --watch --config rollup.config.worker.js --bundleConfigAsCjs",
@@ -1,10 +1,14 @@
1
1
  import {
2
+ ClientInfo_Capability,
2
3
  DisconnectReason,
4
+ JoinRequest,
3
5
  JoinResponse,
4
6
  LeaveRequest,
5
7
  ReconnectResponse,
6
8
  SignalRequest,
7
9
  SignalResponse,
10
+ WrappedJoinRequest,
11
+ WrappedJoinRequest_Compression,
8
12
  } from '@livekit/protocol';
9
13
  import { beforeEach, describe, expect, it, vi } from 'vitest';
10
14
  import { ConnectionError, ConnectionErrorReason } from '../room/errors';
@@ -60,6 +64,7 @@ interface MockWebSocketStreamOptions {
60
64
  connection?: WebSocketConnection;
61
65
  opened?: Promise<WebSocketConnection>;
62
66
  closed?: Promise<WebSocketCloseInfo>;
67
+ onUrl?: (url: string) => void;
63
68
  readyState?: number;
64
69
  }
65
70
 
@@ -69,18 +74,19 @@ function mockWebSocketStream(options: MockWebSocketStreamOptions = {}) {
69
74
  opened = connection ? Promise.resolve(connection) : new Promise(() => {}),
70
75
  closed = new Promise(() => {}),
71
76
  readyState = 1,
77
+ onUrl,
72
78
  } = options;
73
79
 
74
- return vi.mocked(WebSocketStream).mockImplementationOnce(
75
- () =>
76
- ({
77
- url: 'wss://test.livekit.io',
78
- opened,
79
- closed,
80
- close: vi.fn(),
81
- readyState,
82
- }) as any,
83
- );
80
+ return vi.mocked(WebSocketStream).mockImplementationOnce((url) => {
81
+ onUrl?.(url);
82
+ return {
83
+ url: 'wss://test.livekit.io',
84
+ opened,
85
+ closed,
86
+ close: vi.fn(),
87
+ readyState,
88
+ } as any;
89
+ });
84
90
  }
85
91
 
86
92
  describe('SignalClient.connect', () => {
@@ -99,6 +105,47 @@ describe('SignalClient.connect', () => {
99
105
  signalClient = new SignalClient(false);
100
106
  });
101
107
 
108
+ async function decodeJoinRequestFromUrl(url: string): Promise<JoinRequest> {
109
+ const joinRequestParam = new URL(url).searchParams.get('join_request');
110
+ expect(joinRequestParam).toBeTruthy();
111
+
112
+ const paddedBase64Url = joinRequestParam!.padEnd(
113
+ joinRequestParam!.length + ((4 - (joinRequestParam!.length % 4)) % 4),
114
+ '=',
115
+ );
116
+ const binaryString = atob(paddedBase64Url.replace(/-/g, '+').replace(/_/g, '/'));
117
+ const wrappedBytes = new Uint8Array(binaryString.length);
118
+ for (let i = 0; i < binaryString.length; i += 1) {
119
+ wrappedBytes[i] = binaryString.charCodeAt(i);
120
+ }
121
+
122
+ const wrappedJoinRequest = WrappedJoinRequest.fromBinary(wrappedBytes);
123
+ if (wrappedJoinRequest.compression === WrappedJoinRequest_Compression.NONE) {
124
+ return JoinRequest.fromBinary(wrappedJoinRequest.joinRequest);
125
+ }
126
+
127
+ const stream = new DecompressionStream('gzip');
128
+ const writer = stream.writable.getWriter();
129
+ writer.write(wrappedJoinRequest.joinRequest);
130
+ writer.close();
131
+
132
+ const chunks: Uint8Array[] = [];
133
+ const reader = stream.readable.getReader();
134
+ while (true) {
135
+ const { done, value } = await reader.read();
136
+ if (done) break;
137
+ chunks.push(value);
138
+ }
139
+ const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
140
+ const bytes = new Uint8Array(totalLength);
141
+ let offset = 0;
142
+ for (const chunk of chunks) {
143
+ bytes.set(chunk, offset);
144
+ offset += chunk.length;
145
+ }
146
+ return JoinRequest.fromBinary(bytes);
147
+ }
148
+
102
149
  describe('Happy Path - Initial Join', () => {
103
150
  it('should successfully connect and receive join response', async () => {
104
151
  const joinResponse = createJoinResponse();
@@ -113,6 +160,51 @@ describe('SignalClient.connect', () => {
113
160
  expect(result).toEqual(joinResponse);
114
161
  expect(signalClient.currentState).toBe(SignalConnectionState.CONNECTED);
115
162
  });
163
+
164
+ it('does not advertise packet trailer capability by default', async () => {
165
+ const joinResponse = createJoinResponse();
166
+ const signalResponse = createSignalResponse('join', joinResponse);
167
+ const mockReadable = createMockReadableStream([signalResponse]);
168
+ const mockConnection = createMockConnection(mockReadable);
169
+ let capturedUrl = '';
170
+
171
+ mockWebSocketStream({
172
+ connection: mockConnection,
173
+ onUrl: (url) => {
174
+ capturedUrl = url;
175
+ },
176
+ });
177
+
178
+ await signalClient.join('wss://test.livekit.io', 'test-token', defaultOptions);
179
+
180
+ const joinRequest = await decodeJoinRequestFromUrl(capturedUrl);
181
+ expect(joinRequest.clientInfo?.capabilities).toEqual([]);
182
+ });
183
+
184
+ it('advertises packet trailer capability when provided', async () => {
185
+ const joinResponse = createJoinResponse();
186
+ const signalResponse = createSignalResponse('join', joinResponse);
187
+ const mockReadable = createMockReadableStream([signalResponse]);
188
+ const mockConnection = createMockConnection(mockReadable);
189
+ let capturedUrl = '';
190
+
191
+ mockWebSocketStream({
192
+ connection: mockConnection,
193
+ onUrl: (url) => {
194
+ capturedUrl = url;
195
+ },
196
+ });
197
+
198
+ await signalClient.join('wss://test.livekit.io', 'test-token', {
199
+ ...defaultOptions,
200
+ clientInfoCapabilities: [ClientInfo_Capability.CAP_PACKET_TRAILER],
201
+ });
202
+
203
+ const joinRequest = await decodeJoinRequestFromUrl(capturedUrl);
204
+ expect(joinRequest.clientInfo?.capabilities).toEqual([
205
+ ClientInfo_Capability.CAP_PACKET_TRAILER,
206
+ ]);
207
+ });
116
208
  });
117
209
 
118
210
  describe('Happy Path - Reconnect', () => {
@@ -3,6 +3,7 @@ import {
3
3
  AddTrackRequest,
4
4
  AudioTrackFeature,
5
5
  ClientInfo,
6
+ ClientInfo_Capability,
6
7
  ConnectionQualityUpdate,
7
8
  ConnectionSettings,
8
9
  DataTrackSubscriberHandles,
@@ -83,6 +84,7 @@ interface ConnectOpts extends SignalOptions {
83
84
  export interface SignalOptions {
84
85
  autoSubscribe: boolean;
85
86
  adaptiveStream?: boolean;
87
+ clientInfoCapabilities?: ClientInfo_Capability[];
86
88
  maxRetries: number;
87
89
  e2eeEnabled: boolean;
88
90
  websocketTimeout: number;
@@ -320,7 +322,7 @@ export class SignalClient {
320
322
  this.connectOptions = opts;
321
323
  this.useV0SignalPath = useV0Path;
322
324
 
323
- const clientInfo = getClientInfo();
325
+ const clientInfo = getClientInfo(opts.clientInfoCapabilities);
324
326
  const params = useV0Path
325
327
  ? createConnectionParams(token, clientInfo, opts)
326
328
  : await createJoinRequestConnectionParams(token, clientInfo, opts, publisherOffer);
@@ -771,7 +773,7 @@ export class SignalClient {
771
773
  if (this.useJSON) {
772
774
  await this.streamWriter.write(req.toJsonString());
773
775
  } else {
774
- await this.streamWriter.write(req.toBinary());
776
+ await this.streamWriter.write((req.toBinary() as NonSharedUint8Array).buffer);
775
777
  }
776
778
  } catch (e) {
777
779
  this.log.error('error sending signal message', { error: e });
@@ -1,4 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
1
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
2
  import { WebSocketStream } from './WebSocketStream';
4
3