livekit-client 2.19.2 → 2.20.1
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.
- package/dist/livekit-client.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +31 -27
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +334 -126
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.fm.worker.js +2 -0
- package/dist/{livekit-client.pt.worker.js.map → livekit-client.fm.worker.js.map} +1 -1
- package/dist/{livekit-client.pt.worker.mjs → livekit-client.fm.worker.mjs} +12 -4
- package/dist/livekit-client.fm.worker.mjs.map +1 -0
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/e2ee/E2eeManager.d.ts +2 -1
- package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
- package/dist/src/e2ee/types.d.ts +6 -5
- package/dist/src/e2ee/types.d.ts.map +1 -1
- package/dist/src/e2ee/utils.d.ts +1 -0
- package/dist/src/e2ee/utils.d.ts.map +1 -1
- package/dist/src/e2ee/worker/DataCryptor.d.ts +1 -0
- package/dist/src/e2ee/worker/DataCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts +9 -8
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/naluUtils.d.ts +1 -0
- package/dist/src/e2ee/worker/naluUtils.d.ts.map +1 -1
- package/dist/src/e2ee/worker/sifPayload.d.ts +1 -0
- package/dist/src/e2ee/worker/sifPayload.d.ts.map +1 -1
- package/dist/src/{packetTrailer/PacketTrailerManager.d.ts → frameMetadata/FrameMetadataManager.d.ts} +8 -4
- package/dist/src/{packetTrailer/PacketTrailerManager.d.ts.map → frameMetadata/FrameMetadataManager.d.ts.map} +1 -1
- package/dist/src/{packetTrailer/packetTrailer.d.ts → frameMetadata/frameMetadata.d.ts} +8 -7
- package/dist/src/frameMetadata/frameMetadata.d.ts.map +1 -0
- package/dist/src/{packetTrailer → frameMetadata}/types.d.ts +11 -6
- package/dist/src/frameMetadata/types.d.ts.map +1 -0
- package/dist/src/frameMetadata/utils.d.ts +9 -0
- package/dist/src/{packetTrailer → frameMetadata}/utils.d.ts.map +1 -1
- package/dist/src/frameMetadata/worker/frameMetadata.worker.d.ts +2 -0
- package/dist/src/frameMetadata/worker/frameMetadata.worker.d.ts.map +1 -0
- package/dist/src/index.d.ts +10 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/options.d.ts +8 -4
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +41 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts +1 -0
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +4 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +3 -2
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/data-track/depacketizer.d.ts.map +1 -1
- package/dist/src/room/data-track/frame.d.ts +1 -0
- package/dist/src/room/data-track/frame.d.ts.map +1 -1
- package/dist/src/room/data-track/outgoing/types.d.ts +1 -0
- package/dist/src/room/data-track/outgoing/types.d.ts.map +1 -1
- package/dist/src/room/data-track/packet/extensions.d.ts +1 -0
- package/dist/src/room/data-track/packet/extensions.d.ts.map +1 -1
- package/dist/src/room/data-track/packet/index.d.ts +1 -0
- package/dist/src/room/data-track/packet/index.d.ts.map +1 -1
- package/dist/src/room/data-track/packet/serializable.d.ts +1 -0
- package/dist/src/room/data-track/packet/serializable.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +3 -2
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +1 -0
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
- package/dist/src/room/token-source/TokenSource.d.ts.map +1 -1
- package/dist/src/room/token-source/types.d.ts +1 -0
- package/dist/src/room/token-source/types.d.ts.map +1 -1
- package/dist/src/room/token-source/utils.d.ts.map +1 -1
- package/dist/src/room/track/FrameMetadataExtractor.d.ts +19 -0
- package/dist/src/room/track/FrameMetadataExtractor.d.ts.map +1 -0
- package/dist/src/room/track/RemoteVideoTrack.d.ts +7 -7
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +1 -0
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +17 -5
- package/dist/src/room/track/options.d.ts.map +1 -1
- package/dist/src/room/track/record.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +1 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/type-polyfills/non-shared-typed-arrays.d.ts +2 -0
- package/dist/src/type-polyfills/non-shared-typed-arrays.d.ts.map +1 -0
- package/dist/src/utils/dataPacketBuffer.d.ts +1 -0
- package/dist/src/utils/dataPacketBuffer.d.ts.map +1 -1
- package/dist/ts4.2/e2ee/E2eeManager.d.ts +2 -1
- package/dist/ts4.2/e2ee/types.d.ts +6 -5
- package/dist/ts4.2/e2ee/utils.d.ts +1 -0
- package/dist/ts4.2/e2ee/worker/DataCryptor.d.ts +1 -0
- package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +9 -8
- package/dist/ts4.2/e2ee/worker/naluUtils.d.ts +1 -0
- package/dist/ts4.2/e2ee/worker/sifPayload.d.ts +1 -0
- package/dist/ts4.2/{packetTrailer/PacketTrailerManager.d.ts → frameMetadata/FrameMetadataManager.d.ts} +8 -4
- package/dist/ts4.2/{packetTrailer/packetTrailer.d.ts → frameMetadata/frameMetadata.d.ts} +8 -7
- package/dist/ts4.2/{packetTrailer → frameMetadata}/types.d.ts +11 -6
- package/dist/ts4.2/frameMetadata/utils.d.ts +9 -0
- package/dist/ts4.2/frameMetadata/worker/frameMetadata.worker.d.ts +2 -0
- package/dist/ts4.2/index.d.ts +9 -3
- package/dist/ts4.2/options.d.ts +8 -4
- package/dist/ts4.2/room/PCTransport.d.ts +41 -1
- package/dist/ts4.2/room/PCTransportManager.d.ts +1 -0
- package/dist/ts4.2/room/RTCEngine.d.ts +4 -1
- package/dist/ts4.2/room/Room.d.ts +3 -2
- package/dist/ts4.2/room/data-track/frame.d.ts +1 -0
- package/dist/ts4.2/room/data-track/outgoing/types.d.ts +1 -0
- package/dist/ts4.2/room/data-track/packet/extensions.d.ts +1 -0
- package/dist/ts4.2/room/data-track/packet/index.d.ts +1 -0
- package/dist/ts4.2/room/data-track/packet/serializable.d.ts +1 -0
- package/dist/ts4.2/room/participant/LocalParticipant.d.ts +3 -2
- package/dist/ts4.2/room/participant/Participant.d.ts +1 -0
- package/dist/ts4.2/room/token-source/types.d.ts +1 -0
- package/dist/ts4.2/room/track/FrameMetadataExtractor.d.ts +19 -0
- package/dist/ts4.2/room/track/RemoteVideoTrack.d.ts +7 -7
- package/dist/ts4.2/room/track/Track.d.ts +1 -0
- package/dist/ts4.2/room/track/options.d.ts +17 -5
- package/dist/ts4.2/room/utils.d.ts +1 -0
- package/dist/ts4.2/type-polyfills/non-shared-typed-arrays.d.ts +2 -0
- package/dist/ts4.2/utils/dataPacketBuffer.d.ts +1 -0
- package/package.json +24 -19
- package/src/api/SignalClient.test.ts +4 -4
- package/src/api/SignalClient.ts +8 -3
- package/src/api/WebSocketStream.test.ts +7 -7
- package/src/e2ee/E2eeManager.ts +16 -12
- package/src/e2ee/types.ts +6 -5
- package/src/e2ee/utils.ts +1 -0
- package/src/e2ee/worker/DataCryptor.ts +1 -0
- package/src/e2ee/worker/FrameCryptor.test.ts +6 -5
- package/src/e2ee/worker/FrameCryptor.ts +28 -23
- package/src/e2ee/worker/ParticipantKeyHandler.test.ts +1 -0
- package/src/e2ee/worker/e2ee.worker.ts +6 -5
- package/src/e2ee/worker/naluUtils.ts +1 -0
- package/src/e2ee/worker/sifPayload.ts +1 -0
- package/src/e2ee/worker/tsconfig.json +4 -1
- package/src/{packetTrailer/PacketTrailerManager.test.ts → frameMetadata/FrameMetadataManager.test.ts} +10 -8
- package/src/{packetTrailer/PacketTrailerManager.ts → frameMetadata/FrameMetadataManager.ts} +21 -15
- package/src/{packetTrailer/packetTrailer.test.ts → frameMetadata/frameMetadata.test.ts} +84 -1
- package/src/{packetTrailer/packetTrailer.ts → frameMetadata/frameMetadata.ts} +17 -9
- package/src/{packetTrailer → frameMetadata}/types.ts +13 -6
- package/src/{packetTrailer → frameMetadata}/utils.test.ts +19 -19
- package/src/{packetTrailer → frameMetadata}/utils.ts +11 -11
- package/src/{packetTrailer/worker/packetTrailer.worker.ts → frameMetadata/worker/frameMetadata.worker.ts} +5 -5
- package/src/{packetTrailer → frameMetadata}/worker/tsconfig.json +4 -1
- package/src/index.ts +13 -2
- package/src/options.ts +9 -4
- package/src/room/PCTransport.test.ts +150 -0
- package/src/room/PCTransport.ts +117 -0
- package/src/room/PCTransportManager.ts +4 -0
- package/src/room/RTCEngine.test.ts +143 -9
- package/src/room/RTCEngine.ts +112 -31
- package/src/room/Room.ts +11 -10
- package/src/room/data-track/depacketizer.ts +1 -0
- package/src/room/data-track/frame.ts +1 -0
- package/src/room/data-track/outgoing/types.ts +1 -0
- package/src/room/data-track/packet/extensions.ts +1 -0
- package/src/room/data-track/packet/index.ts +1 -0
- package/src/room/data-track/packet/serializable.ts +1 -0
- package/src/room/participant/LocalParticipant.test.ts +19 -19
- package/src/room/participant/LocalParticipant.ts +22 -16
- package/src/room/participant/Participant.ts +1 -0
- package/src/room/participant/publishUtils.test.ts +6 -0
- package/src/room/participant/publishUtils.ts +4 -1
- package/src/room/rpc/client/RpcClientManager.ts +1 -1
- package/src/room/rpc/server/RpcServerManager.ts +1 -1
- package/src/room/token-source/TokenSource.ts +9 -23
- package/src/room/token-source/types.ts +1 -0
- package/src/room/token-source/utils.ts +1 -0
- package/src/room/track/{PacketTrailerExtractor.ts → FrameMetadataExtractor.ts} +8 -8
- package/src/room/track/RemoteVideoTrack.ts +7 -11
- package/src/room/track/Track.ts +1 -0
- package/src/room/track/options.ts +19 -5
- package/src/room/track/record.ts +1 -0
- package/src/room/utils.ts +1 -0
- package/src/type-polyfills/{non-shared-typed-arrays.d.ts → non-shared-typed-arrays.ts} +6 -1
- package/src/utils/dataPacketBuffer.ts +2 -0
- package/dist/livekit-client.pt.worker.js +0 -2
- package/dist/livekit-client.pt.worker.mjs.map +0 -1
- package/dist/src/packetTrailer/packetTrailer.d.ts.map +0 -1
- package/dist/src/packetTrailer/types.d.ts.map +0 -1
- package/dist/src/packetTrailer/utils.d.ts +0 -9
- package/dist/src/packetTrailer/worker/packetTrailer.worker.d.ts +0 -2
- package/dist/src/packetTrailer/worker/packetTrailer.worker.d.ts.map +0 -1
- package/dist/src/room/track/PacketTrailerExtractor.d.ts +0 -19
- package/dist/src/room/track/PacketTrailerExtractor.d.ts.map +0 -1
- package/dist/ts4.2/packetTrailer/utils.d.ts +0 -9
- package/dist/ts4.2/packetTrailer/worker/packetTrailer.worker.d.ts +0 -2
- package/dist/ts4.2/room/track/PacketTrailerExtractor.d.ts +0 -19
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import type { TrackInfo } from '@livekit/protocol';
|
|
3
|
-
import {
|
|
3
|
+
import { FrameMetadataManager } from './FrameMetadataManager';
|
|
4
4
|
|
|
5
|
-
describe('
|
|
5
|
+
describe('FrameMetadataManager', () => {
|
|
6
6
|
const originalRTCRtpSender = window.RTCRtpSender;
|
|
7
7
|
const originalUserAgent = navigator.userAgent;
|
|
8
8
|
const originalRTCRtpScriptTransform = (window as unknown as { RTCRtpScriptTransform?: unknown })
|
|
@@ -63,7 +63,7 @@ describe('PacketTrailerManager', () => {
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
function setupWorkerReceiver(manager:
|
|
66
|
+
function setupWorkerReceiver(manager: FrameMetadataManager, receiver: RTCRtpReceiver) {
|
|
67
67
|
(
|
|
68
68
|
manager as unknown as {
|
|
69
69
|
setupWorkerReceiver: (receiver: RTCRtpReceiver, newTrackId: string) => void;
|
|
@@ -72,7 +72,7 @@ describe('PacketTrailerManager', () => {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
function setupReceiver(
|
|
75
|
-
manager:
|
|
75
|
+
manager: FrameMetadataManager,
|
|
76
76
|
receiver: RTCRtpReceiver,
|
|
77
77
|
trackId: string,
|
|
78
78
|
trackInfo?: TrackInfo,
|
|
@@ -103,11 +103,13 @@ describe('PacketTrailerManager', () => {
|
|
|
103
103
|
it('uses RTCRtpScriptTransform for packet trailer extraction when supported', () => {
|
|
104
104
|
useSafariUserAgent();
|
|
105
105
|
const transform = {};
|
|
106
|
-
const RTCRtpScriptTransform = vi.fn(()
|
|
106
|
+
const RTCRtpScriptTransform = vi.fn(function () {
|
|
107
|
+
return transform;
|
|
108
|
+
});
|
|
107
109
|
setScriptTransform(RTCRtpScriptTransform);
|
|
108
110
|
|
|
109
111
|
const worker = {} as Worker;
|
|
110
|
-
const manager = new
|
|
112
|
+
const manager = new FrameMetadataManager({ worker });
|
|
111
113
|
const receiver = {
|
|
112
114
|
createEncodedStreams: vi.fn(),
|
|
113
115
|
} as unknown as RTCRtpReceiver;
|
|
@@ -129,7 +131,7 @@ describe('PacketTrailerManager', () => {
|
|
|
129
131
|
stubInsertableStreamsSupport();
|
|
130
132
|
|
|
131
133
|
const worker = { postMessage: vi.fn() } as unknown as Worker;
|
|
132
|
-
const manager = new
|
|
134
|
+
const manager = new FrameMetadataManager({ worker });
|
|
133
135
|
const { receiver, readable, writable, createEncodedStreams } = makeReceiver();
|
|
134
136
|
|
|
135
137
|
setupReceiver(manager, receiver, 'track-without-trailer');
|
|
@@ -153,7 +155,7 @@ describe('PacketTrailerManager', () => {
|
|
|
153
155
|
stubInsertableStreamsSupport();
|
|
154
156
|
|
|
155
157
|
const worker = { postMessage: vi.fn() } as unknown as Worker;
|
|
156
|
-
const manager = new
|
|
158
|
+
const manager = new FrameMetadataManager({ worker });
|
|
157
159
|
const { receiver } = makeReceiver();
|
|
158
160
|
const trackInfo = { packetTrailerFeatures: [1] } as unknown as TrackInfo;
|
|
159
161
|
|
|
@@ -2,13 +2,13 @@ import type { TrackInfo } from '@livekit/protocol';
|
|
|
2
2
|
import log from '../logger';
|
|
3
3
|
import type Room from '../room/Room';
|
|
4
4
|
import { RoomEvent } from '../room/events';
|
|
5
|
-
import {
|
|
5
|
+
import { FrameMetadataExtractor } from '../room/track/FrameMetadataExtractor';
|
|
6
6
|
import type RemoteTrack from '../room/track/RemoteTrack';
|
|
7
7
|
import RemoteVideoTrack from '../room/track/RemoteVideoTrack';
|
|
8
8
|
import type { PTDecodeMessage, PTUpdateTrackIdMessage, PTWorkerMessage } from './types';
|
|
9
|
-
import {
|
|
9
|
+
import { isFrameMetadataSupported, shouldUseFrameMetadataScriptTransform } from './utils';
|
|
10
10
|
|
|
11
|
-
export interface
|
|
11
|
+
export interface FrameMetadataOptions {
|
|
12
12
|
/**
|
|
13
13
|
* Dedicated worker for extracting packet trailers off the main thread.
|
|
14
14
|
*
|
|
@@ -34,12 +34,12 @@ export interface PacketTrailerOptions {
|
|
|
34
34
|
*
|
|
35
35
|
* @experimental
|
|
36
36
|
*/
|
|
37
|
-
export class
|
|
37
|
+
export class FrameMetadataManager {
|
|
38
38
|
private worker?: Worker;
|
|
39
39
|
|
|
40
40
|
private room?: Room;
|
|
41
41
|
|
|
42
|
-
private extractors = new Map<string,
|
|
42
|
+
private extractors = new Map<string, FrameMetadataExtractor>();
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Tracks the trackId associated with each receiver that has had its
|
|
@@ -49,7 +49,7 @@ export class PacketTrailerManager {
|
|
|
49
49
|
*/
|
|
50
50
|
private workerPipelines = new Map<RTCRtpReceiver, string>();
|
|
51
51
|
|
|
52
|
-
constructor(options?:
|
|
52
|
+
constructor(options?: FrameMetadataOptions) {
|
|
53
53
|
this.worker = options?.worker;
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -100,18 +100,18 @@ export class PacketTrailerManager {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
if (
|
|
103
|
-
!
|
|
103
|
+
!isFrameMetadataSupported(this.worker ? { worker: this.worker } : undefined) &&
|
|
104
104
|
!this.room?.hasE2EESetup
|
|
105
105
|
) {
|
|
106
|
-
log.warn('
|
|
106
|
+
log.warn('frame metadata transform not supported; skipping extraction');
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
const extractor = new
|
|
110
|
+
const extractor = new FrameMetadataExtractor();
|
|
111
111
|
const trackId = track.mediaStreamID;
|
|
112
112
|
|
|
113
113
|
this.extractors.set(trackId, extractor);
|
|
114
|
-
track.
|
|
114
|
+
track.frameMetadataExtractor = extractor;
|
|
115
115
|
|
|
116
116
|
if (this.room?.hasE2EESetup) {
|
|
117
117
|
// E2EE worker strips the trailer and injects metadata directly into
|
|
@@ -123,7 +123,7 @@ export class PacketTrailerManager {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
private setupPassthroughReceiver(receiver: RTCRtpReceiver, trackId: string) {
|
|
126
|
-
if (
|
|
126
|
+
if (shouldUseFrameMetadataScriptTransform()) {
|
|
127
127
|
if ('transform' in receiver) {
|
|
128
128
|
// @ts-ignore
|
|
129
129
|
receiver.transform = null;
|
|
@@ -133,7 +133,7 @@ export class PacketTrailerManager {
|
|
|
133
133
|
|
|
134
134
|
if (
|
|
135
135
|
this.worker &&
|
|
136
|
-
|
|
136
|
+
isFrameMetadataSupported({ worker: this.worker }) &&
|
|
137
137
|
!this.workerPipelines.has(receiver)
|
|
138
138
|
) {
|
|
139
139
|
this.setupWorkerReceiver(receiver, trackId, false);
|
|
@@ -155,7 +155,7 @@ export class PacketTrailerManager {
|
|
|
155
155
|
return;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
if (
|
|
158
|
+
if (shouldUseFrameMetadataScriptTransform()) {
|
|
159
159
|
// @ts-ignore
|
|
160
160
|
receiver.transform = new RTCRtpScriptTransform(worker, {
|
|
161
161
|
kind: 'decode',
|
|
@@ -215,7 +215,7 @@ export class PacketTrailerManager {
|
|
|
215
215
|
}
|
|
216
216
|
|
|
217
217
|
if (track instanceof RemoteVideoTrack) {
|
|
218
|
-
track.
|
|
218
|
+
track.frameMetadataExtractor = undefined;
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
// The receiver pipeline is intentionally left running. If the receiver is
|
|
@@ -245,6 +245,12 @@ export class PacketTrailerManager {
|
|
|
245
245
|
};
|
|
246
246
|
|
|
247
247
|
private onWorkerError = (ev: ErrorEvent) => {
|
|
248
|
-
log.error('
|
|
248
|
+
log.error('frame metadata worker encountered an error:', { error: ev.error });
|
|
249
249
|
};
|
|
250
250
|
}
|
|
251
|
+
|
|
252
|
+
/** @deprecated Use {@link FrameMetadataManager} instead. */
|
|
253
|
+
export const PacketTrailerManager = FrameMetadataManager;
|
|
254
|
+
|
|
255
|
+
/** @deprecated Use {@link FrameMetadataOptions} instead. */
|
|
256
|
+
export type PacketTrailerOptions = FrameMetadataOptions;
|
|
@@ -1,10 +1,56 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import {
|
|
3
|
+
PACKET_TRAILER_ENVELOPE_SIZE,
|
|
4
|
+
PACKET_TRAILER_FRAME_ID_TAG,
|
|
5
|
+
PACKET_TRAILER_MAGIC,
|
|
6
|
+
PACKET_TRAILER_TIMESTAMP_TAG,
|
|
7
|
+
PACKET_TRAILER_USER_DATA_TAG,
|
|
3
8
|
appendPacketTrailer,
|
|
4
9
|
appendPacketTrailerToEncodedFrame,
|
|
5
10
|
extractPacketTrailer,
|
|
6
11
|
processPacketTrailer,
|
|
7
|
-
} from './
|
|
12
|
+
} from './frameMetadata';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Builds a packet trailer (XORed TLVs + envelope) for the given fields. The
|
|
16
|
+
* SDK only writes timestamp/frameId, so this mirrors the native sender's TLV
|
|
17
|
+
* encoding to exercise user_data extraction.
|
|
18
|
+
*/
|
|
19
|
+
function buildTrailer(
|
|
20
|
+
payload: Uint8Array,
|
|
21
|
+
fields: { userTimestamp?: bigint; frameId?: number; userData?: Uint8Array },
|
|
22
|
+
): Uint8Array {
|
|
23
|
+
const tlvs: number[] = [];
|
|
24
|
+
|
|
25
|
+
if (fields.userTimestamp !== undefined) {
|
|
26
|
+
tlvs.push(PACKET_TRAILER_TIMESTAMP_TAG ^ 0xff, 8 ^ 0xff);
|
|
27
|
+
for (let i = 7; i >= 0; i -= 1) {
|
|
28
|
+
tlvs.push(Number((fields.userTimestamp >> BigInt(i * 8)) & BigInt(0xff)) ^ 0xff);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (fields.frameId !== undefined) {
|
|
33
|
+
tlvs.push(PACKET_TRAILER_FRAME_ID_TAG ^ 0xff, 4 ^ 0xff);
|
|
34
|
+
for (let i = 3; i >= 0; i -= 1) {
|
|
35
|
+
tlvs.push(((fields.frameId >> (i * 8)) & 0xff) ^ 0xff);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (fields.userData !== undefined) {
|
|
40
|
+
tlvs.push(PACKET_TRAILER_USER_DATA_TAG ^ 0xff, fields.userData.length ^ 0xff);
|
|
41
|
+
for (const byte of fields.userData) {
|
|
42
|
+
tlvs.push(byte ^ 0xff);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const trailerLength = tlvs.length + PACKET_TRAILER_ENVELOPE_SIZE;
|
|
47
|
+
const result = new Uint8Array(payload.length + trailerLength);
|
|
48
|
+
result.set(payload, 0);
|
|
49
|
+
result.set(tlvs, payload.length);
|
|
50
|
+
result[payload.length + tlvs.length] = trailerLength ^ 0xff;
|
|
51
|
+
result.set(PACKET_TRAILER_MAGIC, payload.length + tlvs.length + 1);
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
8
54
|
|
|
9
55
|
describe('packetTrailer', () => {
|
|
10
56
|
afterEach(() => {
|
|
@@ -47,6 +93,43 @@ describe('packetTrailer', () => {
|
|
|
47
93
|
});
|
|
48
94
|
});
|
|
49
95
|
|
|
96
|
+
it('extracts user_data from a trailer carrying only user_data', () => {
|
|
97
|
+
const payload = Uint8Array.from([1, 2, 3, 4]);
|
|
98
|
+
const userData = Uint8Array.from([0x00, 0x01, 0xfe, 0xff, 0x42]);
|
|
99
|
+
const trailer = buildTrailer(payload, { userData });
|
|
100
|
+
const extracted = extractPacketTrailer(trailer);
|
|
101
|
+
|
|
102
|
+
expect(Array.from(extracted.data)).toEqual(Array.from(payload));
|
|
103
|
+
expect(extracted.metadata?.userTimestamp).toBe(0n);
|
|
104
|
+
expect(extracted.metadata?.frameId).toBe(0);
|
|
105
|
+
expect(extracted.metadata?.userData).toBeInstanceOf(Uint8Array);
|
|
106
|
+
expect(Array.from(extracted.metadata!.userData!)).toEqual(Array.from(userData));
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('extracts user_data alongside timestamp and frameId', () => {
|
|
110
|
+
const payload = Uint8Array.from([9, 8, 7, 6, 5]);
|
|
111
|
+
const userData = Uint8Array.from([10, 20, 30, 40]);
|
|
112
|
+
const trailer = buildTrailer(payload, {
|
|
113
|
+
userTimestamp: 1_744_249_600_123_456n,
|
|
114
|
+
frameId: 42,
|
|
115
|
+
userData,
|
|
116
|
+
});
|
|
117
|
+
const extracted = extractPacketTrailer(trailer);
|
|
118
|
+
|
|
119
|
+
expect(Array.from(extracted.data)).toEqual(Array.from(payload));
|
|
120
|
+
expect(extracted.metadata?.userTimestamp).toBe(1_744_249_600_123_456n);
|
|
121
|
+
expect(extracted.metadata?.frameId).toBe(42);
|
|
122
|
+
expect(Array.from(extracted.metadata!.userData!)).toEqual(Array.from(userData));
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('leaves userData undefined when no user_data tag is present', () => {
|
|
126
|
+
const payload = Uint8Array.from([1, 2, 3, 4]);
|
|
127
|
+
const trailer = appendPacketTrailer(payload, 1_744_249_600_123_456n, 42);
|
|
128
|
+
const extracted = extractPacketTrailer(trailer);
|
|
129
|
+
|
|
130
|
+
expect(extracted.metadata?.userData).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
|
|
50
133
|
it('returns data unchanged when both timestamp and frameId are 0', () => {
|
|
51
134
|
const payload = Uint8Array.from([1, 2, 3, 4]);
|
|
52
135
|
const result = appendPacketTrailer(payload, 0n, 0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { FrameMetadata, FrameMetadataPublishOptions } from './types';
|
|
2
|
+
import { hasFrameMetadataPublishOptions } from './utils';
|
|
3
3
|
|
|
4
4
|
export const PACKET_TRAILER_MAGIC = Uint8Array.from([
|
|
5
5
|
'L'.charCodeAt(0),
|
|
@@ -10,6 +10,7 @@ export const PACKET_TRAILER_MAGIC = Uint8Array.from([
|
|
|
10
10
|
|
|
11
11
|
export const PACKET_TRAILER_TIMESTAMP_TAG = 0x01;
|
|
12
12
|
export const PACKET_TRAILER_FRAME_ID_TAG = 0x02;
|
|
13
|
+
export const PACKET_TRAILER_USER_DATA_TAG = 0x03;
|
|
13
14
|
export const PACKET_TRAILER_ENVELOPE_SIZE = 5;
|
|
14
15
|
|
|
15
16
|
const TIMESTAMP_TLV_SIZE = 10;
|
|
@@ -17,7 +18,7 @@ const FRAME_ID_TLV_SIZE = 6;
|
|
|
17
18
|
|
|
18
19
|
export interface ExtractPacketTrailerResult {
|
|
19
20
|
data: Uint8Array;
|
|
20
|
-
metadata?:
|
|
21
|
+
metadata?: FrameMetadata;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export function appendPacketTrailer(
|
|
@@ -64,10 +65,10 @@ export function appendPacketTrailer(
|
|
|
64
65
|
|
|
65
66
|
export function appendPacketTrailerToEncodedFrame(
|
|
66
67
|
frame: RTCEncodedVideoFrame,
|
|
67
|
-
options:
|
|
68
|
+
options: FrameMetadataPublishOptions | undefined,
|
|
68
69
|
frameId: number,
|
|
69
70
|
): boolean {
|
|
70
|
-
if (!
|
|
71
|
+
if (!hasFrameMetadataPublishOptions(options) || frame.data.byteLength === 0) {
|
|
71
72
|
return false;
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -108,7 +109,7 @@ export function extractPacketTrailer(data: ArrayBuffer | Uint8Array): ExtractPac
|
|
|
108
109
|
const strippedData = bytes.subarray(0, trailerStart);
|
|
109
110
|
let offset = trailerStart;
|
|
110
111
|
let foundAny = false;
|
|
111
|
-
const metadata:
|
|
112
|
+
const metadata: FrameMetadata = {
|
|
112
113
|
userTimestamp: BigInt(0),
|
|
113
114
|
frameId: 0,
|
|
114
115
|
};
|
|
@@ -127,6 +128,13 @@ export function extractPacketTrailer(data: ArrayBuffer | Uint8Array): ExtractPac
|
|
|
127
128
|
} else if (tag === PACKET_TRAILER_FRAME_ID_TAG && length === 4) {
|
|
128
129
|
metadata.frameId = readUint32Xor(bytes, offset, length);
|
|
129
130
|
foundAny = true;
|
|
131
|
+
} else if (tag === PACKET_TRAILER_USER_DATA_TAG) {
|
|
132
|
+
const userData = new Uint8Array(length);
|
|
133
|
+
for (let index = 0; index < length; index += 1) {
|
|
134
|
+
userData[index] = bytes[offset + index] ^ 0xff;
|
|
135
|
+
}
|
|
136
|
+
metadata.userData = userData;
|
|
137
|
+
foundAny = true;
|
|
130
138
|
}
|
|
131
139
|
|
|
132
140
|
offset += length;
|
|
@@ -223,16 +231,16 @@ export function getFrameSsrc(frame: RTCEncodedVideoFrame | RTCEncodedAudioFrame)
|
|
|
223
231
|
return 0;
|
|
224
232
|
}
|
|
225
233
|
|
|
226
|
-
export interface
|
|
234
|
+
export interface FrameMetadataPayload {
|
|
227
235
|
trackId: string;
|
|
228
236
|
rtpTimestamp: number;
|
|
229
237
|
ssrc: number;
|
|
230
|
-
metadata:
|
|
238
|
+
metadata: FrameMetadata;
|
|
231
239
|
}
|
|
232
240
|
|
|
233
241
|
export interface ProcessPacketTrailerResult {
|
|
234
242
|
data?: ArrayBuffer;
|
|
235
|
-
payload?:
|
|
243
|
+
payload?: FrameMetadataPayload;
|
|
236
244
|
}
|
|
237
245
|
|
|
238
246
|
/**
|
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FrameMetadataPayload } from './frameMetadata';
|
|
2
2
|
|
|
3
|
-
export interface
|
|
3
|
+
export interface FrameMetadata {
|
|
4
4
|
userTimestamp: bigint;
|
|
5
5
|
frameId: number;
|
|
6
|
+
userData?: Uint8Array;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/** @deprecated Use {@link FrameMetadata} instead. */
|
|
10
|
+
export type PacketTrailerMetadata = FrameMetadata;
|
|
11
|
+
|
|
12
|
+
export interface FrameMetadataPublishOptions {
|
|
9
13
|
timestamp?: boolean;
|
|
10
14
|
frameId?: boolean;
|
|
11
15
|
}
|
|
12
16
|
|
|
17
|
+
/** @deprecated Use {@link FrameMetadataPublishOptions} instead. */
|
|
18
|
+
export type PacketTrailerPublishOptions = FrameMetadataPublishOptions;
|
|
19
|
+
|
|
13
20
|
export interface PTBaseMessage {
|
|
14
21
|
kind: string;
|
|
15
22
|
data?: unknown;
|
|
@@ -38,7 +45,7 @@ export interface PTEncodeMessage extends PTBaseMessage {
|
|
|
38
45
|
data: {
|
|
39
46
|
readableStream: ReadableStream;
|
|
40
47
|
writableStream: WritableStream;
|
|
41
|
-
packetTrailer?:
|
|
48
|
+
packetTrailer?: FrameMetadataPublishOptions;
|
|
42
49
|
};
|
|
43
50
|
}
|
|
44
51
|
|
|
@@ -49,12 +56,12 @@ export type PTScriptTransformOptions =
|
|
|
49
56
|
}
|
|
50
57
|
| {
|
|
51
58
|
kind: 'encode';
|
|
52
|
-
packetTrailer?:
|
|
59
|
+
packetTrailer?: FrameMetadataPublishOptions;
|
|
53
60
|
};
|
|
54
61
|
|
|
55
62
|
export interface PTMetadataMessage extends PTBaseMessage {
|
|
56
63
|
kind: 'metadata';
|
|
57
|
-
data:
|
|
64
|
+
data: FrameMetadataPayload;
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
export interface PTUpdateTrackIdMessage extends PTBaseMessage {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { PacketTrailerFeature } from '@livekit/protocol';
|
|
2
2
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
getFrameMetadataFeatures,
|
|
5
|
+
getFrameMetadataPublishOptions,
|
|
6
|
+
isFrameMetadataSupported,
|
|
7
7
|
} from './utils';
|
|
8
8
|
|
|
9
|
-
describe('
|
|
9
|
+
describe('frame metadata support', () => {
|
|
10
10
|
const originalRTCRtpSender = window.RTCRtpSender;
|
|
11
11
|
const originalRTCRtpScriptTransform = (window as unknown as { RTCRtpScriptTransform?: unknown })
|
|
12
12
|
.RTCRtpScriptTransform;
|
|
@@ -46,20 +46,20 @@ describe('packet trailer support', () => {
|
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
it('supports
|
|
49
|
+
it('supports frame metadata with RTCRtpScriptTransform on Safari', () => {
|
|
50
50
|
stubScriptTransformSupport(
|
|
51
51
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15',
|
|
52
52
|
);
|
|
53
53
|
|
|
54
|
-
expect(
|
|
54
|
+
expect(isFrameMetadataSupported({ worker: {} as Worker })).toBe(true);
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
it('supports
|
|
57
|
+
it('supports frame metadata with RTCRtpScriptTransform on Firefox', () => {
|
|
58
58
|
stubScriptTransformSupport(
|
|
59
59
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.0; rv:144.0) Gecko/20100101 Firefox/144.0',
|
|
60
60
|
);
|
|
61
61
|
|
|
62
|
-
expect(
|
|
62
|
+
expect(isFrameMetadataSupported({ worker: {} as Worker })).toBe(true);
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
it('does not use RTCRtpScriptTransform support on Chromium-based browsers', () => {
|
|
@@ -67,39 +67,39 @@ describe('packet trailer support', () => {
|
|
|
67
67
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36',
|
|
68
68
|
);
|
|
69
69
|
|
|
70
|
-
expect(
|
|
70
|
+
expect(isFrameMetadataSupported({ worker: {} as Worker })).toBe(false);
|
|
71
71
|
});
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
describe('
|
|
74
|
+
describe('frame metadata publish features', () => {
|
|
75
75
|
it('maps publish options to protocol features', () => {
|
|
76
|
-
expect(
|
|
76
|
+
expect(getFrameMetadataFeatures({ timestamp: true, frameId: true })).toEqual([
|
|
77
77
|
PacketTrailerFeature.PTF_USER_TIMESTAMP,
|
|
78
78
|
PacketTrailerFeature.PTF_FRAME_ID,
|
|
79
79
|
]);
|
|
80
|
-
expect(
|
|
80
|
+
expect(getFrameMetadataFeatures({ timestamp: true })).toEqual([
|
|
81
81
|
PacketTrailerFeature.PTF_USER_TIMESTAMP,
|
|
82
82
|
]);
|
|
83
|
-
expect(
|
|
83
|
+
expect(getFrameMetadataFeatures({ frameId: true })).toEqual([
|
|
84
84
|
PacketTrailerFeature.PTF_FRAME_ID,
|
|
85
85
|
]);
|
|
86
|
-
expect(
|
|
86
|
+
expect(getFrameMetadataFeatures()).toEqual([]);
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
it('maps protocol features to publish options', () => {
|
|
90
90
|
expect(
|
|
91
|
-
|
|
91
|
+
getFrameMetadataPublishOptions([
|
|
92
92
|
PacketTrailerFeature.PTF_USER_TIMESTAMP,
|
|
93
93
|
PacketTrailerFeature.PTF_FRAME_ID,
|
|
94
94
|
]),
|
|
95
95
|
).toEqual({ timestamp: true, frameId: true });
|
|
96
|
-
expect(
|
|
96
|
+
expect(getFrameMetadataPublishOptions([PacketTrailerFeature.PTF_USER_TIMESTAMP])).toEqual({
|
|
97
97
|
timestamp: true,
|
|
98
98
|
});
|
|
99
|
-
expect(
|
|
99
|
+
expect(getFrameMetadataPublishOptions([PacketTrailerFeature.PTF_FRAME_ID])).toEqual({
|
|
100
100
|
frameId: true,
|
|
101
101
|
});
|
|
102
|
-
expect(
|
|
103
|
-
expect(
|
|
102
|
+
expect(getFrameMetadataPublishOptions()).toBeUndefined();
|
|
103
|
+
expect(getFrameMetadataPublishOptions([])).toBeUndefined();
|
|
104
104
|
});
|
|
105
105
|
});
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { PacketTrailerFeature } from '@livekit/protocol';
|
|
2
2
|
import { isInsertableStreamSupported } from '../e2ee/utils';
|
|
3
3
|
import { isScriptTransformSupportedForWorker } from '../room/utils';
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
4
|
+
import type { FrameMetadataOptions } from './FrameMetadataManager';
|
|
5
|
+
import type { FrameMetadataPublishOptions } from './types';
|
|
6
6
|
|
|
7
|
-
export function
|
|
7
|
+
export function shouldUseFrameMetadataScriptTransform() {
|
|
8
8
|
return isScriptTransformSupportedForWorker();
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function
|
|
11
|
+
export function isFrameMetadataSupported(options?: FrameMetadataOptions) {
|
|
12
12
|
return (
|
|
13
|
-
!!options?.worker && (isInsertableStreamSupported() ||
|
|
13
|
+
!!options?.worker && (isInsertableStreamSupported() || shouldUseFrameMetadataScriptTransform())
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function
|
|
17
|
+
export function hasFrameMetadataPublishOptions(options?: FrameMetadataPublishOptions): boolean {
|
|
18
18
|
return !!(options?.timestamp || options?.frameId);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function
|
|
22
|
-
options?:
|
|
21
|
+
export function getFrameMetadataFeatures(
|
|
22
|
+
options?: FrameMetadataPublishOptions,
|
|
23
23
|
): PacketTrailerFeature[] {
|
|
24
24
|
const features: PacketTrailerFeature[] = [];
|
|
25
25
|
if (options?.timestamp) {
|
|
@@ -31,14 +31,14 @@ export function getPacketTrailerFeatures(
|
|
|
31
31
|
return features;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export function
|
|
34
|
+
export function getFrameMetadataPublishOptions(
|
|
35
35
|
features?: PacketTrailerFeature[],
|
|
36
|
-
):
|
|
36
|
+
): FrameMetadataPublishOptions | undefined {
|
|
37
37
|
if (!features || features.length === 0) {
|
|
38
38
|
return undefined;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const options:
|
|
41
|
+
const options: FrameMetadataPublishOptions = {};
|
|
42
42
|
if (features.includes(PacketTrailerFeature.PTF_USER_TIMESTAMP)) {
|
|
43
43
|
options.timestamp = true;
|
|
44
44
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { appendPacketTrailerToEncodedFrame, processPacketTrailer } from '../
|
|
1
|
+
import { appendPacketTrailerToEncodedFrame, processPacketTrailer } from '../frameMetadata';
|
|
2
2
|
import type {
|
|
3
|
+
FrameMetadataPublishOptions,
|
|
3
4
|
PTMetadataMessage,
|
|
4
5
|
PTScriptTransformOptions,
|
|
5
6
|
PTWorkerMessage,
|
|
6
|
-
PacketTrailerPublishOptions,
|
|
7
7
|
} from '../types';
|
|
8
|
-
import {
|
|
8
|
+
import { hasFrameMetadataPublishOptions } from '../utils';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Holds the trackId currently associated with a pipeline. A mutable
|
|
@@ -97,9 +97,9 @@ function setupDecodeTransform(
|
|
|
97
97
|
function setupEncodeTransform(
|
|
98
98
|
readable: ReadableStream,
|
|
99
99
|
writable: WritableStream,
|
|
100
|
-
packetTrailer?:
|
|
100
|
+
packetTrailer?: FrameMetadataPublishOptions,
|
|
101
101
|
) {
|
|
102
|
-
if (!
|
|
102
|
+
if (!hasFrameMetadataPublishOptions(packetTrailer)) {
|
|
103
103
|
readable.pipeTo(writable).catch(() => {});
|
|
104
104
|
return;
|
|
105
105
|
}
|
package/src/index.ts
CHANGED
|
@@ -64,11 +64,22 @@ import {
|
|
|
64
64
|
import { getBrowser } from './utils/browserParser';
|
|
65
65
|
|
|
66
66
|
export { RpcError, type RpcInvocationData, type PerformRpcParams } from './room/rpc';
|
|
67
|
-
export type {
|
|
67
|
+
export type {
|
|
68
|
+
FrameMetadata,
|
|
69
|
+
FrameMetadataPublishOptions,
|
|
70
|
+
/** @deprecated Use {@link FrameMetadata} instead. */
|
|
71
|
+
PacketTrailerMetadata,
|
|
72
|
+
/** @deprecated Use {@link FrameMetadataPublishOptions} instead. */
|
|
73
|
+
PacketTrailerPublishOptions,
|
|
74
|
+
} from './frameMetadata/types';
|
|
68
75
|
export {
|
|
76
|
+
FrameMetadataManager,
|
|
77
|
+
/** @deprecated Use {@link FrameMetadataManager} instead. */
|
|
69
78
|
PacketTrailerManager,
|
|
79
|
+
type FrameMetadataOptions,
|
|
80
|
+
/** @deprecated Use {@link FrameMetadataOptions} instead. */
|
|
70
81
|
type PacketTrailerOptions,
|
|
71
|
-
} from './
|
|
82
|
+
} from './frameMetadata/FrameMetadataManager';
|
|
72
83
|
|
|
73
84
|
export * from './connectionHelper/ConnectionCheck';
|
|
74
85
|
export * from './connectionHelper/checks/Checker';
|
package/src/options.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { E2EEOptions } from './e2ee/types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { FrameMetadataOptions } from './frameMetadata/FrameMetadataManager';
|
|
3
3
|
import type { ReconnectPolicy } from './room/ReconnectPolicy';
|
|
4
4
|
import type {
|
|
5
5
|
AudioCaptureOptions,
|
|
@@ -103,10 +103,15 @@ export interface InternalRoomOptions {
|
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
105
|
* @experimental
|
|
106
|
-
* Options for enabling
|
|
107
|
-
*
|
|
106
|
+
* Options for enabling frame metadata on video tracks.
|
|
107
|
+
* Frame metadata carries frame-level information such as user timestamps and frame IDs.
|
|
108
108
|
*/
|
|
109
|
-
|
|
109
|
+
frameMetadata?: FrameMetadataOptions;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @deprecated Use {@link InternalRoomOptions.frameMetadata} instead.
|
|
113
|
+
*/
|
|
114
|
+
packetTrailer?: FrameMetadataOptions;
|
|
110
115
|
|
|
111
116
|
/**
|
|
112
117
|
* will attempt to connect via single peer connection mode.
|