livekit-client 2.19.1 → 2.20.0

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 (124) 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 +204 -145
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +664 -526
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.fm.worker.js +2 -0
  8. package/dist/{livekit-client.pt.worker.js.map → livekit-client.fm.worker.js.map} +1 -1
  9. package/dist/{livekit-client.pt.worker.mjs → livekit-client.fm.worker.mjs} +133 -99
  10. package/dist/livekit-client.fm.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.map +1 -1
  14. package/dist/src/e2ee/E2eeManager.d.ts +1 -1
  15. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  16. package/dist/src/e2ee/types.d.ts +5 -5
  17. package/dist/src/e2ee/types.d.ts.map +1 -1
  18. package/dist/src/e2ee/worker/FrameCryptor.d.ts +20 -10
  19. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  20. package/dist/src/{packetTrailer/PacketTrailerManager.d.ts → frameMetadata/FrameMetadataManager.d.ts} +8 -4
  21. package/dist/src/{packetTrailer/PacketTrailerManager.d.ts.map → frameMetadata/FrameMetadataManager.d.ts.map} +1 -1
  22. package/dist/src/{packetTrailer/packetTrailer.d.ts → frameMetadata/frameMetadata.d.ts} +7 -7
  23. package/dist/src/frameMetadata/frameMetadata.d.ts.map +1 -0
  24. package/dist/src/{packetTrailer → frameMetadata}/types.d.ts +10 -6
  25. package/dist/src/frameMetadata/types.d.ts.map +1 -0
  26. package/dist/src/frameMetadata/utils.d.ts +9 -0
  27. package/dist/src/{packetTrailer → frameMetadata}/utils.d.ts.map +1 -1
  28. package/dist/src/frameMetadata/worker/frameMetadata.worker.d.ts +2 -0
  29. package/dist/src/frameMetadata/worker/frameMetadata.worker.d.ts.map +1 -0
  30. package/dist/src/index.d.ts +10 -2
  31. package/dist/src/index.d.ts.map +1 -1
  32. package/dist/src/options.d.ts +8 -4
  33. package/dist/src/options.d.ts.map +1 -1
  34. package/dist/src/room/PCTransport.d.ts +1 -0
  35. package/dist/src/room/PCTransport.d.ts.map +1 -1
  36. package/dist/src/room/PCTransportManager.d.ts +1 -0
  37. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  38. package/dist/src/room/RTCEngine.d.ts +11 -1
  39. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  40. package/dist/src/room/Room.d.ts +2 -2
  41. package/dist/src/room/Room.d.ts.map +1 -1
  42. package/dist/src/room/participant/LocalParticipant.d.ts +2 -2
  43. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  44. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  45. package/dist/src/room/rpc/client/RpcClientManager.d.ts.map +1 -1
  46. package/dist/src/room/token-source/TokenSource.d.ts.map +1 -1
  47. package/dist/src/room/token-source/types.d.ts +1 -0
  48. package/dist/src/room/token-source/types.d.ts.map +1 -1
  49. package/dist/src/room/token-source/utils.d.ts.map +1 -1
  50. package/dist/src/room/track/FrameMetadataExtractor.d.ts +19 -0
  51. package/dist/src/room/track/FrameMetadataExtractor.d.ts.map +1 -0
  52. package/dist/src/room/track/RemoteVideoTrack.d.ts +7 -7
  53. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  54. package/dist/src/room/track/options.d.ts +17 -5
  55. package/dist/src/room/track/options.d.ts.map +1 -1
  56. package/dist/ts4.2/e2ee/E2eeManager.d.ts +1 -1
  57. package/dist/ts4.2/e2ee/types.d.ts +5 -5
  58. package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +19 -9
  59. package/dist/ts4.2/{packetTrailer/PacketTrailerManager.d.ts → frameMetadata/FrameMetadataManager.d.ts} +8 -4
  60. package/dist/ts4.2/{packetTrailer/packetTrailer.d.ts → frameMetadata/frameMetadata.d.ts} +7 -7
  61. package/dist/ts4.2/{packetTrailer → frameMetadata}/types.d.ts +10 -6
  62. package/dist/ts4.2/frameMetadata/utils.d.ts +9 -0
  63. package/dist/ts4.2/frameMetadata/worker/frameMetadata.worker.d.ts +2 -0
  64. package/dist/ts4.2/index.d.ts +9 -3
  65. package/dist/ts4.2/options.d.ts +8 -4
  66. package/dist/ts4.2/room/PCTransport.d.ts +1 -0
  67. package/dist/ts4.2/room/PCTransportManager.d.ts +1 -0
  68. package/dist/ts4.2/room/RTCEngine.d.ts +11 -1
  69. package/dist/ts4.2/room/Room.d.ts +2 -2
  70. package/dist/ts4.2/room/participant/LocalParticipant.d.ts +2 -2
  71. package/dist/ts4.2/room/token-source/types.d.ts +1 -0
  72. package/dist/ts4.2/room/track/FrameMetadataExtractor.d.ts +19 -0
  73. package/dist/ts4.2/room/track/RemoteVideoTrack.d.ts +7 -7
  74. package/dist/ts4.2/room/track/options.d.ts +17 -5
  75. package/package.json +25 -20
  76. package/src/api/SignalClient.test.ts +4 -4
  77. package/src/api/SignalClient.ts +7 -3
  78. package/src/api/WebSocketStream.test.ts +7 -7
  79. package/src/e2ee/E2eeManager.ts +13 -11
  80. package/src/e2ee/types.ts +5 -5
  81. package/src/e2ee/worker/FrameCryptor.test.ts +5 -5
  82. package/src/e2ee/worker/FrameCryptor.ts +69 -30
  83. package/src/e2ee/worker/e2ee.worker.ts +5 -5
  84. package/src/e2ee/worker/tsconfig.json +4 -1
  85. package/src/{packetTrailer/PacketTrailerManager.test.ts → frameMetadata/FrameMetadataManager.test.ts} +10 -8
  86. package/src/{packetTrailer/PacketTrailerManager.ts → frameMetadata/FrameMetadataManager.ts} +21 -15
  87. package/src/{packetTrailer/packetTrailer.test.ts → frameMetadata/frameMetadata.test.ts} +1 -1
  88. package/src/{packetTrailer/packetTrailer.ts → frameMetadata/frameMetadata.ts} +9 -9
  89. package/src/{packetTrailer → frameMetadata}/types.ts +12 -6
  90. package/src/{packetTrailer → frameMetadata}/utils.test.ts +19 -19
  91. package/src/{packetTrailer → frameMetadata}/utils.ts +11 -11
  92. package/src/{packetTrailer/worker/packetTrailer.worker.ts → frameMetadata/worker/frameMetadata.worker.ts} +5 -5
  93. package/src/{packetTrailer → frameMetadata}/worker/tsconfig.json +4 -1
  94. package/src/index.ts +13 -2
  95. package/src/options.ts +9 -4
  96. package/src/room/PCTransport.ts +4 -0
  97. package/src/room/PCTransportManager.ts +4 -0
  98. package/src/room/RTCEngine.test.ts +143 -9
  99. package/src/room/RTCEngine.ts +156 -48
  100. package/src/room/Room.ts +10 -10
  101. package/src/room/participant/LocalParticipant.test.ts +19 -19
  102. package/src/room/participant/LocalParticipant.ts +21 -16
  103. package/src/room/participant/publishUtils.test.ts +6 -0
  104. package/src/room/participant/publishUtils.ts +4 -1
  105. package/src/room/rpc/client/RpcClientManager.ts +6 -3
  106. package/src/room/rpc/server/RpcServerManager.ts +1 -1
  107. package/src/room/token-source/TokenSource.ts +9 -23
  108. package/src/room/token-source/types.ts +1 -0
  109. package/src/room/token-source/utils.ts +1 -0
  110. package/src/room/track/{PacketTrailerExtractor.ts → FrameMetadataExtractor.ts} +8 -8
  111. package/src/room/track/RemoteVideoTrack.ts +7 -11
  112. package/src/room/track/options.ts +19 -5
  113. package/dist/livekit-client.pt.worker.js +0 -2
  114. package/dist/livekit-client.pt.worker.mjs.map +0 -1
  115. package/dist/src/packetTrailer/packetTrailer.d.ts.map +0 -1
  116. package/dist/src/packetTrailer/types.d.ts.map +0 -1
  117. package/dist/src/packetTrailer/utils.d.ts +0 -9
  118. package/dist/src/packetTrailer/worker/packetTrailer.worker.d.ts +0 -2
  119. package/dist/src/packetTrailer/worker/packetTrailer.worker.d.ts.map +0 -1
  120. package/dist/src/room/track/PacketTrailerExtractor.d.ts +0 -19
  121. package/dist/src/room/track/PacketTrailerExtractor.d.ts.map +0 -1
  122. package/dist/ts4.2/packetTrailer/utils.d.ts +0 -9
  123. package/dist/ts4.2/packetTrailer/worker/packetTrailer.worker.d.ts +0 -2
  124. package/dist/ts4.2/room/track/PacketTrailerExtractor.d.ts +0 -19
