livekit-client 2.22.0 → 2.22.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 +187 -1
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +1764 -121
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.fm.worker.js +1 -1
- package/dist/livekit-client.fm.worker.js.map +1 -1
- package/dist/livekit-client.fm.worker.mjs +187 -1
- package/dist/livekit-client.fm.worker.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +25 -1
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/api/SignalClientStateMachine.d.ts +85 -0
- package/dist/src/api/SignalClientStateMachine.d.ts.map +1 -0
- package/dist/src/api/WebSocketStream.d.ts.map +1 -1
- package/dist/src/api/utils.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -2
- 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/options.d.ts +22 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +2 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +7 -2
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +8 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +1 -1
- package/dist/src/room/statsSummary.d.ts +13 -0
- package/dist/src/room/statsSummary.d.ts.map +1 -0
- package/dist/src/room/token-source/utils.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +10 -0
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/utils/machineInspector.d.ts +54 -0
- package/dist/src/utils/machineInspector.d.ts.map +1 -0
- package/dist/ts4.2/api/SignalClient.d.ts +25 -1
- package/dist/ts4.2/api/SignalClientStateMachine.d.ts +85 -0
- package/dist/ts4.2/index.d.ts +3 -2
- package/dist/ts4.2/logger.d.ts +2 -1
- package/dist/ts4.2/options.d.ts +22 -0
- package/dist/ts4.2/room/PCTransport.d.ts +2 -1
- package/dist/ts4.2/room/RTCEngine.d.ts +7 -2
- package/dist/ts4.2/room/Room.d.ts +8 -1
- package/dist/ts4.2/room/events.d.ts +1 -1
- package/dist/ts4.2/room/statsSummary.d.ts +13 -0
- package/dist/ts4.2/room/track/Track.d.ts +10 -0
- package/dist/ts4.2/utils/machineInspector.d.ts +54 -0
- package/package.json +7 -1
- package/src/api/SignalClient.test.ts +320 -8
- package/src/api/SignalClient.ts +260 -82
- package/src/api/SignalClientStateMachine.test.ts +472 -0
- package/src/api/SignalClientStateMachine.ts +180 -0
- package/src/api/WebSocketStream.ts +19 -3
- package/src/api/utils.test.ts +20 -1
- package/src/api/utils.ts +5 -0
- package/src/index.ts +5 -0
- package/src/logger.ts +1 -0
- package/src/options.ts +24 -0
- package/src/room/PCTransport.ts +2 -1
- package/src/room/RTCEngine.ts +16 -7
- package/src/room/Room.ts +70 -5
- package/src/room/events.ts +1 -1
- package/src/room/statsSummary.ts +187 -0
- package/src/room/token-source/test-tokens.ts +20 -0
- package/src/room/token-source/utils.test.ts +27 -0
- package/src/room/token-source/utils.ts +12 -5
- package/src/room/track/LocalAudioTrack.ts +9 -3
- package/src/room/track/Track.ts +27 -0
- package/src/room/utils.test.ts +24 -1
- package/src/room/utils.ts +1 -1
- package/src/utils/machineInspector.ts +90 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in registry that lets a development tool observe the state machines driving the connection
|
|
3
|
+
* layer.
|
|
4
|
+
*
|
|
5
|
+
* The machines are private to the objects that own them and, more importantly, do not outlive them:
|
|
6
|
+
* a full reconnect replaces the whole engine along with its `SignalClient`, so anything watching a
|
|
7
|
+
* single machine reference goes blind exactly when the interesting part starts. Machines therefore
|
|
8
|
+
* announce themselves here as they are constructed, and a subscriber sees the whole succession.
|
|
9
|
+
*
|
|
10
|
+
* Nothing is recorded until {@link enableMachineInspector} is called, which no shipping code does —
|
|
11
|
+
* with the registry off, announcing is a comparison and a return.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The slice of machina's `Fsm` surface an inspector needs. Structural rather than machina's own
|
|
15
|
+
* type so that any machine satisfies it regardless of its state and input unions.
|
|
16
|
+
*/
|
|
17
|
+
export interface InspectableMachine {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly initialState: string;
|
|
20
|
+
readonly states: Record<string, Record<string, unknown>>;
|
|
21
|
+
readonly context?: unknown;
|
|
22
|
+
currentState(): string;
|
|
23
|
+
canHandle(input: string): boolean;
|
|
24
|
+
on(eventName: string, callback: (data: any) => void): {
|
|
25
|
+
off(): void;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface MachineAnnouncement {
|
|
29
|
+
/** What the machine drives, e.g. `signal`. Not unique: each new `SignalClient` announces one. */
|
|
30
|
+
label: string;
|
|
31
|
+
/** How many machines have been announced before this one, so successive instances are tellable apart. */
|
|
32
|
+
seq: number;
|
|
33
|
+
/**
|
|
34
|
+
* When the machine was constructed. Carried on the announcement because subscribers receive the
|
|
35
|
+
* recorded ones on subscribe, and stamping those at replay time would date them all to whenever
|
|
36
|
+
* the tool happened to open.
|
|
37
|
+
*/
|
|
38
|
+
at: number;
|
|
39
|
+
machine: InspectableMachine;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Starts recording machine announcements. Call before the machines of interest are constructed —
|
|
43
|
+
* for the signal machine that means before the `Room` is created.
|
|
44
|
+
*/
|
|
45
|
+
export declare function enableMachineInspector(): void;
|
|
46
|
+
export declare function isMachineInspectorEnabled(): boolean;
|
|
47
|
+
/** Announces a machine to whatever is watching. A no-op unless the inspector was enabled. */
|
|
48
|
+
export declare function announceMachine(label: string, machine: InspectableMachine): void;
|
|
49
|
+
/**
|
|
50
|
+
* Subscribes to machine announcements, replaying the ones already recorded so that a panel opened
|
|
51
|
+
* after connecting still sees the machine currently in charge. Returns an unsubscribe function.
|
|
52
|
+
*/
|
|
53
|
+
export declare function onMachineAnnounced(callback: (announcement: MachineAnnouncement) => void): () => void;
|
|
54
|
+
//# sourceMappingURL=machineInspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machineInspector.d.ts","sourceRoot":"","sources":["../../../src/utils/machineInspector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,IAAI,MAAM,CAAC;IACvB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG;QAAE,GAAG,IAAI,IAAI,CAAA;KAAE,CAAC;CACvE;AAED,MAAM,WAAW,mBAAmB;IAClC,iGAAiG;IACjG,KAAK,EAAE,MAAM,CAAC;IACd,yGAAyG;IACzG,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AASD;;;GAGG;AACH,wBAAgB,sBAAsB,SAErC;AAED,wBAAgB,yBAAyB,YAExC;AAED,6FAA6F;AAC7F,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,QAczE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,CAAC,YAAY,EAAE,mBAAmB,KAAK,IAAI,cAQvF"}
|
|
@@ -70,6 +70,20 @@ export declare class SignalClient {
|
|
|
70
70
|
ws?: WebSocketStream;
|
|
71
71
|
get currentState(): SignalConnectionState;
|
|
72
72
|
get isDisconnected(): boolean;
|
|
73
|
+
/** Runtime lifecycle state, finer grained than the public {@link currentState} projection. */
|
|
74
|
+
private get lifecycleState();
|
|
75
|
+
/** Id of the current connection attempt and of the transport it owns. */
|
|
76
|
+
private get attemptId();
|
|
77
|
+
/**
|
|
78
|
+
* Applies a lifecycle input and reports whether it moved the machine
|
|
79
|
+
*/
|
|
80
|
+
private sendLifecycleInput;
|
|
81
|
+
/**
|
|
82
|
+
* Waits out a close that is already in flight. Establishing a session while one is tearing down
|
|
83
|
+
* would race it for the transport — the teardown can close the socket the new attempt just
|
|
84
|
+
* opened.
|
|
85
|
+
*/
|
|
86
|
+
private settleInFlightClose;
|
|
73
87
|
private get isEstablishingConnection();
|
|
74
88
|
private getNextRequestId;
|
|
75
89
|
private options?;
|
|
@@ -78,7 +92,7 @@ export declare class SignalClient {
|
|
|
78
92
|
private pingIntervalDuration;
|
|
79
93
|
private pingInterval;
|
|
80
94
|
private closingLock;
|
|
81
|
-
private
|
|
95
|
+
private machine;
|
|
82
96
|
private connectionLock;
|
|
83
97
|
private log;
|
|
84
98
|
private loggerContextCb?;
|
|
@@ -94,6 +108,12 @@ export declare class SignalClient {
|
|
|
94
108
|
/** @internal */
|
|
95
109
|
resetCallbacks: () => void;
|
|
96
110
|
close(updateState?: boolean, reason?: string): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Releases the transport and everything tied to it, without touching the lifecycle state. Used
|
|
113
|
+
* both by {@link close} and by paths that replace the transport under a live lifecycle (a new
|
|
114
|
+
* attempt, or an unexpected close that leaves the client in `offline`).
|
|
115
|
+
*/
|
|
116
|
+
private teardownTransport;
|
|
97
117
|
sendOffer(offer: RTCSessionDescriptionInit, offerId: number): void;
|
|
98
118
|
sendAnswer(answer: RTCSessionDescriptionInit, offerId: number): Promise<void>;
|
|
99
119
|
sendIceCandidate(candidate: RTCIceCandidateInit, target: SignalTarget): Promise<void>;
|
|
@@ -118,6 +138,10 @@ export declare class SignalClient {
|
|
|
118
138
|
private sendRequest;
|
|
119
139
|
private handleSignalResponse;
|
|
120
140
|
setReconnected(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Handles a transport we lost without asking to. The client goes to `offline` rather than
|
|
143
|
+
* `closed`: whether this session gets resumed, restarted or given up on is the engine's call.
|
|
144
|
+
*/
|
|
121
145
|
private handleOnClose;
|
|
122
146
|
private handleWSError;
|
|
123
147
|
/**
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime lifecycle states of the signal connection.
|
|
3
|
+
*
|
|
4
|
+
* `offline` is the resting state after the transport was lost without an explicit close: no
|
|
5
|
+
* attempt is in flight, but a resume is still legal. It is what makes retrying a failed resume
|
|
6
|
+
* expressible — `closed` is only reached by an explicit close or by a terminal attempt failure.
|
|
7
|
+
*/
|
|
8
|
+
export type SignalLifecycleState = 'new' | 'connecting' | 'connected' | 'offline' | 'reconnecting' | 'disconnecting' | 'closed';
|
|
9
|
+
export interface SignalMachineContext {
|
|
10
|
+
/** Monotonic id of the current (re)connection attempt and of the transport it owns */
|
|
11
|
+
attemptId: number;
|
|
12
|
+
/** Error or reason that ended the last attempt, kept for diagnostics. */
|
|
13
|
+
lastError?: unknown;
|
|
14
|
+
/** Reason passed to the last close request. */
|
|
15
|
+
closeReason?: string;
|
|
16
|
+
}
|
|
17
|
+
export type SignalMachineInput =
|
|
18
|
+
/**
|
|
19
|
+
* Start an initial session, or restart from scratch (full reconnect).
|
|
20
|
+
*
|
|
21
|
+
* Establishing is legal exactly where no transport and no attempt are in play: `new`, `offline`
|
|
22
|
+
* and `closed`. `closed` is included because it means "no transport", not "session over" — a
|
|
23
|
+
* deliberate close and an unexpected loss leave the session equally resumable, and the engine
|
|
24
|
+
* recovers from both. Establishing over a live session, or over an attempt already in flight, is
|
|
25
|
+
* a caller error; `disconnecting` is waited out rather than refused.
|
|
26
|
+
*/
|
|
27
|
+
{
|
|
28
|
+
type: 'connect';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resume the existing session: legal wherever establishing is, minus `new` (nothing to resume
|
|
32
|
+
* yet), plus `connected` — the peer connection can be severed while signalling stays up.
|
|
33
|
+
*/
|
|
34
|
+
| {
|
|
35
|
+
type: 'reconnect';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* An attempt established its transport. Carries the attempt it belongs to: an attempt that a
|
|
39
|
+
* newer one has already superseded must not declare the session live.
|
|
40
|
+
*/
|
|
41
|
+
| {
|
|
42
|
+
type: 'connectComplete';
|
|
43
|
+
attemptId: number;
|
|
44
|
+
} | {
|
|
45
|
+
type: 'connectFailed';
|
|
46
|
+
error?: unknown;
|
|
47
|
+
} | {
|
|
48
|
+
type: 'reconnectComplete';
|
|
49
|
+
attemptId: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A resume attempt ended. `recoverable` distinguishes "another resume may follow" (→ `offline`)
|
|
53
|
+
* from a terminal outcome such as a server leave or an expired token (→ `closed`).
|
|
54
|
+
*/
|
|
55
|
+
| {
|
|
56
|
+
type: 'reconnectFailed';
|
|
57
|
+
error?: unknown;
|
|
58
|
+
recoverable: boolean;
|
|
59
|
+
}
|
|
60
|
+
/** The transport identified by `attemptId` was lost (unexpected ws close, ping timeout). */
|
|
61
|
+
| {
|
|
62
|
+
type: 'transportFailed';
|
|
63
|
+
attemptId: number;
|
|
64
|
+
reason: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: 'close';
|
|
67
|
+
reason: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'closeComplete';
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Lifecycle model of the signal connection.
|
|
73
|
+
*
|
|
74
|
+
* The machine deliberately does not own connection attempts: `SignalClient` performs the
|
|
75
|
+
* asynchronous work and reports the outcome. It also does not decide *whether* to reconnect —
|
|
76
|
+
* that policy (backoff, resume vs. full reconnect, region failover, giving up) belongs to
|
|
77
|
+
* `RTCEngine`, so transport loss lands in `offline` rather than starting a reconnect on its own.
|
|
78
|
+
*
|
|
79
|
+
* Each client gets its own instance: the context is mutable and per-connection.
|
|
80
|
+
*/
|
|
81
|
+
export declare function createSignalMachine(initialState?: SignalLifecycleState): import("machina").Fsm<SignalMachineContext, "new" | "connecting" | "connected" | "offline" | "reconnecting" | "disconnecting" | "closed", "connect" | "reconnect" | "connectComplete" | "connectFailed" | "reconnectComplete" | "reconnectFailed" | "transportFailed" | "close" | "closeComplete", never>;
|
|
82
|
+
export type SignalMachine = ReturnType<typeof createSignalMachine>;
|
|
83
|
+
/** All lifecycle states, derived from the machine itself so the two cannot drift. */
|
|
84
|
+
export declare const signalLifecycleStates: Array<SignalLifecycleState>;
|
|
85
|
+
//# sourceMappingURL=SignalClientStateMachine.d.ts.map
|
package/dist/ts4.2/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ import type { PublicationEventCallbacks } from './room/track/TrackPublication';
|
|
|
29
29
|
import { TrackPublication } from './room/track/TrackPublication';
|
|
30
30
|
import type { LiveKitReactNativeInfo, TextStreamInfo } from './room/types';
|
|
31
31
|
import type { AudioAnalyserOptions } from './room/utils';
|
|
32
|
-
import { compareVersions, createAudioAnalyser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, isAudioCodec, isAudioTrack, isBrowserSupported, isLocalParticipant, isLocalTrack, isRemoteParticipant, isRemoteTrack, isVideoCodec, isVideoTrack, supportsAV1, supportsAdaptiveStream, supportsAudioOutputSelection, supportsDynacast, supportsVP9 } from './room/utils';
|
|
32
|
+
import { compareVersions, createAudioAnalyser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, isAudioCodec, isAudioTrack, isBrowserSupported, isLocalParticipant, isLocalTrack, isRemoteParticipant, isRemoteTrack, isSVCCodec, isVideoCodec, isVideoTrack, supportsAV1, supportsAdaptiveStream, supportsAudioOutputSelection, supportsDynacast, supportsH265, supportsVP9 } from './room/utils';
|
|
33
33
|
import { getBrowser } from './utils/browserParser';
|
|
34
34
|
export type { RpcInvocationData, PerformRpcParams } from './room/rpc';
|
|
35
35
|
export { RpcError } from './room/rpc';
|
|
@@ -63,8 +63,9 @@ export type { DataPublishOptions, SimulationScenario, TranscriptionSegment, Chat
|
|
|
63
63
|
export * from './version';
|
|
64
64
|
export {
|
|
65
65
|
/** @internal */
|
|
66
|
-
attributes, ConnectionQuality, ConnectionState, CriticalTimers, DataPacket_Kind, Encryption_Type, DefaultReconnectPolicy, DisconnectReason, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, Participant, RemoteAudioTrack, RemoteParticipant, ParticipantKind, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, SubscriptionError, TrackPublication, TrackType, compareVersions, createAudioAnalyser, getBrowser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, isBrowserSupported, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsAudioOutputSelection, supportsDynacast, supportsVP9, Mutex, isAudioCodec, isAudioTrack, isLocalTrack, isRemoteTrack, isVideoCodec, isVideoTrack, isLocalParticipant, isRemoteParticipant, LocalDataTrack, RemoteDataTrack, };
|
|
66
|
+
attributes, ConnectionQuality, ConnectionState, CriticalTimers, DataPacket_Kind, Encryption_Type, DefaultReconnectPolicy, DisconnectReason, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, LoggerNames, Participant, RemoteAudioTrack, RemoteParticipant, ParticipantKind, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, SubscriptionError, TrackPublication, TrackType, compareVersions, createAudioAnalyser, getBrowser, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, getLogger, isBrowserSupported, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsAudioOutputSelection, supportsDynacast, supportsH265, supportsVP9, Mutex, isAudioCodec, isAudioTrack, isLocalTrack, isRemoteTrack, isSVCCodec, isVideoCodec, isVideoTrack, isLocalParticipant, isRemoteParticipant, LocalDataTrack, RemoteDataTrack, };
|
|
67
67
|
export type { AudioAnalyserOptions, ElementInfo, LiveKitReactNativeInfo, TextStreamInfo, ParticipantTrackPermission, AudioReceiverStats, AudioSenderStats, VideoReceiverStats, VideoSenderStats, ReconnectContext, ReconnectPolicy, RoomEventCallbacks, ParticipantEventCallbacks, PublicationEventCallbacks, DataTrackSubscribeOptions, RemoteDataTrackPipelineOptions, };
|
|
68
|
+
export type { DataTrackFrame } from './room/data-track/frame';
|
|
68
69
|
export type { DataTrackPacketHeader } from './room/data-track/packet';
|
|
69
70
|
export { DataTrackPacket } from './room/data-track/packet';
|
|
70
71
|
export type { DataTrackExtensions, DataTrackUserTimestampExtension, DataTrackE2eeExtension } from './room/data-track/packet/extensions';
|
package/dist/ts4.2/logger.d.ts
CHANGED
|
@@ -21,7 +21,8 @@ export declare enum LoggerNames {
|
|
|
21
21
|
E2EE = "lk-e2ee",
|
|
22
22
|
DataTracks = "livekit-data-tracks",
|
|
23
23
|
Region = "livekit-region",
|
|
24
|
-
ICE = "livekit-ice"
|
|
24
|
+
ICE = "livekit-ice",
|
|
25
|
+
Stats = "livekit-stats"
|
|
25
26
|
}
|
|
26
27
|
type LogLevelString = keyof typeof LogLevel;
|
|
27
28
|
export type StructuredLogger = log.Logger & {
|
package/dist/ts4.2/options.d.ts
CHANGED
|
@@ -96,6 +96,28 @@ export interface InternalRoomOptions {
|
|
|
96
96
|
* @default true
|
|
97
97
|
*/
|
|
98
98
|
singlePeerConnection: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Options controlling data stream behavior for this room.
|
|
101
|
+
*/
|
|
102
|
+
dataStream?: RoomDataStreamOptions;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Options controlling data stream behavior for a room.
|
|
106
|
+
*/
|
|
107
|
+
export interface RoomDataStreamOptions {
|
|
108
|
+
/**
|
|
109
|
+
* Maximum size, in bytes, of the payload this client accepts from a single incoming data stream.
|
|
110
|
+
*
|
|
111
|
+
* A compressed stream can inflate to an arbitrarily large payload, so the decompressed output is
|
|
112
|
+
* bounded rather than trusting the size declared on the wire. An incoming stream that exceeds the
|
|
113
|
+
* cap fails with a `DataStreamErrorReason.PayloadTooLarge` error on the next read instead of
|
|
114
|
+
* buffering without bound.
|
|
115
|
+
*
|
|
116
|
+
* This is enforced on the receiving side only: raising it on a sender has no effect.
|
|
117
|
+
*
|
|
118
|
+
* @default 5_000_000_000 (5 GB)
|
|
119
|
+
*/
|
|
120
|
+
maxPayloadByteLength?: number;
|
|
99
121
|
}
|
|
100
122
|
/**
|
|
101
123
|
* Options for when creating a new room
|
|
@@ -91,7 +91,8 @@ export default class PCTransport extends PCTransport_base {
|
|
|
91
91
|
getSenders(): RTCRtpSender[];
|
|
92
92
|
getLocalDescription(): RTCSessionDescription | null | undefined;
|
|
93
93
|
getRemoteDescription(): RTCSessionDescription | null;
|
|
94
|
-
|
|
94
|
+
/** stats of the underlying connection, `undefined` when there is none */
|
|
95
|
+
getStats(): Promise<RTCStatsReport> | undefined;
|
|
95
96
|
getMaxMessageSize(): number | undefined;
|
|
96
97
|
getConnectedAddress(): Promise<string | undefined>;
|
|
97
98
|
close: () => void;
|
|
@@ -98,10 +98,15 @@ export default class RTCEngine extends RTCEngine_base {
|
|
|
98
98
|
joinResponse: JoinResponse;
|
|
99
99
|
serverInfo: Partial<ServerInfo>;
|
|
100
100
|
}>;
|
|
101
|
-
|
|
101
|
+
/**
|
|
102
|
+
* @param reason why the session is ending, recorded by the signal lifecycle. Worth passing
|
|
103
|
+
* wherever the caller knows more than "someone called close" — the server's leave reason, or
|
|
104
|
+
* having given up on reconnecting.
|
|
105
|
+
*/
|
|
106
|
+
close(reason?: string): Promise<void>;
|
|
102
107
|
cleanupPeerConnections(): Promise<void>;
|
|
103
108
|
cleanupLossyDataStats(): void;
|
|
104
|
-
cleanupClient(): Promise<void>;
|
|
109
|
+
cleanupClient(reason?: string): Promise<void>;
|
|
105
110
|
addTrack(req: AddTrackRequest): Promise<TrackInfo>;
|
|
106
111
|
/**
|
|
107
112
|
* Removes sender from PeerConnection, returning true if it was removed successfully
|
|
@@ -72,10 +72,12 @@ declare class Room extends Room_base {
|
|
|
72
72
|
private frameMetadataManager;
|
|
73
73
|
private e2eeStateMutex;
|
|
74
74
|
private connectionReconcileInterval?;
|
|
75
|
+
private statsLogInterval?;
|
|
75
76
|
private regionUrlProvider?;
|
|
76
77
|
private regionUrl?;
|
|
77
78
|
private isVideoPlaybackBlocked;
|
|
78
79
|
private log;
|
|
80
|
+
private statsLog;
|
|
79
81
|
private bufferedEvents;
|
|
80
82
|
private isResuming;
|
|
81
83
|
private pendingTrackAddedCallbacks;
|
|
@@ -276,6 +278,11 @@ declare class Room extends Room_base {
|
|
|
276
278
|
private getRemoteParticipantCapabilities;
|
|
277
279
|
private getAllRemoteParticipantIdentities;
|
|
278
280
|
private registerRpcDataStreamHandler;
|
|
281
|
+
private setStatsLogging;
|
|
282
|
+
/**
|
|
283
|
+
* Dumps stats of both peer connections.
|
|
284
|
+
*/
|
|
285
|
+
private logWebRTCStats;
|
|
279
286
|
private registerConnectionReconcile;
|
|
280
287
|
private clearConnectionReconcile;
|
|
281
288
|
private setAndEmitConnectionState;
|
|
@@ -313,7 +320,7 @@ export type RoomEventCallbacks = {
|
|
|
313
320
|
moved: (name: string) => void;
|
|
314
321
|
mediaDevicesChanged: () => void;
|
|
315
322
|
participantConnected: (participant: RemoteParticipant) => void;
|
|
316
|
-
participantDisconnected: (participant: RemoteParticipant) => void;
|
|
323
|
+
participantDisconnected: (participant: RemoteParticipant, disconnectReason?: DisconnectReason) => void;
|
|
317
324
|
trackPublished: (publication: RemoteTrackPublication, participant: RemoteParticipant) => void;
|
|
318
325
|
trackSubscribed: (track: RemoteTrack, publication: RemoteTrackPublication, participant: RemoteParticipant) => void;
|
|
319
326
|
trackSubscriptionFailed: (trackSid: string, participant: RemoteParticipant, reason?: SubscriptionError) => void;
|
|
@@ -70,7 +70,7 @@ export declare enum RoomEvent {
|
|
|
70
70
|
* When a [[RemoteParticipant]] leaves *after* the local
|
|
71
71
|
* participant has joined.
|
|
72
72
|
*
|
|
73
|
-
* args: ([[RemoteParticipant]])
|
|
73
|
+
* args: ([[RemoteParticipant]], [[DisconnectReason]] | undefined)
|
|
74
74
|
*/
|
|
75
75
|
ParticipantDisconnected = "participantDisconnected",
|
|
76
76
|
/**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** one summarised stats entry; keys without a value are dropped */
|
|
2
|
+
type Summary = Record<string, unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* Picks the interesting fields out of a `getStats()` report and groups them by
|
|
5
|
+
* RTP stream, so a stats dump can be read without unfolding the raw report.
|
|
6
|
+
*/
|
|
7
|
+
export declare function summarizeStatsReport(report: RTCStatsReport): {
|
|
8
|
+
connection: Summary | undefined;
|
|
9
|
+
outbound: Summary[] | undefined;
|
|
10
|
+
inbound: Summary[] | undefined;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=statsSummary.d.ts.map
|
|
@@ -42,6 +42,7 @@ export declare abstract class Track<TrackKind extends Track.Kind = Track.Kind> e
|
|
|
42
42
|
protected timeSyncHandle: number | undefined;
|
|
43
43
|
protected _currentBitrate: number;
|
|
44
44
|
protected monitorInterval?: ReturnType<typeof setInterval>;
|
|
45
|
+
private finalStatsLogged;
|
|
45
46
|
protected log: StructuredLogger;
|
|
46
47
|
protected constructor(mediaTrack: MediaStreamTrack, kind: TrackKind, loggerOptions?: LoggerOptions);
|
|
47
48
|
protected get logContext(): {
|
|
@@ -78,7 +79,16 @@ export declare abstract class Track<TrackKind extends Track.Kind = Track.Kind> e
|
|
|
78
79
|
protected enable(): void;
|
|
79
80
|
protected disable(): void;
|
|
80
81
|
abstract startMonitor(signalClient?: SignalClient): void;
|
|
82
|
+
/**
|
|
83
|
+
* Raw stats of the sender or receiver this track is attached to.
|
|
84
|
+
*/
|
|
85
|
+
abstract getRTCStatsReport(): Promise<RTCStatsReport | undefined>;
|
|
81
86
|
stopMonitor(): void;
|
|
87
|
+
/**
|
|
88
|
+
* Dumps the raw stats of the track as it ends, once: a track that stops
|
|
89
|
+
* between two of the room's stats dumps is gone by the time the next one runs.
|
|
90
|
+
*/
|
|
91
|
+
private logFinalStats;
|
|
82
92
|
/** @internal */
|
|
83
93
|
updateLoggerOptions(loggerOptions: LoggerOptions): void;
|
|
84
94
|
private recycleElement;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in registry that lets a development tool observe the state machines driving the connection
|
|
3
|
+
* layer.
|
|
4
|
+
*
|
|
5
|
+
* The machines are private to the objects that own them and, more importantly, do not outlive them:
|
|
6
|
+
* a full reconnect replaces the whole engine along with its `SignalClient`, so anything watching a
|
|
7
|
+
* single machine reference goes blind exactly when the interesting part starts. Machines therefore
|
|
8
|
+
* announce themselves here as they are constructed, and a subscriber sees the whole succession.
|
|
9
|
+
*
|
|
10
|
+
* Nothing is recorded until {@link enableMachineInspector} is called, which no shipping code does —
|
|
11
|
+
* with the registry off, announcing is a comparison and a return.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The slice of machina's `Fsm` surface an inspector needs. Structural rather than machina's own
|
|
15
|
+
* type so that any machine satisfies it regardless of its state and input unions.
|
|
16
|
+
*/
|
|
17
|
+
export interface InspectableMachine {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly initialState: string;
|
|
20
|
+
readonly states: Record<string, Record<string, unknown>>;
|
|
21
|
+
readonly context?: unknown;
|
|
22
|
+
currentState(): string;
|
|
23
|
+
canHandle(input: string): boolean;
|
|
24
|
+
on(eventName: string, callback: (data: any) => void): {
|
|
25
|
+
off(): void;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface MachineAnnouncement {
|
|
29
|
+
/** What the machine drives, e.g. `signal`. Not unique: each new `SignalClient` announces one. */
|
|
30
|
+
label: string;
|
|
31
|
+
/** How many machines have been announced before this one, so successive instances are tellable apart. */
|
|
32
|
+
seq: number;
|
|
33
|
+
/**
|
|
34
|
+
* When the machine was constructed. Carried on the announcement because subscribers receive the
|
|
35
|
+
* recorded ones on subscribe, and stamping those at replay time would date them all to whenever
|
|
36
|
+
* the tool happened to open.
|
|
37
|
+
*/
|
|
38
|
+
at: number;
|
|
39
|
+
machine: InspectableMachine;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Starts recording machine announcements. Call before the machines of interest are constructed —
|
|
43
|
+
* for the signal machine that means before the `Room` is created.
|
|
44
|
+
*/
|
|
45
|
+
export declare function enableMachineInspector(): void;
|
|
46
|
+
export declare function isMachineInspectorEnabled(): boolean;
|
|
47
|
+
/** Announces a machine to whatever is watching. A no-op unless the inspector was enabled. */
|
|
48
|
+
export declare function announceMachine(label: string, machine: InspectableMachine): void;
|
|
49
|
+
/**
|
|
50
|
+
* Subscribes to machine announcements, replaying the ones already recorded so that a panel opened
|
|
51
|
+
* after connecting still sees the machine currently in charge. Returns an unsubscribe function.
|
|
52
|
+
*/
|
|
53
|
+
export declare function onMachineAnnounced(callback: (announcement: MachineAnnouncement) => void): () => void;
|
|
54
|
+
//# sourceMappingURL=machineInspector.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livekit-client",
|
|
3
|
-
"version": "2.22.
|
|
3
|
+
"version": "2.22.1",
|
|
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",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"events": "^3.3.0",
|
|
55
55
|
"jose": "^6.1.0",
|
|
56
56
|
"loglevel": "^1.9.2",
|
|
57
|
+
"machina": "^7.0.0",
|
|
57
58
|
"sdp-transform": "^2.15.0",
|
|
58
59
|
"tslib": "2.8.1",
|
|
59
60
|
"typed-emitter": "^2.1.0",
|
|
@@ -92,12 +93,16 @@
|
|
|
92
93
|
"eslint-config-prettier": "10.1.8",
|
|
93
94
|
"eslint-plugin-compat": "^6.0.2",
|
|
94
95
|
"eslint-plugin-import-x": "^4.16.1",
|
|
96
|
+
"eslint-plugin-machina": "^0.1.4",
|
|
95
97
|
"eslint-plugin-prettier": "^5.5.4",
|
|
96
98
|
"gh-pages": "6.3.0",
|
|
97
99
|
"glob": "^13.0.6",
|
|
98
100
|
"happy-dom": "^20.0.0",
|
|
99
101
|
"jsdom": "^26.1.0",
|
|
100
102
|
"livekit-server-sdk": "^2.17.0",
|
|
103
|
+
"machina-inspect": "^4.0.0",
|
|
104
|
+
"machina-test": "^3.0.0",
|
|
105
|
+
"mermaid": "^11.16.1",
|
|
101
106
|
"playwright": "^1.61.1",
|
|
102
107
|
"prettier": "^3.4.2",
|
|
103
108
|
"publint": "^0.3.21",
|
|
@@ -121,6 +126,7 @@
|
|
|
121
126
|
"build-docs": "typedoc && mkdir -p docs/assets/github && cp .github/*.png docs/assets/github/ && find docs -name '*.html' -type f -exec sed -i.bak 's|=\"/.github/|=\"assets/github/|g' {} + && find docs -name '*.bak' -delete",
|
|
122
127
|
"proto": "protoc --es_out src/proto --es_opt target=ts -I./protocol ./protocol/livekit_rtc.proto ./protocol/livekit_models.proto",
|
|
123
128
|
"examples:demo": "vite examples/demo -c vite.config.mjs",
|
|
129
|
+
"examples:machine": "vite examples/state-machine -c vite.config.mjs",
|
|
124
130
|
"dev": "pnpm examples:demo",
|
|
125
131
|
"lint": "eslint src",
|
|
126
132
|
"test": "vitest run src",
|