livekit-client 2.17.0 → 2.17.2
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 +7 -2
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +2350 -1430
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/e2ee/KeyProvider.d.ts +4 -2
- package/dist/src/e2ee/KeyProvider.d.ts.map +1 -1
- package/dist/src/index.d.ts +9 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/logger.d.ts +2 -1
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/data-stream/incoming/IncomingDataStreamManager.d.ts.map +1 -1
- package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts.map +1 -1
- package/dist/src/room/data-track/depacketizer.d.ts +51 -0
- package/dist/src/room/data-track/depacketizer.d.ts.map +1 -0
- package/dist/src/room/data-track/frame.d.ts +7 -0
- package/dist/src/room/data-track/frame.d.ts.map +1 -0
- package/dist/src/room/data-track/handle.d.ts +27 -0
- package/dist/src/room/data-track/handle.d.ts.map +1 -0
- package/dist/src/room/data-track/packet/constants.d.ts +20 -0
- package/dist/src/room/data-track/packet/constants.d.ts.map +1 -0
- package/dist/src/room/data-track/packet/errors.d.ts +42 -0
- package/dist/src/room/data-track/packet/errors.d.ts.map +1 -0
- package/dist/src/room/data-track/packet/extensions.d.ts +68 -0
- package/dist/src/room/data-track/packet/extensions.d.ts.map +1 -0
- package/dist/src/room/data-track/packet/index.d.ts +91 -0
- package/dist/src/room/data-track/packet/index.d.ts.map +1 -0
- package/dist/src/room/data-track/packet/serializable.d.ts +12 -0
- package/dist/src/room/data-track/packet/serializable.d.ts.map +1 -0
- package/dist/src/room/data-track/packetizer.d.ts +43 -0
- package/dist/src/room/data-track/packetizer.d.ts.map +1 -0
- package/dist/src/room/data-track/utils.d.ts +60 -0
- package/dist/src/room/data-track/utils.d.ts.map +1 -0
- package/dist/src/room/errors.d.ts +16 -4
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +1 -0
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/types.d.ts +1 -0
- package/dist/src/room/types.d.ts.map +1 -1
- package/dist/src/utils/TypedPromise.d.ts +4 -0
- package/dist/src/utils/TypedPromise.d.ts.map +1 -1
- package/dist/src/utils/throws.d.ts +36 -0
- package/dist/src/utils/throws.d.ts.map +1 -0
- package/dist/ts4.2/e2ee/KeyProvider.d.ts +4 -2
- package/dist/ts4.2/index.d.ts +10 -3
- package/dist/ts4.2/logger.d.ts +2 -1
- package/dist/ts4.2/room/data-track/depacketizer.d.ts +51 -0
- package/dist/ts4.2/room/data-track/frame.d.ts +7 -0
- package/dist/ts4.2/room/data-track/handle.d.ts +27 -0
- package/dist/ts4.2/room/data-track/packet/constants.d.ts +20 -0
- package/dist/ts4.2/room/data-track/packet/errors.d.ts +42 -0
- package/dist/ts4.2/room/data-track/packet/extensions.d.ts +68 -0
- package/dist/ts4.2/room/data-track/packet/index.d.ts +98 -0
- package/dist/ts4.2/room/data-track/packet/serializable.d.ts +12 -0
- package/dist/ts4.2/room/data-track/packetizer.d.ts +43 -0
- package/dist/ts4.2/room/data-track/utils.d.ts +60 -0
- package/dist/ts4.2/room/errors.d.ts +16 -4
- package/dist/ts4.2/room/track/LocalTrack.d.ts +1 -0
- package/dist/ts4.2/room/types.d.ts +1 -0
- package/dist/ts4.2/utils/TypedPromise.d.ts +4 -0
- package/dist/ts4.2/utils/throws.d.ts +39 -0
- package/package.json +12 -10
- package/src/e2ee/KeyProvider.ts +4 -2
- package/src/index.ts +21 -5
- package/src/logger.ts +1 -0
- package/src/room/PCTransport.ts +1 -0
- package/src/room/PCTransportManager.ts +27 -9
- package/src/room/RTCEngine.ts +13 -2
- package/src/room/Room.ts +1 -1
- package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +1 -0
- package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +2 -1
- package/src/room/data-track/depacketizer.test.ts +442 -0
- package/src/room/data-track/depacketizer.ts +298 -0
- package/src/room/data-track/frame.ts +8 -0
- package/src/room/data-track/handle.test.ts +13 -0
- package/src/room/data-track/handle.ts +80 -0
- package/src/room/data-track/packet/constants.ts +27 -0
- package/src/room/data-track/packet/errors.ts +121 -0
- package/src/room/data-track/packet/extensions.ts +259 -0
- package/src/room/data-track/packet/index.test.ts +615 -0
- package/src/room/data-track/packet/index.ts +363 -0
- package/src/room/data-track/packet/serializable.ts +29 -0
- package/src/room/data-track/packetizer.test.ts +131 -0
- package/src/room/data-track/packetizer.ts +128 -0
- package/src/room/data-track/utils.test.ts +54 -0
- package/src/room/data-track/utils.ts +206 -0
- package/src/room/errors.ts +23 -5
- package/src/room/track/LocalAudioTrack.ts +4 -7
- package/src/room/track/LocalTrack.ts +4 -0
- package/src/room/types.ts +3 -1
- package/src/utils/TypedPromise.ts +7 -0
- package/src/utils/throws.ts +42 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Throws } from '../../../utils/throws';
|
|
2
|
+
import { DataTrackHandle } from '../handle';
|
|
3
|
+
import { DataTrackTimestamp, U16_MAX_SIZE, WrapAroundUnsignedInt } from '../utils';
|
|
4
|
+
import type { DataTrackDeserializeErrorAll, DataTrackSerializeErrorAll } from './errors';
|
|
5
|
+
import { DataTrackSerializeError, DataTrackSerializeErrorReason } from './errors';
|
|
6
|
+
import { DataTrackExtensions } from './extensions';
|
|
7
|
+
import Serializable from './serializable';
|
|
8
|
+
/** A class for serializing / deserializing data track packet header sections. */
|
|
9
|
+
export declare class DataTrackPacketHeader extends Serializable {
|
|
10
|
+
marker: FrameMarker;
|
|
11
|
+
trackHandle: DataTrackHandle;
|
|
12
|
+
sequence: WrapAroundUnsignedInt<typeof U16_MAX_SIZE>;
|
|
13
|
+
frameNumber: WrapAroundUnsignedInt<typeof U16_MAX_SIZE>;
|
|
14
|
+
timestamp: DataTrackTimestamp<90000>;
|
|
15
|
+
extensions: DataTrackExtensions;
|
|
16
|
+
constructor(opts: {
|
|
17
|
+
marker: FrameMarker;
|
|
18
|
+
trackHandle: DataTrackHandle;
|
|
19
|
+
sequence: WrapAroundUnsignedInt<typeof U16_MAX_SIZE>;
|
|
20
|
+
frameNumber: WrapAroundUnsignedInt<typeof U16_MAX_SIZE>;
|
|
21
|
+
timestamp: DataTrackTimestamp<90000>;
|
|
22
|
+
extensions?: DataTrackExtensions;
|
|
23
|
+
});
|
|
24
|
+
private extensionsMetrics;
|
|
25
|
+
toBinaryLengthBytes(): number;
|
|
26
|
+
toBinaryInto(dataView: DataView): Throws<number, DataTrackSerializeError<DataTrackSerializeErrorReason.TooSmallForHeader>>;
|
|
27
|
+
static fromBinary<Input extends DataView | ArrayBuffer | Uint8Array>(input: Input): Throws<[
|
|
28
|
+
header: DataTrackPacketHeader,
|
|
29
|
+
byteLength: number
|
|
30
|
+
], DataTrackDeserializeErrorAll>;
|
|
31
|
+
toJSON(): {
|
|
32
|
+
marker: FrameMarker;
|
|
33
|
+
trackHandle: number;
|
|
34
|
+
sequence: number;
|
|
35
|
+
frameNumber: number;
|
|
36
|
+
timestamp: number;
|
|
37
|
+
extensions: {
|
|
38
|
+
userTimestamp: {
|
|
39
|
+
tag: number;
|
|
40
|
+
lengthBytes: number;
|
|
41
|
+
timestamp: bigint;
|
|
42
|
+
} | null;
|
|
43
|
+
e2ee: {
|
|
44
|
+
tag: number;
|
|
45
|
+
lengthBytes: number;
|
|
46
|
+
keyIndex: number;
|
|
47
|
+
iv: Uint8Array<ArrayBufferLike>;
|
|
48
|
+
} | null;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Marker indicating a packet's position in relation to a frame. */
|
|
53
|
+
export declare enum FrameMarker {
|
|
54
|
+
/** Packet is the first in a frame. */
|
|
55
|
+
Start = 0,
|
|
56
|
+
/** Packet is within a frame. */
|
|
57
|
+
Inter = 1,
|
|
58
|
+
/** Packet is the last in a frame. */
|
|
59
|
+
Final = 2,
|
|
60
|
+
/** Packet is the only one in a frame. */
|
|
61
|
+
Single = 3
|
|
62
|
+
}
|
|
63
|
+
/** A class for serializing / deserializing data track packets. */
|
|
64
|
+
export declare class DataTrackPacket extends Serializable {
|
|
65
|
+
header: DataTrackPacketHeader;
|
|
66
|
+
payload: Uint8Array;
|
|
67
|
+
constructor(header: DataTrackPacketHeader, payload: Uint8Array);
|
|
68
|
+
toBinaryLengthBytes(): number;
|
|
69
|
+
toBinaryInto(dataView: DataView): Throws<number, DataTrackSerializeErrorAll>;
|
|
70
|
+
static fromBinary<Input extends DataView | ArrayBuffer | Uint8Array>(input: Input): Throws<[
|
|
71
|
+
packet: DataTrackPacket,
|
|
72
|
+
byteLength: number
|
|
73
|
+
], DataTrackDeserializeErrorAll>;
|
|
74
|
+
toJSON(): {
|
|
75
|
+
header: {
|
|
76
|
+
marker: FrameMarker;
|
|
77
|
+
trackHandle: number;
|
|
78
|
+
sequence: number;
|
|
79
|
+
frameNumber: number;
|
|
80
|
+
timestamp: number;
|
|
81
|
+
extensions: {
|
|
82
|
+
userTimestamp: {
|
|
83
|
+
tag: number;
|
|
84
|
+
lengthBytes: number;
|
|
85
|
+
timestamp: bigint;
|
|
86
|
+
} | null;
|
|
87
|
+
e2ee: {
|
|
88
|
+
tag: number;
|
|
89
|
+
lengthBytes: number;
|
|
90
|
+
keyIndex: number;
|
|
91
|
+
iv: Uint8Array<ArrayBufferLike>;
|
|
92
|
+
} | null;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
payload: Uint8Array<ArrayBufferLike>;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Throws } from '../../../utils/throws';
|
|
2
|
+
import type { DataTrackSerializeErrorAll } from './errors';
|
|
3
|
+
/** An abstract class implementing common behavior related to data track binary serialization. */
|
|
4
|
+
export default abstract class Serializable {
|
|
5
|
+
/** Returns the expected length of the serialized output in bytes */
|
|
6
|
+
abstract toBinaryLengthBytes(): number;
|
|
7
|
+
/** Given a DataView, serialize the instance inside and return the number of bytes written. */
|
|
8
|
+
abstract toBinaryInto(dataView: DataView): Throws<number, DataTrackSerializeErrorAll>;
|
|
9
|
+
/** Encodes the instance as binary and returns the data as a Uint8Array. */
|
|
10
|
+
toBinary(): Throws<Uint8Array, DataTrackSerializeErrorAll>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=serializable.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Throws } from '../../utils/throws';
|
|
2
|
+
import { LivekitReasonedError } from '../errors';
|
|
3
|
+
import type { DataTrackFrame } from './frame';
|
|
4
|
+
import { DataTrackHandle } from './handle';
|
|
5
|
+
import { DataTrackPacket, FrameMarker } from './packet';
|
|
6
|
+
import { DataTrackTimestamp } from './utils';
|
|
7
|
+
type PacketizeOptions = {
|
|
8
|
+
/** "now" timestamp to use as a base when generating new packet timestamps. If not specified,
|
|
9
|
+
* defaults to the return value of {@link DataTrackClock#now}. */
|
|
10
|
+
now?: DataTrackTimestamp<90000>;
|
|
11
|
+
};
|
|
12
|
+
export declare class DataTrackPacketizerError<Reason extends DataTrackPacketizerReason> extends LivekitReasonedError<Reason> {
|
|
13
|
+
readonly name = "DataTrackPacketizerError";
|
|
14
|
+
reason: Reason;
|
|
15
|
+
reasonName: string;
|
|
16
|
+
constructor(message: string, reason: Reason, options?: {
|
|
17
|
+
cause?: unknown;
|
|
18
|
+
});
|
|
19
|
+
static mtuTooShort(): DataTrackPacketizerError<DataTrackPacketizerReason>;
|
|
20
|
+
}
|
|
21
|
+
export declare enum DataTrackPacketizerReason {
|
|
22
|
+
MtuTooShort = 0
|
|
23
|
+
}
|
|
24
|
+
/** A packetizer takes a {@link DataTrackFrame} as input and generates a series
|
|
25
|
+
* of {@link DataTrackPacket}s for transmission to other clients over webrtc. */
|
|
26
|
+
export declare class DataTrackPacketizer {
|
|
27
|
+
private handle;
|
|
28
|
+
private mtuSizeBytes;
|
|
29
|
+
private sequence;
|
|
30
|
+
private frameNumber;
|
|
31
|
+
private clock;
|
|
32
|
+
constructor(trackHandle: DataTrackHandle, mtuSizeBytes: number);
|
|
33
|
+
/** @internal */
|
|
34
|
+
static computeFrameMarker(index: number, packetCount: number): FrameMarker;
|
|
35
|
+
/** Generates a series of packets for the specified {@link DataTrackPacketizerFrame}.
|
|
36
|
+
*
|
|
37
|
+
* NOTE: The return value of this function is a generator, so it can be lazily ran if desired,
|
|
38
|
+
* or converted to an array with {@link Array.from}.
|
|
39
|
+
*/
|
|
40
|
+
packetize(frame: DataTrackFrame, options?: PacketizeOptions): Throws<Generator<DataTrackPacket>, DataTrackPacketizerError<DataTrackPacketizerReason.MtuTooShort>>;
|
|
41
|
+
}
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=packetizer.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export declare const U16_MAX_SIZE = 65535;
|
|
2
|
+
export declare const U32_MAX_SIZE = 4294967295;
|
|
3
|
+
/**
|
|
4
|
+
* A number of fields withing the data tracks packet specification assume wrap around behavior when
|
|
5
|
+
* an unsigned type is incremented beyond its max size (ie, the packet `sequence` field). This
|
|
6
|
+
* wrapper type manually reimplements this wrap around behavior given javascript's lack of fixed
|
|
7
|
+
* size integer types.
|
|
8
|
+
*/
|
|
9
|
+
export declare class WrapAroundUnsignedInt<MaxSize extends number> {
|
|
10
|
+
value: number;
|
|
11
|
+
private maxSize;
|
|
12
|
+
static u16(raw: number): WrapAroundUnsignedInt<65535>;
|
|
13
|
+
static u32(raw: number): WrapAroundUnsignedInt<4294967295>;
|
|
14
|
+
constructor(raw: number, maxSize: MaxSize);
|
|
15
|
+
/** Manually clamp the given containing value according to the wrap around max size bounds. Use
|
|
16
|
+
* this after out of bounds modification to the contained value by external code. */
|
|
17
|
+
clamp(): void;
|
|
18
|
+
clone(): WrapAroundUnsignedInt<MaxSize>;
|
|
19
|
+
/** When called, maps the containing value to a new containing value. After mapping, the wrap
|
|
20
|
+
* around external max size bounds are applied. Note that this is a mutative operation. */
|
|
21
|
+
update(updateFn: (value: number) => number): void;
|
|
22
|
+
/** Increments the given `n` to the inner value. Note that this is a mutative operation. */
|
|
23
|
+
increment(n?: number): void;
|
|
24
|
+
/** Decrements the given `n` from the inner value. Note that this is a mutative operation. */
|
|
25
|
+
decrement(n?: number): void;
|
|
26
|
+
getThenIncrement(): WrapAroundUnsignedInt<MaxSize>;
|
|
27
|
+
/** Returns true if {@link this} is before the passed other {@link WrapAroundUnsignedInt}. */
|
|
28
|
+
isBefore(other: WrapAroundUnsignedInt<MaxSize>): boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare class DataTrackTimestamp<RateInHz extends number> {
|
|
31
|
+
rateInHz: RateInHz;
|
|
32
|
+
timestamp: WrapAroundUnsignedInt<typeof U32_MAX_SIZE>;
|
|
33
|
+
static fromRtpTicks(rtpTicks: number): DataTrackTimestamp<90000>;
|
|
34
|
+
/** Generates a timestamp initialized to a non cryptographically secure random value, so that
|
|
35
|
+
* different streams are more difficult to correlate in packet capture. */
|
|
36
|
+
static rtpRandom(): DataTrackTimestamp<90000>;
|
|
37
|
+
private constructor();
|
|
38
|
+
asTicks(): number;
|
|
39
|
+
clone(): DataTrackTimestamp<RateInHz>;
|
|
40
|
+
wrappingAdd(n: number): void;
|
|
41
|
+
/** Returns true if {@link this} is before the passed other {@link DataTrackTimestamp}. */
|
|
42
|
+
isBefore(other: DataTrackTimestamp<RateInHz>): boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare class DataTrackClock<RateInHz extends number> {
|
|
45
|
+
epoch: Date;
|
|
46
|
+
base: DataTrackTimestamp<RateInHz>;
|
|
47
|
+
previous: DataTrackTimestamp<RateInHz>;
|
|
48
|
+
rateInHz: RateInHz;
|
|
49
|
+
private constructor();
|
|
50
|
+
static startingNow<RateInHz extends number>(base: DataTrackTimestamp<RateInHz>, rateInHz: RateInHz): DataTrackClock<RateInHz>;
|
|
51
|
+
static startingAtTime<RateInHz extends number>(epoch: Date, base: DataTrackTimestamp<RateInHz>, rateInHz: RateInHz): DataTrackClock<RateInHz>;
|
|
52
|
+
static rtpStartingNow(base: DataTrackTimestamp<90000>): DataTrackClock<90000>;
|
|
53
|
+
static rtpStartingAtTime(epoch: Date, base: DataTrackTimestamp<90000>): DataTrackClock<90000>;
|
|
54
|
+
now(): DataTrackTimestamp<RateInHz>;
|
|
55
|
+
at(timestamp: Date): DataTrackTimestamp<RateInHz>;
|
|
56
|
+
/** Convert a duration since the epoch into clock ticks. */
|
|
57
|
+
static durationInMsToTicks(durationMilliseconds: number, rateInHz: number): number;
|
|
58
|
+
}
|
|
59
|
+
export declare function coerceToDataView<Input extends DataView | ArrayBuffer | Uint8Array>(input: Input): DataView;
|
|
60
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { DisconnectReason, RequestResponse_Reason } from '@livekit/protocol';
|
|
2
|
+
/** Base error that all LiveKit specific custom errors inherit from. */
|
|
2
3
|
export declare class LivekitError extends Error {
|
|
3
4
|
code: number;
|
|
4
|
-
|
|
5
|
+
cause?: unknown;
|
|
6
|
+
constructor(code: number, message?: string, options?: {
|
|
7
|
+
cause?: unknown;
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* LiveKit specific error type representing an error with an associated set of reasons.
|
|
12
|
+
* Use this to represent an error with multiple different but contextually related variants.
|
|
13
|
+
* */
|
|
14
|
+
export declare abstract class LivekitReasonedError<Reason> extends LivekitError {
|
|
15
|
+
abstract reason: Reason;
|
|
16
|
+
abstract reasonName: string;
|
|
5
17
|
}
|
|
6
18
|
export declare class SimulatedError extends LivekitError {
|
|
7
19
|
readonly name = "simulated";
|
|
@@ -61,7 +73,7 @@ type ServiceNotFound = {
|
|
|
61
73
|
context: string;
|
|
62
74
|
};
|
|
63
75
|
type ConnectionErrorVariants = NotAllowed | ConnectionTimeout | LeaveRequest | InternalError | Cancelled | ServerUnreachable | WebSocket | ServiceNotFound;
|
|
64
|
-
export declare class ConnectionError<Variant extends ConnectionErrorVariants = ConnectionErrorVariants> extends
|
|
76
|
+
export declare class ConnectionError<Variant extends ConnectionErrorVariants = ConnectionErrorVariants> extends LivekitReasonedError<Variant['reason']> {
|
|
65
77
|
status?: Variant['status'];
|
|
66
78
|
context: Variant['context'];
|
|
67
79
|
reason: Variant['reason'];
|
|
@@ -110,7 +122,7 @@ export declare class PublishTrackError extends LivekitError {
|
|
|
110
122
|
constructor(message: string, status: number);
|
|
111
123
|
}
|
|
112
124
|
export type RequestErrorReason = Exclude<RequestResponse_Reason, RequestResponse_Reason.OK> | 'TimeoutError';
|
|
113
|
-
export declare class SignalRequestError extends
|
|
125
|
+
export declare class SignalRequestError extends LivekitReasonedError<RequestErrorReason> {
|
|
114
126
|
readonly name = "SignalRequestError";
|
|
115
127
|
reason: RequestErrorReason;
|
|
116
128
|
reasonName: string;
|
|
@@ -125,7 +137,7 @@ export declare enum DataStreamErrorReason {
|
|
|
125
137
|
HandlerAlreadyRegistered = 7,
|
|
126
138
|
EncryptionTypeMismatch = 8
|
|
127
139
|
}
|
|
128
|
-
export declare class DataStreamError extends
|
|
140
|
+
export declare class DataStreamError extends LivekitReasonedError<DataStreamErrorReason> {
|
|
129
141
|
readonly name = "DataStreamError";
|
|
130
142
|
reason: DataStreamErrorReason;
|
|
131
143
|
reasonName: string;
|
|
@@ -27,6 +27,7 @@ export default abstract class LocalTrack<TrackKind extends Track.Kind = Track.Ki
|
|
|
27
27
|
protected manuallyStopped: boolean;
|
|
28
28
|
protected localTrackRecorder: LocalTrackRecorder<typeof this> | undefined;
|
|
29
29
|
protected trackChangeLock: Mutex;
|
|
30
|
+
protected pendingDeviceChange: boolean;
|
|
30
31
|
/**
|
|
31
32
|
*
|
|
32
33
|
* @param mediaTrack
|
|
@@ -2,6 +2,10 @@ type InferErrors<T> = T extends TypedPromise<any, infer E> ? E : never;
|
|
|
2
2
|
export default class TypedPromise<T, E extends Error> extends Promise<T> {
|
|
3
3
|
constructor(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason: E) => void) => void);
|
|
4
4
|
catch<TResult = never>(onrejected?: ((reason: E) => TResult | PromiseLike<TResult>) | null | undefined): TypedPromise<T | TResult, E>;
|
|
5
|
+
static resolve: {
|
|
6
|
+
(): TypedPromise<void, never>;
|
|
7
|
+
<V>(value: V): TypedPromise<Awaited<V>, never>;
|
|
8
|
+
};
|
|
5
9
|
static reject<E extends Error>(reason: E): TypedPromise<never, E>;
|
|
6
10
|
static all<T extends readonly unknown[] | [
|
|
7
11
|
]>(values: T): TypedPromise<{
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type Primitives = null | undefined | string | number | bigint | boolean | symbol;
|
|
2
|
+
/**
|
|
3
|
+
* Branded type that encodes possible thrown errors in the return type.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* function fetchUser(id: string): Throws<User, NetworkError | NotFoundError> { ... }
|
|
7
|
+
*
|
|
8
|
+
* The actual runtime value is just T - the error types are phantom types
|
|
9
|
+
* that exist only for static analysis.
|
|
10
|
+
*
|
|
11
|
+
* To indicate that a function shouldn't throw any errors, make it return `Throws<T, never>`.
|
|
12
|
+
*
|
|
13
|
+
* For more info about how this is checked, see ./throws-transformer at the root of this repo.
|
|
14
|
+
*/
|
|
15
|
+
export type Throws<T, E extends Error> = (T & {
|
|
16
|
+
readonly __throws?: E;
|
|
17
|
+
}) | Extract<T, Primitives>;
|
|
18
|
+
/**
|
|
19
|
+
* Extract the error types from a Throws type.
|
|
20
|
+
*/
|
|
21
|
+
export type ExtractErrors<T> = T extends Throws<any, infer E> ? E : never;
|
|
22
|
+
/**
|
|
23
|
+
* Extract the success type from a Throws type.
|
|
24
|
+
*/
|
|
25
|
+
export type ExtractSuccess<T> = T extends Throws<infer S, any> ? S : T;
|
|
26
|
+
/**
|
|
27
|
+
* Combine error types from multiple Throws types.
|
|
28
|
+
*/
|
|
29
|
+
export type CombineErrors<T extends any[]> = T extends [
|
|
30
|
+
infer First,
|
|
31
|
+
...infer Rest
|
|
32
|
+
] ? ExtractErrors<First> | CombineErrors<Rest> : never;
|
|
33
|
+
/**
|
|
34
|
+
* Helper to propagate errors - use this when your function calls other
|
|
35
|
+
* throwing functions and wants to propagate their errors.
|
|
36
|
+
*/
|
|
37
|
+
export type PropagatesErrors<T, AdditionalErrors extends Error = never> = Throws<ExtractSuccess<T>, ExtractErrors<T> | AdditionalErrors>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=throws.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livekit-client",
|
|
3
|
-
"version": "2.17.
|
|
3
|
+
"version": "2.17.2",
|
|
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",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"license": "Apache-2.0",
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@livekit/mutex": "1.1.1",
|
|
40
|
-
"@livekit/protocol": "1.
|
|
40
|
+
"@livekit/protocol": "1.44.0",
|
|
41
41
|
"events": "^3.3.0",
|
|
42
42
|
"jose": "^6.1.0",
|
|
43
43
|
"loglevel": "^1.9.2",
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
"@types/dom-mediacapture-record": "^1"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@babel/core": "7.
|
|
55
|
-
"@babel/preset-env": "7.
|
|
54
|
+
"@babel/core": "7.29.0",
|
|
55
|
+
"@babel/preset-env": "7.29.0",
|
|
56
56
|
"@bufbuild/protoc-gen-es": "^1.10.0",
|
|
57
|
-
"@changesets/cli": "2.29.
|
|
58
|
-
"@eslint/js": "9.39.
|
|
57
|
+
"@changesets/cli": "2.29.8",
|
|
58
|
+
"@eslint/js": "9.39.2",
|
|
59
59
|
"@livekit/changesets-changelog-github": "^0.0.4",
|
|
60
60
|
"@rollup/plugin-babel": "6.1.0",
|
|
61
61
|
"@rollup/plugin-commonjs": "28.0.9",
|
|
@@ -72,25 +72,26 @@
|
|
|
72
72
|
"@typescript-eslint/eslint-plugin": "7.18.0",
|
|
73
73
|
"@typescript-eslint/parser": "7.18.0",
|
|
74
74
|
"downlevel-dts": "^0.11.0",
|
|
75
|
-
"eslint": "9.39.
|
|
75
|
+
"eslint": "9.39.2",
|
|
76
76
|
"eslint-config-airbnb-extended": "^2.3.2",
|
|
77
77
|
"eslint-config-prettier": "10.1.8",
|
|
78
78
|
"eslint-plugin-compat": "^6.0.2",
|
|
79
79
|
"eslint-plugin-import-x": "^4.16.1",
|
|
80
80
|
"eslint-plugin-prettier": "^5.5.4",
|
|
81
81
|
"gh-pages": "6.3.0",
|
|
82
|
+
"glob": "^13.0.0",
|
|
82
83
|
"happy-dom": "^17.2.0",
|
|
83
84
|
"jsdom": "^26.1.0",
|
|
84
85
|
"prettier": "^3.4.2",
|
|
85
|
-
"rollup": "4.
|
|
86
|
+
"rollup": "4.57.1",
|
|
86
87
|
"rollup-plugin-delete": "^2.1.0",
|
|
87
88
|
"rollup-plugin-typescript2": "0.36.0",
|
|
88
89
|
"size-limit": "^11.2.0",
|
|
89
|
-
"typedoc": "0.28.
|
|
90
|
+
"typedoc": "0.28.16",
|
|
90
91
|
"typedoc-plugin-no-inherit": "1.6.1",
|
|
91
92
|
"typescript": "5.8.3",
|
|
92
93
|
"typescript-eslint": "^8.47.0",
|
|
93
|
-
"vite": "7.
|
|
94
|
+
"vite": "7.3.1",
|
|
94
95
|
"vitest": "^3.0.0"
|
|
95
96
|
},
|
|
96
97
|
"scripts": {
|
|
@@ -107,6 +108,7 @@
|
|
|
107
108
|
"deploy": "gh-pages -d examples/demo/dist",
|
|
108
109
|
"format": "prettier --write src examples/**/*.ts",
|
|
109
110
|
"format:check": "prettier --check src examples/**/*.ts",
|
|
111
|
+
"throws:check": "pnpm dlx tsx ./throws-transformer/cli.ts 'src/!(*.test).ts' 'src/**/!(*.test).ts'",
|
|
110
112
|
"ci:publish": "pnpm build:clean && pnpm compat && changeset publish",
|
|
111
113
|
"downlevel-dts": "downlevel-dts ./dist/src ./dist/ts4.2 --to=4.2",
|
|
112
114
|
"compat": "eslint --config ./eslint.config.dist.mjs --no-inline-config ./dist/livekit-client.esm.mjs",
|
package/src/e2ee/KeyProvider.ts
CHANGED
|
@@ -91,8 +91,10 @@ export class ExternalE2EEKeyProvider extends BaseKeyProvider {
|
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
* Accepts a passphrase that's used to create the crypto keys.
|
|
94
|
-
* When passing in a string, PBKDF2 is used.
|
|
95
|
-
* When passing in an
|
|
94
|
+
* When passing in a string, PBKDF2 is used. (recommended for maximum compatibility across SDKs)
|
|
95
|
+
* When passing in an ArrayBuffer of cryptographically random numbers, HKDF is used.
|
|
96
|
+
*
|
|
97
|
+
* Note: Not all client SDKS support HKDF.
|
|
96
98
|
* @param key
|
|
97
99
|
*/
|
|
98
100
|
async setKey(key: string | ArrayBuffer) {
|
package/src/index.ts
CHANGED
|
@@ -9,11 +9,18 @@ import {
|
|
|
9
9
|
import { LogLevel, LoggerNames, getLogger, setLogExtension, setLogLevel } from './logger';
|
|
10
10
|
import DefaultReconnectPolicy from './room/DefaultReconnectPolicy';
|
|
11
11
|
import type { ReconnectContext, ReconnectPolicy } from './room/ReconnectPolicy';
|
|
12
|
-
import Room, { ConnectionState } from './room/Room';
|
|
13
|
-
import type { RoomEventCallbacks } from './room/Room';
|
|
12
|
+
import Room, { ConnectionState, type RoomEventCallbacks } from './room/Room';
|
|
14
13
|
import * as attributes from './room/attribute-typings';
|
|
14
|
+
// FIXME: remove this import in a follow up data track pull request.
|
|
15
|
+
import './room/data-track/depacketizer';
|
|
16
|
+
// FIXME: remove this import in a follow up data track pull request.
|
|
17
|
+
import './room/data-track/packetizer';
|
|
15
18
|
import LocalParticipant from './room/participant/LocalParticipant';
|
|
16
|
-
import Participant, {
|
|
19
|
+
import Participant, {
|
|
20
|
+
ConnectionQuality,
|
|
21
|
+
type ParticipantEventCallbacks,
|
|
22
|
+
ParticipantKind,
|
|
23
|
+
} from './room/participant/Participant';
|
|
17
24
|
import type { ParticipantTrackPermission } from './room/participant/ParticipantTrackPermission';
|
|
18
25
|
import RemoteParticipant from './room/participant/RemoteParticipant';
|
|
19
26
|
import type {
|
|
@@ -32,8 +39,8 @@ import RemoteTrack from './room/track/RemoteTrack';
|
|
|
32
39
|
import RemoteTrackPublication from './room/track/RemoteTrackPublication';
|
|
33
40
|
import type { ElementInfo } from './room/track/RemoteVideoTrack';
|
|
34
41
|
import RemoteVideoTrack from './room/track/RemoteVideoTrack';
|
|
35
|
-
import { TrackPublication } from './room/track/TrackPublication';
|
|
36
|
-
import type { LiveKitReactNativeInfo } from './room/types';
|
|
42
|
+
import { type PublicationEventCallbacks, TrackPublication } from './room/track/TrackPublication';
|
|
43
|
+
import type { LiveKitReactNativeInfo, TextStreamInfo } from './room/types';
|
|
37
44
|
import type { AudioAnalyserOptions } from './room/utils';
|
|
38
45
|
import {
|
|
39
46
|
compareVersions,
|
|
@@ -140,6 +147,7 @@ export type {
|
|
|
140
147
|
AudioAnalyserOptions,
|
|
141
148
|
ElementInfo,
|
|
142
149
|
LiveKitReactNativeInfo,
|
|
150
|
+
TextStreamInfo,
|
|
143
151
|
ParticipantTrackPermission,
|
|
144
152
|
AudioReceiverStats,
|
|
145
153
|
AudioSenderStats,
|
|
@@ -148,6 +156,14 @@ export type {
|
|
|
148
156
|
ReconnectContext,
|
|
149
157
|
ReconnectPolicy,
|
|
150
158
|
RoomEventCallbacks,
|
|
159
|
+
ParticipantEventCallbacks,
|
|
160
|
+
PublicationEventCallbacks,
|
|
151
161
|
};
|
|
162
|
+
export { DataTrackPacket, type DataTrackPacketHeader } from './room/data-track/packet';
|
|
163
|
+
export {
|
|
164
|
+
type DataTrackExtensions,
|
|
165
|
+
type DataTrackUserTimestampExtension,
|
|
166
|
+
type DataTrackE2eeExtension,
|
|
167
|
+
} from './room/data-track/packet/extensions';
|
|
152
168
|
|
|
153
169
|
export { LocalTrackRecorder } from './room/track/record';
|
package/src/logger.ts
CHANGED
package/src/room/PCTransport.ts
CHANGED
|
@@ -278,6 +278,7 @@ export default class PCTransport extends EventEmitter {
|
|
|
278
278
|
await this._pc.setRemoteDescription(currentSD);
|
|
279
279
|
} else {
|
|
280
280
|
this.renegotiate = true;
|
|
281
|
+
this.log.debug('requesting renegotiation', { ...this.logContext });
|
|
281
282
|
return;
|
|
282
283
|
}
|
|
283
284
|
} else if (!this._pc || this._pc.signalingState === 'closed') {
|
|
@@ -229,28 +229,46 @@ export class PCTransportManager {
|
|
|
229
229
|
|
|
230
230
|
async negotiate(abortController: AbortController) {
|
|
231
231
|
return new TypedPromise<void, NegotiationError | Error>(async (resolve, reject) => {
|
|
232
|
-
|
|
232
|
+
let negotiationTimeout = setTimeout(() => {
|
|
233
233
|
reject(new NegotiationError('negotiation timed out'));
|
|
234
234
|
}, this.peerConnectionTimeout);
|
|
235
235
|
|
|
236
|
-
const
|
|
236
|
+
const cleanup = () => {
|
|
237
237
|
clearTimeout(negotiationTimeout);
|
|
238
|
+
this.publisher.off(PCEvents.NegotiationStarted, onNegotiationStarted);
|
|
239
|
+
abortController.signal.removeEventListener('abort', abortHandler);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const abortHandler = () => {
|
|
243
|
+
cleanup();
|
|
238
244
|
reject(new NegotiationError('negotiation aborted'));
|
|
239
245
|
};
|
|
240
246
|
|
|
241
|
-
|
|
242
|
-
|
|
247
|
+
// Reset the timeout each time a renegotiation cycle starts. This
|
|
248
|
+
// prevents premature timeouts when the negotiation machinery is
|
|
249
|
+
// actively renegotiating (offers going out, answers coming back) but
|
|
250
|
+
// NegotiationComplete hasn't fired yet because new requirements keep
|
|
251
|
+
// arriving between offer/answer round-trips.
|
|
252
|
+
const onNegotiationStarted = () => {
|
|
243
253
|
if (abortController.signal.aborted) {
|
|
244
254
|
return;
|
|
245
255
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
256
|
+
clearTimeout(negotiationTimeout);
|
|
257
|
+
negotiationTimeout = setTimeout(() => {
|
|
258
|
+
cleanup();
|
|
259
|
+
reject(new NegotiationError('negotiation timed out'));
|
|
260
|
+
}, this.peerConnectionTimeout);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
abortController.signal.addEventListener('abort', abortHandler);
|
|
264
|
+
this.publisher.on(PCEvents.NegotiationStarted, onNegotiationStarted);
|
|
265
|
+
this.publisher.once(PCEvents.NegotiationComplete, () => {
|
|
266
|
+
cleanup();
|
|
267
|
+
resolve();
|
|
250
268
|
});
|
|
251
269
|
|
|
252
270
|
await this.publisher.negotiate((e) => {
|
|
253
|
-
|
|
271
|
+
cleanup();
|
|
254
272
|
if (e instanceof Error) {
|
|
255
273
|
reject(e);
|
|
256
274
|
} else {
|
package/src/room/RTCEngine.ts
CHANGED
|
@@ -1477,8 +1477,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
1477
1477
|
if (!this.pcManager) {
|
|
1478
1478
|
return false;
|
|
1479
1479
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1480
|
+
const allowedConnectionStates: PCTransportState[] = [
|
|
1481
|
+
PCTransportState.CONNECTING,
|
|
1482
|
+
PCTransportState.CONNECTED,
|
|
1483
|
+
];
|
|
1484
|
+
if (!allowedConnectionStates.includes(this.pcManager.currentState)) {
|
|
1482
1485
|
return false;
|
|
1483
1486
|
}
|
|
1484
1487
|
|
|
@@ -1521,6 +1524,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
1521
1524
|
reject(new NegotiationError('cannot negotiate on closed engine'));
|
|
1522
1525
|
}
|
|
1523
1526
|
this.on(EngineEvent.Closing, handleClosed);
|
|
1527
|
+
this.on(EngineEvent.Restarting, handleClosed);
|
|
1524
1528
|
|
|
1525
1529
|
this.pcManager.publisher.once(
|
|
1526
1530
|
PCEvents.RTPVideoPayloadTypes,
|
|
@@ -1540,6 +1544,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
1540
1544
|
await this.pcManager.negotiate(abortController);
|
|
1541
1545
|
resolve();
|
|
1542
1546
|
} catch (e: unknown) {
|
|
1547
|
+
if (abortController.signal.aborted) {
|
|
1548
|
+
// negotiation was aborted due to engine close or restart, resolve
|
|
1549
|
+
// cleanly to avoid triggering a cascading reconnect loop
|
|
1550
|
+
resolve();
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1543
1553
|
if (e instanceof NegotiationError) {
|
|
1544
1554
|
this.fullReconnectOnNext = true;
|
|
1545
1555
|
}
|
|
@@ -1551,6 +1561,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
1551
1561
|
}
|
|
1552
1562
|
} finally {
|
|
1553
1563
|
this.off(EngineEvent.Closing, handleClosed);
|
|
1564
|
+
this.off(EngineEvent.Restarting, handleClosed);
|
|
1554
1565
|
}
|
|
1555
1566
|
});
|
|
1556
1567
|
}
|
package/src/room/Room.ts
CHANGED
|
@@ -2307,7 +2307,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
|
2307
2307
|
engine: this.engine
|
|
2308
2308
|
? {
|
|
2309
2309
|
closed: this.engine.isClosed,
|
|
2310
|
-
|
|
2310
|
+
transportsConnectedOrConnecting: this.engine.verifyTransport(),
|
|
2311
2311
|
}
|
|
2312
2312
|
: undefined,
|
|
2313
2313
|
});
|
|
@@ -191,6 +191,7 @@ export default class IncomingDataStreamManager {
|
|
|
191
191
|
timestamp: Number(streamHeader.timestamp),
|
|
192
192
|
attributes: streamHeader.attributes,
|
|
193
193
|
encryptionType,
|
|
194
|
+
attachedStreamIds: streamHeader.contentHeader.value.attachedStreamIds,
|
|
194
195
|
};
|
|
195
196
|
|
|
196
197
|
const stream = new ReadableStream<DataStream_Chunk>({
|
|
@@ -107,6 +107,7 @@ export default class OutgoingDataStreamManager {
|
|
|
107
107
|
encryptionType: this.engine.e2eeManager?.isDataChannelEncryptionEnabled
|
|
108
108
|
? Encryption_Type.GCM
|
|
109
109
|
: Encryption_Type.NONE,
|
|
110
|
+
attachedStreamIds: options?.attachedStreamIds,
|
|
110
111
|
};
|
|
111
112
|
const header = new DataStream_Header({
|
|
112
113
|
streamId,
|
|
@@ -119,7 +120,7 @@ export default class OutgoingDataStreamManager {
|
|
|
119
120
|
case: 'textHeader',
|
|
120
121
|
value: new DataStream_TextHeader({
|
|
121
122
|
version: options?.version,
|
|
122
|
-
attachedStreamIds:
|
|
123
|
+
attachedStreamIds: info.attachedStreamIds,
|
|
123
124
|
replyToStreamId: options?.replyToStreamId,
|
|
124
125
|
operationType:
|
|
125
126
|
options?.type === 'update'
|