@@ -120,16 +120,25 @@ export default class RTCEngine extends RTCEngine_base {
120
120
  private configure;
121
121
  private setupSignalClientCallbacks;
122
122
  private makeRTCConfiguration;
123
+ /**
124
+ * Populate the publisher PC so its first offer carries the data channels + recvonly media
125
+ * sections. Required for every V1 connection: Firefox only binds receive decoders for media
126
+ * present in that first offer, and the offer-with-join path needs the sections to
127
+ * build a meaningful initial offer. Must be called on a configured pcManager.
128
+ */
129
+ private applyInitialPublisherLayout;
123
130
  private addMediaSections;
124
131
  private createDataChannels;
125
132
  private handleDataChannel;
126
133
  private handleDataMessage;
127
134
  private handleDataTrackMessage;
128
135
  private handleDataError;
136
+ private handleDataChannelClose;
129
137
  private handleBufferedAmountLow;
130
138
  createSender(track: LocalTrack, opts: TrackPublishOptions, encodings?: RTCRtpEncodingParameters[]): Promise<RTCRtpSender>;
131
139
  createSimulcastSender(track: LocalVideoTrack, simulcastTrack: SimulcastTrackInfo, opts: TrackPublishOptions, encodings?: RTCRtpEncodingParameters[]): Promise<RTCRtpSender | undefined>;
132
- private setupPacketTrailerSender;
140
+ private get frameMetadataWorker();
141
+ private setupFrameMetadataSender;
133
142
  private createTransceiverRTCRtpSender;
134
143
  private createSimulcastTransceiverSender;
135
144
  private createRTCRtpSender;
@@ -162,6 +171,7 @@ export default class RTCEngine extends RTCEngine_base {
162
171
  sendSyncState(remoteTracks: RemoteTrackPublication[], localTracks: LocalTrackPublication[], localDataTrackInfos: Array<DataTrackInfo>): void;
163
172
  failNext(): void;
164
173
  failNextV1Path(): void;
174
+ private onRtpMapAvailable;
165
175
  private dataChannelsInfo;
166
176
  private clearReconnectTimeout;
167
177
  private clearPendingReconnect;
@@ -68,7 +68,7 @@ declare class Room extends Room_base {
68
68
  private connectFuture?;
69
69
  private disconnectLock;
70
70
  private e2eeManager;
71
- private packetTrailerManager;
71
+ private frameMetadataManager;
72
72
  private e2eeStateMutex;
73
73
  private connectionReconcileInterval?;
74
74
  private regionUrlProvider?;
@@ -135,7 +135,7 @@ declare class Room extends Room_base {
135
135
  */
136
136
  setE2EEEnabled(enabled: boolean): Promise<void>;
137
137
  private setupE2EE;
138
- private setupPacketTrailer;
138
+ private setupFrameMetadata;
139
139
  private get logContext();
140
140
  /**
141
141
  * if the current room has a participant with `recorder: true` in its JWT grant
@@ -146,8 +146,8 @@ export default class LocalParticipant extends Participant {
146
146
  private waitUntilEngineConnected;
147
147
  private hasPermissionsToPublish;
148
148
  private publish;
149
- private canPublishPacketTrailer;
150
- private normalizeRequestedPacketTrailerOptions;
149
+ private canPublishFrameMetadata;
150
+ private normalizeRequestedFrameMetadataOptions;
151
151
  get isLocal(): boolean;
152
152
  /** @internal
153
153
  * publish additional codec to existing track
@@ -48,6 +48,7 @@ export type TokenSourceFetchOptions = {
48
48
  };
49
49
  agentName?: string;
50
50
  agentMetadata?: string;
51
+ deployment?: string;
51
52
  };
52
53
  /** A Configurable TokenSource is a token source that takes a
53
54
  * {@link TokenSourceFetchOptions} object as input and returns a deterministic
@@ -0,0 +1,19 @@
1
+ import type { FrameMetadata } from '../../frameMetadata/types';
2
+ /**
3
+ * Caches frame 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 frame metadata worker managed by
7
+ * `FrameMetadataManager` (non-E2EE) or by the E2EE FrameCryptor worker
8
+ * after decryption (E2EE).
9
+ *
10
+ * @experimental
11
+ */
12
+ export declare class FrameMetadataExtractor {
13
+ private metadataMap;
14
+ private activeSsrc;
15
+ storeMetadata(rtpTimestamp: number, ssrc: number, metadata: FrameMetadata): void;
16
+ lookupMetadata(rtpTimestamp: number): FrameMetadata | undefined;
17
+ dispose(): void;
18
+ }
19
+ //# sourceMappingURL=FrameMetadataExtractor.d.ts.map
@@ -1,7 +1,7 @@
1
- import type { PacketTrailerMetadata } from '../../packetTrailer/types';
1
+ import type { FrameMetadata } from '../../frameMetadata/types';
2
2
  import type { VideoReceiverStats } from '../stats';
3
3
  import type { LoggerOptions } from '../types';
4
- import type { PacketTrailerExtractor } from './PacketTrailerExtractor';
4
+ import type { FrameMetadataExtractor } from './FrameMetadataExtractor';
5
5
  import RemoteTrack from './RemoteTrack';
6
6
  import { Track } from './Track';
7
7
  import type { AdaptiveStreamSettings } from './types';
@@ -12,7 +12,7 @@ export default class RemoteVideoTrack extends RemoteTrack<Track.Kind.Video> {
12
12
  private lastVisible?;
13
13
  private lastDimensions?;
14
14
  /** @internal */
15
- packetTrailerExtractor?: PacketTrailerExtractor;
15
+ frameMetadataExtractor?: FrameMetadataExtractor;
16
16
  constructor(mediaTrack: MediaStreamTrack, sid: string, receiver: RTCRtpReceiver, adaptiveStreamSettings?: AdaptiveStreamSettings, loggerOptions?: LoggerOptions);
17
17
  get isAdaptiveStream(): boolean;
18
18
  /**
@@ -20,13 +20,13 @@ export default class RemoteVideoTrack extends RemoteTrack<Track.Kind.Video> {
20
20
  * Use with the `TrackEvent.TimeSyncUpdate` event to correlate displayed frames
21
21
  * with their capture-time metadata.
22
22
  *
23
- * Requires the room to be configured with the `packetTrailer` worker option
24
- * and the publishing track to have packet trailer features enabled.
23
+ * Requires the room to be configured with the `frameMetadata` worker option
24
+ * and the publishing track to have frame metadata features enabled.
25
25
  *
26
26
  */
27
- lookupFrameMetadata({ rtpTimestamp, }: {
27
+ lookupFrameMetadata({ rtpTimestamp }: {
28
28
  rtpTimestamp: number;
29
- }): PacketTrailerMetadata | undefined;
29
+ }): FrameMetadata | undefined;
30
30
  setStreamState(value: Track.StreamState): void;
31
31
  /**
32
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
@@ -1,4 +1,4 @@
1
- import type { PacketTrailerPublishOptions } from '../../packetTrailer/types';
1
+ import type { FrameMetadataPublishOptions } from '../../frameMetadata/types';
2
2
  import type { Track } from './Track';
3
3
  import type { AudioProcessorOptions, TrackProcessor, VideoProcessorOptions } from './processor/types';
4
4
  export interface TrackPublishDefaults {
@@ -113,14 +113,18 @@ export interface TrackPublishDefaults {
113
113
  */
114
114
  preConnectBuffer?: boolean;
115
115
  /**
116
- * Packet trailer metadata to append to published video frames.
116
+ * Frame metadata to append to published video frames.
117
117
  *
118
- * Requires either room-level packet trailer worker configuration or E2EE,
119
- * because encoded frame transforms are used to write the trailer.
118
+ * Requires either room-level frame metadata worker configuration or E2EE,
119
+ * because encoded frame transforms are used to write the metadata.
120
120
  *
121
121
  * @experimental
122
122
  */
123
- packetTrailer?: PacketTrailerPublishOptions;
123
+ frameMetadata?: FrameMetadataPublishOptions;
124
+ /**
125
+ * @deprecated Use {@link TrackPublishDefaults.frameMetadata} instead.
126
+ */
127
+ packetTrailer?: FrameMetadataPublishOptions;
124
128
  }
125
129
  /**
126
130
  * Options when publishing tracks
@@ -248,6 +252,14 @@ export interface AudioCaptureOptions {
248
252
  * @see https://w3c.github.io/mediacapture-extensions/#voiceisolation-constraint
249
253
  */
250
254
  voiceIsolation?: ConstrainBoolean;
255
+ /**
256
+ * @experimental
257
+ * when capturing system/screen-share audio, excludes the local participant's own audio
258
+ * from the captured stream to prevent echo. Browser support is not widespread yet
259
+ * (as of mid 2026, Chromium-based browsers only).
260
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/restrictOwnAudio
261
+ */
262
+ restrictOwnAudio?: ConstrainBoolean;
251
263
  /**
252
264
  * the sample rate or range of sample rates which are acceptable and/or required.
253
265
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livekit-client",
3
- "version": "2.19.1",
3
+ "version": "2.20.0",
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",
@@ -17,9 +17,14 @@
17
17
  "require": "./dist/livekit-client.e2ee.worker.js"
18
18
  },
19
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"
20
+ "types": "./dist/src/frameMetadata/worker/frameMetadata.worker.d.ts",
21
+ "import": "./dist/livekit-client.fm.worker.mjs",
22
+ "require": "./dist/livekit-client.fm.worker.js"
23
+ },
24
+ "./frame-metadata-worker": {
25
+ "types": "./dist/src/frameMetadata/worker/frameMetadata.worker.d.ts",
26
+ "import": "./dist/livekit-client.fm.worker.mjs",
27
+ "require": "./dist/livekit-client.fm.worker.js"
23
28
  }
24
29
  },
25
30
  "files": [
@@ -35,8 +40,8 @@
35
40
  "./dist/src/e2ee/worker/e2ee.worker.d.ts": [
36
41
  "./dist/ts4.2/e2ee/worker/e2ee.worker.d.ts"
37
42
  ],
38
- "./dist/src/packetTrailer/worker/packetTrailer.worker.d.ts": [
39
- "./dist/ts4.2/packetTrailer/worker/packetTrailer.worker.d.ts"
43
+ "./dist/src/frameMetadata/worker/frameMetadata.worker.d.ts": [
44
+ "./dist/ts4.2/frameMetadata/worker/frameMetadata.worker.d.ts"
40
45
  ]
41
46
  }
42
47
  },
@@ -45,7 +50,7 @@
45
50
  "license": "Apache-2.0",
46
51
  "dependencies": {
47
52
  "@livekit/mutex": "1.1.1",
48
- "@livekit/protocol": "1.45.8",
53
+ "@livekit/protocol": "1.46.6",
49
54
  "events": "^3.3.0",
50
55
  "jose": "^6.1.0",
51
56
  "loglevel": "^1.9.2",
@@ -58,8 +63,8 @@
58
63
  "@types/dom-mediacapture-record": "^1"
59
64
  },
60
65
  "devDependencies": {
61
- "@babel/core": "7.29.0",
62
- "@babel/preset-env": "7.29.2",
66
+ "@babel/core": "7.29.7",
67
+ "@babel/preset-env": "7.29.7",
63
68
  "@bufbuild/protoc-gen-es": "^1.10.0",
64
69
  "@changesets/cli": "2.31.0",
65
70
  "@eslint/js": "10.0.1",
@@ -69,18 +74,18 @@
69
74
  "@rollup/plugin-commonjs": "29.0.2",
70
75
  "@rollup/plugin-json": "6.1.0",
71
76
  "@rollup/plugin-node-resolve": "16.0.3",
72
- "@rollup/plugin-terser": "^0.4.4",
73
- "@size-limit/file": "^11.2.0",
74
- "@size-limit/webpack": "^11.2.0",
77
+ "@rollup/plugin-terser": "^1.0.0",
78
+ "@size-limit/file": "^12.1.0",
79
+ "@size-limit/webpack": "^12.1.0",
75
80
  "@stylistic/eslint-plugin": "^5.10.0",
76
- "@trivago/prettier-plugin-sort-imports": "^5.0.0",
81
+ "@trivago/prettier-plugin-sort-imports": "^6.0.2",
77
82
  "@types/events": "^3.0.3",
78
83
  "@types/sdp-transform": "2.15.0",
79
84
  "@types/ua-parser-js": "0.7.39",
80
- "@typescript-eslint/eslint-plugin": "8.59.2",
81
- "@typescript-eslint/parser": "8.59.2",
85
+ "@typescript-eslint/eslint-plugin": "8.59.4",
86
+ "@typescript-eslint/parser": "8.59.4",
82
87
  "downlevel-dts": "^0.11.0",
83
- "eslint": "10.2.1",
88
+ "eslint": "10.4.0",
84
89
  "eslint-config-airbnb-extended": "^2.3.2",
85
90
  "eslint-config-prettier": "10.1.8",
86
91
  "eslint-plugin-compat": "^6.0.2",
@@ -92,7 +97,7 @@
92
97
  "jsdom": "^26.1.0",
93
98
  "prettier": "^3.4.2",
94
99
  "publint": "^0.3.21",
95
- "rollup": "4.60.2",
100
+ "rollup": "4.60.4",
96
101
  "rollup-plugin-delete": "^2.1.0",
97
102
  "rollup-plugin-typescript2": "0.37.0",
98
103
  "size-limit": "^11.2.0",
@@ -101,11 +106,11 @@
101
106
  "typedoc-plugin-no-inherit": "1.6.1",
102
107
  "typescript": "5.9.3",
103
108
  "typescript-eslint": "^8.47.0",
104
- "vite": "7.3.2",
105
- "vitest": "^3.0.0"
109
+ "vite": "7.3.5",
110
+ "vitest": "^4.0.0"
106
111
  },
107
112
  "scripts": {
108
- "build": "rollup --config --bundleConfigAsCjs && rollup --config rollup.config.worker.js --bundleConfigAsCjs && rollup --config rollup.config.pt-worker.js --bundleConfigAsCjs && pnpm downlevel-dts",
113
+ "build": "rollup --config --bundleConfigAsCjs && rollup --config rollup.config.worker.js --bundleConfigAsCjs && rollup --config rollup.config.fm-worker.js --bundleConfigAsCjs && pnpm downlevel-dts",
109
114
  "build:clean": "rm -rf ./dist && pnpm build",
110
115
  "build:watch": "rollup --watch --config --bundleConfigAsCjs",
111
116
  "build:worker:watch": "rollup --watch --config rollup.config.worker.js --bundleConfigAsCjs",
@@ -77,7 +77,7 @@ function mockWebSocketStream(options: MockWebSocketStreamOptions = {}) {
77
77
  onUrl,
78
78
  } = options;
79
79
 
80
- return vi.mocked(WebSocketStream).mockImplementationOnce((url) => {
80
+ return vi.mocked(WebSocketStream).mockImplementationOnce(function (url) {
81
81
  onUrl?.(url);
82
82
  return {
83
83
  url: 'wss://test.livekit.io',
@@ -283,7 +283,7 @@ describe('SignalClient.connect', () => {
283
283
  it('should reject when AbortSignal is triggered', async () => {
284
284
  const abortController = new AbortController();
285
285
 
286
- vi.mocked(WebSocketStream).mockImplementation(() => {
286
+ vi.mocked(WebSocketStream).mockImplementation(function () {
287
287
  // Simulate abort
288
288
  setTimeout(() => abortController.abort(new Error('User aborted connection')), 50);
289
289
 
@@ -344,7 +344,7 @@ describe('SignalClient.connect', () => {
344
344
  extensions: '',
345
345
  };
346
346
 
347
- vi.mocked(WebSocketStream).mockImplementation(() => {
347
+ vi.mocked(WebSocketStream).mockImplementation(function () {
348
348
  return {
349
349
  url: 'wss://test.livekit.io',
350
350
  opened: Promise.resolve(mockConnection),
@@ -526,7 +526,7 @@ describe('SignalClient.connect', () => {
526
526
  closedResolve = resolve;
527
527
  });
528
528
 
529
- vi.mocked(WebSocketStream).mockImplementation(() => {
529
+ vi.mocked(WebSocketStream).mockImplementation(function () {
530
530
  // Simulate close during connection
531
531
  queueMicrotask(() => {
532
532
  closedResolve({ closeCode: 1006, reason: 'Connection lost' });
@@ -376,13 +376,17 @@ export class SignalClient {
376
376
  if (redactedUrl.searchParams.has('access_token')) {
377
377
  redactedUrl.searchParams.set('access_token', '<redacted>');
378
378
  }
379
+
380
+ if (this.ws) {
381
+ const startClose = performance.now();
382
+ await this.close(false);
383
+ this.log.debug(`closed previous ws connection in ${performance.now() - startClose}ms`);
384
+ }
385
+
379
386
  this.log.info(`signal connecting to ${redactedUrl}`, {
380
387
  reconnect: opts.reconnect,
381
388
  reconnectReason: opts.reconnectReason,
382
389
  });
383
- if (this.ws) {
384
- await this.close(false);
385
- }
386
390
  this.ws = new WebSocketStream<ArrayBuffer>(rtcUrl);
387
391
 
388
392
  try {
@@ -129,24 +129,24 @@ describe('WebSocketStream', () => {
129
129
  vi.clearAllMocks();
130
130
 
131
131
  // Store original WebSocket
132
- originalWebSocket = global.WebSocket;
132
+ originalWebSocket = globalThis.WebSocket;
133
133
 
134
134
  // Mock WebSocket globally
135
- global.WebSocket = vi.fn((url: string, protocols?: string | string[]) => {
135
+ globalThis.WebSocket = vi.fn(function (url: string, protocols?: string | string[]) {
136
136
  mockWebSocket = new MockWebSocket(url, protocols);
137
137
  return mockWebSocket as any;
138
138
  }) as any;
139
139
 
140
140
  // Add constants to the mocked WebSocket
141
- (global.WebSocket as any).CONNECTING = MockWebSocket.CONNECTING;
142
- (global.WebSocket as any).OPEN = MockWebSocket.OPEN;
143
- (global.WebSocket as any).CLOSING = MockWebSocket.CLOSING;
144
- (global.WebSocket as any).CLOSED = MockWebSocket.CLOSED;
141
+ (globalThis.WebSocket as any).CONNECTING = MockWebSocket.CONNECTING;
142
+ (globalThis.WebSocket as any).OPEN = MockWebSocket.OPEN;
143
+ (globalThis.WebSocket as any).CLOSING = MockWebSocket.CLOSING;
144
+ (globalThis.WebSocket as any).CLOSED = MockWebSocket.CLOSED;
145
145
  });
146
146
 
147
147
  afterEach(() => {
148
148
  // Restore original WebSocket
149
- global.WebSocket = originalWebSocket;
149
+ globalThis.WebSocket = originalWebSocket;
150
150
  });
151
151
 
152
152
  describe('Constructor and Initialization', () => {
@@ -1,8 +1,8 @@
1
1
  import { Encryption_Type, TrackInfo } from '@livekit/protocol';
2
2
  import { EventEmitter } from 'events';
3
3
  import type TypedEventEmitter from 'typed-emitter';
4
+ import { hasFrameMetadataPublishOptions } from '../frameMetadata/utils';
4
5
  import log, { LogLevel, workerLogger } from '../logger';
5
- import { hasPacketTrailerPublishOptions } from '../packetTrailer/utils';
6
6
  import type RTCEngine from '../room/RTCEngine';
7
7
  import type Room from '../room/Room';
8
8
  import { ConnectionState } from '../room/Room';
@@ -230,7 +230,7 @@ export class E2EEManager
230
230
  }
231
231
  break;
232
232
  case 'packetTrailerMetadata':
233
- this.handlePacketTrailerMetadata(data.trackId, data.rtpTimestamp, data.ssrc, data.metadata);
233
+ this.handleFrameMetadata(data.trackId, data.rtpTimestamp, data.ssrc, data.metadata);
234
234
  break;
235
235
  default:
236
236
  break;
@@ -242,7 +242,7 @@ export class E2EEManager
242
242
  this.emit(EncryptionEvent.EncryptionError, ev.error, undefined);
243
243
  };
244
244
 
245
- private handlePacketTrailerMetadata(
245
+ private handleFrameMetadata(
246
246
  trackId: string,
247
247
  rtpTimestamp: number,
248
248
  ssrc: number,
@@ -260,9 +260,9 @@ export class E2EEManager
260
260
  pub.track &&
261
261
  pub.track.mediaStreamID === trackId &&
262
262
  pub.track instanceof RemoteVideoTrack &&
263
- pub.track.packetTrailerExtractor
263
+ pub.track.frameMetadataExtractor
264
264
  ) {
265
- pub.track.packetTrailerExtractor.storeMetadata(rtpTimestamp, ssrc, metadata);
265
+ pub.track.frameMetadataExtractor.storeMetadata(rtpTimestamp, ssrc, metadata);
266
266
  return;
267
267
  }
268
268
  }
@@ -509,7 +509,9 @@ export class E2EEManager
509
509
  sender,
510
510
  track.mediaStreamID,
511
511
  undefined,
512
- isVideoTrack(track) ? track.publishOptions?.packetTrailer : undefined,
512
+ isVideoTrack(track)
513
+ ? (track.publishOptions?.frameMetadata ?? track.publishOptions?.packetTrailer)
514
+ : undefined,
513
515
  );
514
516
  }
515
517
 
@@ -598,7 +600,7 @@ export class E2EEManager
598
600
  sender: RTCRtpSender,
599
601
  trackId: string,
600
602
  codec?: VideoCodec,
601
- packetTrailer?: TrackPublishOptions['packetTrailer'],
603
+ frameMetadata?: TrackPublishOptions['frameMetadata'],
602
604
  ) {
603
605
  if (E2EE_FLAG in sender || !this.worker) {
604
606
  return;
@@ -615,8 +617,8 @@ export class E2EEManager
615
617
  participantIdentity: this.room.localParticipant.identity,
616
618
  trackId,
617
619
  codec,
618
- hasPacketTrailer: hasPacketTrailerPublishOptions(packetTrailer),
619
- packetTrailer,
620
+ hasPacketTrailer: hasFrameMetadataPublishOptions(frameMetadata),
621
+ packetTrailer: frameMetadata,
620
622
  };
621
623
  // @ts-ignore
622
624
  sender.transform = new RTCRtpScriptTransform(this.worker, options);
@@ -633,8 +635,8 @@ export class E2EEManager
633
635
  trackId,
634
636
  participantIdentity: this.room.localParticipant.identity,
635
637
  isReuse: false,
636
- hasPacketTrailer: hasPacketTrailerPublishOptions(packetTrailer),
637
- packetTrailer,
638
+ hasPacketTrailer: hasFrameMetadataPublishOptions(frameMetadata),
639
+ packetTrailer: frameMetadata,
638
640
  },
639
641
  };
640
642
  this.worker.postMessage(msg, [senderStreams.readable, senderStreams.writable]);
package/src/e2ee/types.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import type { FrameMetadataPayload } from '../frameMetadata/frameMetadata';
2
+ import type { FrameMetadataPublishOptions } from '../frameMetadata/types';
1
3
  import type { LogLevel } from '../logger';
2
- import type { PacketTrailerFramePayload } from '../packetTrailer/packetTrailer';
3
- import type { PacketTrailerPublishOptions } from '../packetTrailer/types';
4
4
  import type { VideoCodec } from '../room/track/options';
5
5
  import type { BaseE2EEManager } from './E2eeManager';
6
6
  import type { BaseKeyProvider } from './KeyProvider';
@@ -62,7 +62,7 @@ export interface EncodeMessage extends BaseMessage {
62
62
  /**
63
63
  * Packet trailer metadata to append on published video frames.
64
64
  */
65
- packetTrailer?: PacketTrailerPublishOptions;
65
+ packetTrailer?: FrameMetadataPublishOptions;
66
66
  };
67
67
  }
68
68
 
@@ -165,7 +165,7 @@ export interface EncryptDataResponseMessage extends BaseMessage {
165
165
 
166
166
  export interface PTMetadataFromE2EEMessage extends BaseMessage {
167
167
  kind: 'packetTrailerMetadata';
168
- data: PacketTrailerFramePayload;
168
+ data: FrameMetadataPayload;
169
169
  }
170
170
 
171
171
  export type E2EEWorkerMessage =
@@ -249,5 +249,5 @@ export type ScriptTransformOptions = {
249
249
  /**
250
250
  * Packet trailer metadata to append on published video frames.
251
251
  */
252
- packetTrailer?: PacketTrailerPublishOptions;
252
+ packetTrailer?: FrameMetadataPublishOptions;
253
253
  };
@@ -1,6 +1,6 @@
1
1
  import { afterEach, describe, expect, it, vitest } from 'vitest';
2
- import { appendPacketTrailer, extractPacketTrailer } from '../../packetTrailer/packetTrailer';
3
- import type { PacketTrailerPublishOptions } from '../../packetTrailer/types';
2
+ import { appendPacketTrailer, extractPacketTrailer } from '../../frameMetadata/frameMetadata';
3
+ import type { FrameMetadataPublishOptions } from '../../frameMetadata/types';
4
4
  import { IV_LENGTH, KEY_PROVIDER_DEFAULTS } from '../constants';
5
5
  import { CryptorEvent } from '../events';
6
6
  import type { KeyProviderOptions } from '../types';
@@ -69,7 +69,7 @@ function prepareParticipantTestDecoder(
69
69
  function prepareParticipantTestEncoder(
70
70
  participantIdentity: string,
71
71
  partialKeyProviderOptions: Partial<KeyProviderOptions>,
72
- packetTrailer?: PacketTrailerPublishOptions,
72
+ packetTrailer?: FrameMetadataPublishOptions,
73
73
  ) {
74
74
  return prepareParticipantTest(
75
75
  'encode',
@@ -83,7 +83,7 @@ function prepareParticipantTest(
83
83
  mode: 'encode' | 'decode',
84
84
  participantIdentity: string,
85
85
  partialKeyProviderOptions: Partial<KeyProviderOptions>,
86
- packetTrailer?: PacketTrailerPublishOptions,
86
+ packetTrailer?: FrameMetadataPublishOptions,
87
87
  ): {
88
88
  keys: ParticipantKeyHandler;
89
89
  cryptor: FrameCryptor;
@@ -536,7 +536,7 @@ describe('FrameCryptor', () => {
536
536
  const postMessage = vitest.fn();
537
537
  vitest.stubGlobal('postMessage', postMessage);
538
538
  encryptionEnabledMap.set(participantIdentity, false);
539
- cryptor.setHasPacketTrailer(true);
539
+ cryptor.setHasFrameMetadata(true);
540
540
 
541
541
  const payload = Uint8Array.from([1, 2, 3, 4]);
542
542
  const trailer = appendPacketTrailer(payload, 1_744_249_600_123_456n, 0);