livekit-client 1.15.6 → 1.15.8
Sign up to get free protection for your applications and to get access to all the features.
- 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 +14 -1
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +556 -348
- 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/api/SignalClient.d.ts +5 -1
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/logger.d.ts +19 -3
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/options.d.ts +1 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +5 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts +5 -1
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +8 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +2 -0
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +9 -1
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts +2 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/publishUtils.d.ts +2 -1
- package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
- package/dist/src/room/timers.d.ts +5 -4
- package/dist/src/room/timers.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts +2 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +2 -1
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrackPublication.d.ts +2 -1
- package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +2 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteAudioTrack.d.ts +2 -1
- package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrack.d.ts +2 -1
- package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts +2 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts +2 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +10 -1
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/TrackPublication.d.ts +7 -1
- package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/create.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +8 -3
- package/dist/src/room/track/options.d.ts.map +1 -1
- package/dist/src/room/track/utils.d.ts +1 -0
- package/dist/src/room/track/utils.d.ts.map +1 -1
- package/dist/src/room/types.d.ts +4 -0
- package/dist/src/room/types.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/ts4.2/src/api/SignalClient.d.ts +5 -1
- package/dist/ts4.2/src/index.d.ts +2 -2
- package/dist/ts4.2/src/logger.d.ts +19 -3
- package/dist/ts4.2/src/options.d.ts +1 -0
- package/dist/ts4.2/src/room/PCTransport.d.ts +5 -1
- package/dist/ts4.2/src/room/PCTransportManager.d.ts +5 -1
- package/dist/ts4.2/src/room/RTCEngine.d.ts +8 -0
- package/dist/ts4.2/src/room/Room.d.ts +2 -0
- package/dist/ts4.2/src/room/participant/Participant.d.ts +9 -1
- package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +2 -1
- package/dist/ts4.2/src/room/participant/publishUtils.d.ts +2 -1
- package/dist/ts4.2/src/room/timers.d.ts +5 -4
- package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/LocalTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +2 -1
- package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +2 -1
- package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +2 -1
- package/dist/ts4.2/src/room/track/Track.d.ts +10 -1
- package/dist/ts4.2/src/room/track/TrackPublication.d.ts +7 -1
- package/dist/ts4.2/src/room/track/options.d.ts +8 -3
- package/dist/ts4.2/src/room/track/utils.d.ts +1 -0
- package/dist/ts4.2/src/room/types.d.ts +4 -0
- package/dist/ts4.2/src/room/utils.d.ts +1 -0
- package/package.json +2 -2
- package/src/api/SignalClient.ts +43 -21
- package/src/index.ts +2 -1
- package/src/logger.ts +32 -8
- package/src/options.ts +2 -0
- package/src/room/PCTransport.ts +29 -8
- package/src/room/PCTransportManager.ts +29 -9
- package/src/room/RTCEngine.ts +71 -34
- package/src/room/Room.ts +91 -60
- package/src/room/participant/LocalParticipant.ts +165 -47
- package/src/room/participant/Participant.ts +26 -3
- package/src/room/participant/RemoteParticipant.ts +23 -15
- package/src/room/participant/publishUtils.test.ts +2 -2
- package/src/room/participant/publishUtils.ts +7 -4
- package/src/room/track/LocalAudioTrack.ts +8 -7
- package/src/room/track/LocalTrack.ts +23 -19
- package/src/room/track/LocalTrackPublication.ts +3 -2
- package/src/room/track/LocalVideoTrack.ts +31 -13
- package/src/room/track/RemoteAudioTrack.ts +4 -3
- package/src/room/track/RemoteTrack.ts +4 -1
- package/src/room/track/RemoteTrackPublication.ts +21 -13
- package/src/room/track/RemoteVideoTrack.ts +5 -4
- package/src/room/track/Track.ts +32 -2
- package/src/room/track/TrackPublication.ts +18 -3
- package/src/room/track/create.ts +4 -3
- package/src/room/track/options.ts +12 -5
- package/src/room/track/utils.ts +23 -1
- package/src/room/types.ts +5 -0
- package/src/room/utils.ts +5 -0
@@ -2,6 +2,7 @@ import type { SignalClient } from '../../api/SignalClient';
|
|
2
2
|
import { VideoLayer, VideoQuality } from '../../proto/livekit_models_pb';
|
3
3
|
import { SubscribedCodec, SubscribedQuality } from '../../proto/livekit_rtc_pb';
|
4
4
|
import type { VideoSenderStats } from '../stats';
|
5
|
+
import type { LoggerOptions } from '../types';
|
5
6
|
import LocalTrack from './LocalTrack';
|
6
7
|
import { Track } from './Track';
|
7
8
|
import type { VideoCaptureOptions, VideoCodec } from './options';
|
@@ -26,7 +27,7 @@ export default class LocalVideoTrack extends LocalTrack {
|
|
26
27
|
* @param constraints MediaTrackConstraints that are being used when restarting or reacquiring tracks
|
27
28
|
* @param userProvidedTrack Signals to the SDK whether or not the mediaTrack should be managed (i.e. released and reacquired) internally by the SDK
|
28
29
|
*/
|
29
|
-
constructor(mediaTrack: MediaStreamTrack, constraints?: MediaTrackConstraints, userProvidedTrack?: boolean);
|
30
|
+
constructor(mediaTrack: MediaStreamTrack, constraints?: MediaTrackConstraints, userProvidedTrack?: boolean, loggerOptions?: LoggerOptions);
|
30
31
|
get isSimulcast(): boolean;
|
31
32
|
startMonitor(signalClient: SignalClient): void;
|
32
33
|
stop(): void;
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import type { AudioReceiverStats } from '../stats';
|
2
|
+
import type { LoggerOptions } from '../types';
|
2
3
|
import RemoteTrack from './RemoteTrack';
|
3
4
|
import type { AudioOutputOptions } from './options';
|
4
5
|
export default class RemoteAudioTrack extends RemoteTrack {
|
@@ -9,7 +10,7 @@ export default class RemoteAudioTrack extends RemoteTrack {
|
|
9
10
|
private sourceNode?;
|
10
11
|
private webAudioPluginNodes;
|
11
12
|
private sinkId?;
|
12
|
-
constructor(mediaTrack: MediaStreamTrack, sid: string, receiver?: RTCRtpReceiver, audioContext?: AudioContext, audioOutput?: AudioOutputOptions);
|
13
|
+
constructor(mediaTrack: MediaStreamTrack, sid: string, receiver?: RTCRtpReceiver, audioContext?: AudioContext, audioOutput?: AudioOutputOptions, loggerOptions?: LoggerOptions);
|
13
14
|
/**
|
14
15
|
* sets the volume for all attached audio elements
|
15
16
|
*/
|
@@ -1,8 +1,9 @@
|
|
1
|
+
import type { LoggerOptions } from '../types';
|
1
2
|
import { Track } from './Track';
|
2
3
|
export default abstract class RemoteTrack extends Track {
|
3
4
|
/** @internal */
|
4
5
|
receiver?: RTCRtpReceiver;
|
5
|
-
constructor(mediaTrack: MediaStreamTrack, sid: string, kind: Track.Kind, receiver?: RTCRtpReceiver);
|
6
|
+
constructor(mediaTrack: MediaStreamTrack, sid: string, kind: Track.Kind, receiver?: RTCRtpReceiver, loggerOptions?: LoggerOptions);
|
6
7
|
/** @internal */
|
7
8
|
setMuted(muted: boolean): void;
|
8
9
|
/** @internal */
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { SubscriptionError, TrackInfo, VideoQuality } from '../../proto/livekit_models_pb';
|
2
|
+
import type { LoggerOptions } from '../types';
|
2
3
|
import type RemoteTrack from './RemoteTrack';
|
3
4
|
import { Track } from './Track';
|
4
5
|
import { TrackPublication } from './TrackPublication';
|
@@ -12,7 +13,7 @@ export default class RemoteTrackPublication extends TrackPublication {
|
|
12
13
|
protected videoDimensions?: Track.Dimensions;
|
13
14
|
protected fps?: number;
|
14
15
|
protected subscriptionError?: SubscriptionError;
|
15
|
-
constructor(kind: Track.Kind, ti: TrackInfo, autoSubscribe: boolean | undefined);
|
16
|
+
constructor(kind: Track.Kind, ti: TrackInfo, autoSubscribe: boolean | undefined, loggerOptions?: LoggerOptions);
|
16
17
|
/**
|
17
18
|
* Subscribe or unsubscribe to this remote track
|
18
19
|
* @param subscribed true to subscribe to a track, false to unsubscribe
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import type { LoggerOptions } from '../types';
|
1
2
|
import RemoteTrack from './RemoteTrack';
|
2
3
|
import type { AdaptiveStreamSettings } from './types';
|
3
4
|
export default class RemoteVideoTrack extends RemoteTrack {
|
@@ -6,7 +7,7 @@ export default class RemoteVideoTrack extends RemoteTrack {
|
|
6
7
|
private adaptiveStreamSettings?;
|
7
8
|
private lastVisible?;
|
8
9
|
private lastDimensions?;
|
9
|
-
constructor(mediaTrack: MediaStreamTrack, sid: string, receiver?: RTCRtpReceiver, adaptiveStreamSettings?: AdaptiveStreamSettings);
|
10
|
+
constructor(mediaTrack: MediaStreamTrack, sid: string, receiver?: RTCRtpReceiver, adaptiveStreamSettings?: AdaptiveStreamSettings, loggerOptions?: LoggerOptions);
|
10
11
|
get isAdaptiveStream(): boolean;
|
11
12
|
/**
|
12
13
|
* Note: When using adaptiveStream, you need to use remoteVideoTrack.attach() to add the track to a HTMLVideoElement, otherwise your video tracks might never start
|
@@ -1,7 +1,9 @@
|
|
1
1
|
import type TypedEventEmitter from 'typed-emitter';
|
2
2
|
import type { SignalClient } from '../../api/SignalClient';
|
3
|
+
import { StructuredLogger } from '../../logger';
|
3
4
|
import { TrackSource, TrackType } from '../../proto/livekit_models_pb';
|
4
5
|
import { StreamState as ProtoStreamState } from '../../proto/livekit_rtc_pb';
|
6
|
+
import type { LoggerOptions } from '../types';
|
5
7
|
declare const Track_base: new () => TypedEventEmitter<TrackEventCallbacks>;
|
6
8
|
export declare abstract class Track extends Track_base {
|
7
9
|
kind: Track.Kind;
|
@@ -25,9 +27,14 @@ export declare abstract class Track extends Track_base {
|
|
25
27
|
protected _mediaStreamID: string;
|
26
28
|
protected isInBackground: boolean;
|
27
29
|
private backgroundTimeout;
|
30
|
+
private loggerContextCb;
|
28
31
|
protected _currentBitrate: number;
|
29
32
|
protected monitorInterval?: ReturnType<typeof setInterval>;
|
30
|
-
protected
|
33
|
+
protected log: StructuredLogger;
|
34
|
+
protected constructor(mediaTrack: MediaStreamTrack, kind: Track.Kind, loggerOptions?: LoggerOptions);
|
35
|
+
protected get logContext(): {
|
36
|
+
[x: string]: unknown;
|
37
|
+
};
|
31
38
|
/** current receive bits per second */
|
32
39
|
get currentBitrate(): number;
|
33
40
|
get mediaStreamTrack(): MediaStreamTrack;
|
@@ -59,6 +66,8 @@ export declare abstract class Track extends Track_base {
|
|
59
66
|
protected disable(): void;
|
60
67
|
abstract startMonitor(signalClient?: SignalClient): void;
|
61
68
|
stopMonitor(): void;
|
69
|
+
/** @internal */
|
70
|
+
updateLoggerOptions(loggerOptions: LoggerOptions): void;
|
62
71
|
private recycleElement;
|
63
72
|
protected appVisibilityChangedListener: () => void;
|
64
73
|
protected handleAppVisibilityChanged(): Promise<void>;
|
@@ -2,6 +2,7 @@ import type TypedEventEmitter from 'typed-emitter';
|
|
2
2
|
import { Encryption_Type } from '../../proto/livekit_models_pb';
|
3
3
|
import type { SubscriptionError, TrackInfo } from '../../proto/livekit_models_pb';
|
4
4
|
import type { UpdateSubscription, UpdateTrackSettings } from '../../proto/livekit_rtc_pb';
|
5
|
+
import type { LoggerOptions } from '../types';
|
5
6
|
import LocalAudioTrack from './LocalAudioTrack';
|
6
7
|
import LocalVideoTrack from './LocalVideoTrack';
|
7
8
|
import RemoteAudioTrack from './RemoteAudioTrack';
|
@@ -25,9 +26,14 @@ export declare class TrackPublication extends TrackPublication_base {
|
|
25
26
|
trackInfo?: TrackInfo;
|
26
27
|
protected metadataMuted: boolean;
|
27
28
|
protected encryption: Encryption_Type;
|
28
|
-
|
29
|
+
protected log: import("../../logger").StructuredLogger;
|
30
|
+
private loggerContextCb?;
|
31
|
+
constructor(kind: Track.Kind, id: string, name: string, loggerOptions?: LoggerOptions);
|
29
32
|
/** @internal */
|
30
33
|
setTrack(track?: Track): void;
|
34
|
+
protected get logContext(): {
|
35
|
+
[x: string]: unknown;
|
36
|
+
};
|
31
37
|
get isMuted(): boolean;
|
32
38
|
get isEnabled(): boolean;
|
33
39
|
get isSubscribed(): boolean;
|
@@ -149,9 +149,10 @@ export interface ScreenShareCaptureOptions {
|
|
149
149
|
displaySurface?: 'window' | 'browser' | 'monitor';
|
150
150
|
};
|
151
151
|
/**
|
152
|
-
* capture resolution, defaults to
|
153
|
-
*
|
154
|
-
* capture.
|
152
|
+
* capture resolution, defaults to 1080 for all browsers other than Safari
|
153
|
+
* On Safari 17, default resolution is not capped, due to a bug, specifying
|
154
|
+
* any resolution at all would lead to a low-resolution capture.
|
155
|
+
* https://bugs.webkit.org/show_bug.cgi?id=263015
|
155
156
|
*/
|
156
157
|
resolution?: VideoResolution;
|
157
158
|
/** a CaptureController object instance containing methods that can be used to further manipulate the capture session if included. */
|
@@ -162,6 +163,8 @@ export interface ScreenShareCaptureOptions {
|
|
162
163
|
surfaceSwitching?: 'include' | 'exclude';
|
163
164
|
/** specifies whether the browser should include the system audio among the possible audio sources offered to the user */
|
164
165
|
systemAudio?: 'include' | 'exclude';
|
166
|
+
/** specify the type of content, see: https://www.w3.org/TR/mst-content-hint/#video-content-hints */
|
167
|
+
contentHint?: 'detail' | 'text' | 'motion';
|
165
168
|
/**
|
166
169
|
* Experimental option to control whether the audio playing in a tab will continue to be played out of a user's
|
167
170
|
* local speakers when the tab is captured.
|
@@ -288,11 +291,13 @@ export declare const VideoPresets43: {
|
|
288
291
|
};
|
289
292
|
export declare const ScreenSharePresets: {
|
290
293
|
readonly h360fps3: VideoPreset;
|
294
|
+
readonly h360fps15: VideoPreset;
|
291
295
|
readonly h720fps5: VideoPreset;
|
292
296
|
readonly h720fps15: VideoPreset;
|
293
297
|
readonly h720fps30: VideoPreset;
|
294
298
|
readonly h1080fps15: VideoPreset;
|
295
299
|
readonly h1080fps30: VideoPreset;
|
300
|
+
readonly original: VideoPreset;
|
296
301
|
};
|
297
302
|
export {};
|
298
303
|
//# sourceMappingURL=options.d.ts.map
|
@@ -28,4 +28,5 @@ export declare function sourceToKind(source: Track.Source): MediaDeviceKind | un
|
|
28
28
|
export declare function screenCaptureToDisplayMediaStreamOptions(options: ScreenShareCaptureOptions): DisplayMediaStreamOptions;
|
29
29
|
export declare function mimeTypeToVideoCodecString(mimeType: string): "vp8" | "h264" | "vp9" | "av1";
|
30
30
|
export declare function getTrackPublicationInfo<T extends TrackPublication>(tracks: T[]): TrackPublishedResponse[];
|
31
|
+
export declare function getLogContextFromTrack(track: Track | TrackPublication): Record<string, unknown>;
|
31
32
|
//# sourceMappingURL=utils.d.ts.map
|
@@ -23,4 +23,8 @@ export type LiveKitReactNativeInfo = {
|
|
23
23
|
devicePixelRatio: number;
|
24
24
|
};
|
25
25
|
export type SimulationScenario = 'signal-reconnect' | 'speaker' | 'node-failure' | 'server-leave' | 'migration' | 'resume-reconnect' | 'force-tcp' | 'force-tls' | 'full-reconnect' | 'subscriber-bandwidth';
|
26
|
+
export type LoggerOptions = {
|
27
|
+
loggerName?: string;
|
28
|
+
loggerContextCb?: () => Record<string, unknown>;
|
29
|
+
};
|
26
30
|
//# sourceMappingURL=types.d.ts.map
|
@@ -20,6 +20,7 @@ export declare function isBrowserSupported(): boolean;
|
|
20
20
|
export declare function isFireFox(): boolean;
|
21
21
|
export declare function isChromiumBased(): boolean;
|
22
22
|
export declare function isSafari(): boolean;
|
23
|
+
export declare function isSafari17(): boolean;
|
23
24
|
export declare function isMobile(): boolean;
|
24
25
|
export declare function isWeb(): boolean;
|
25
26
|
export declare function isReactNative(): boolean;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "livekit-client",
|
3
|
-
"version": "1.15.
|
3
|
+
"version": "1.15.8",
|
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",
|
@@ -89,7 +89,7 @@
|
|
89
89
|
"build:watch": "rollup --watch --config rollup.config.js",
|
90
90
|
"build-docs": "typedoc",
|
91
91
|
"proto": "protoc --es_out src/proto --es_opt target=ts -I./protocol ./protocol/livekit_rtc.proto ./protocol/livekit_models.proto",
|
92
|
-
"sample": "vite example -c vite.config.
|
92
|
+
"sample": "vite example -c vite.config.mjs",
|
93
93
|
"lint": "eslint src",
|
94
94
|
"test": "vitest run src",
|
95
95
|
"deploy": "gh-pages -d example/dist",
|
package/src/api/SignalClient.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { protoInt64 } from '@bufbuild/protobuf';
|
2
|
-
import log from '../logger';
|
2
|
+
import log, { LoggerNames, getLogger } from '../logger';
|
3
3
|
import {
|
4
4
|
ClientInfo,
|
5
5
|
DisconnectReason,
|
@@ -39,6 +39,7 @@ import {
|
|
39
39
|
} from '../proto/livekit_rtc_pb';
|
40
40
|
import { ConnectionError, ConnectionErrorReason } from '../room/errors';
|
41
41
|
import CriticalTimers from '../room/timers';
|
42
|
+
import type { LoggerOptions } from '../room/types';
|
42
43
|
import { Mutex, getClientInfo, isReactNative, sleep, toWebsocketUrl } from '../room/utils';
|
43
44
|
import { AsyncQueue } from '../utils/AsyncQueue';
|
44
45
|
|
@@ -172,7 +173,13 @@ export class SignalClient {
|
|
172
173
|
|
173
174
|
private connectionLock: Mutex;
|
174
175
|
|
175
|
-
|
176
|
+
private log = log;
|
177
|
+
|
178
|
+
private loggerContextCb?: LoggerOptions['loggerContextCb'];
|
179
|
+
|
180
|
+
constructor(useJSON: boolean = false, loggerOptions: LoggerOptions = {}) {
|
181
|
+
this.log = getLogger(loggerOptions.loggerName ?? LoggerNames.Signal);
|
182
|
+
this.loggerContextCb = loggerOptions.loggerContextCb;
|
176
183
|
this.useJSON = useJSON;
|
177
184
|
this.requestQueue = new AsyncQueue();
|
178
185
|
this.queuedRequests = [];
|
@@ -181,6 +188,10 @@ export class SignalClient {
|
|
181
188
|
this.state = SignalConnectionState.DISCONNECTED;
|
182
189
|
}
|
183
190
|
|
191
|
+
private get logContext() {
|
192
|
+
return this.loggerContextCb?.() ?? {};
|
193
|
+
}
|
194
|
+
|
184
195
|
async join(
|
185
196
|
url: string,
|
186
197
|
token: string,
|
@@ -202,7 +213,10 @@ export class SignalClient {
|
|
202
213
|
reason?: ReconnectReason,
|
203
214
|
): Promise<ReconnectResponse | void> {
|
204
215
|
if (!this.options) {
|
205
|
-
log.warn(
|
216
|
+
this.log.warn(
|
217
|
+
'attempted to reconnect without signal options being set, ignoring',
|
218
|
+
this.logContext,
|
219
|
+
);
|
206
220
|
return;
|
207
221
|
}
|
208
222
|
this.state = SignalConnectionState.RECONNECTING;
|
@@ -251,7 +265,7 @@ export class SignalClient {
|
|
251
265
|
abortHandler();
|
252
266
|
}
|
253
267
|
abortSignal?.addEventListener('abort', abortHandler);
|
254
|
-
log.debug(`connecting to ${url + params}
|
268
|
+
this.log.debug(`connecting to ${url + params}`, this.logContext);
|
255
269
|
if (this.ws) {
|
256
270
|
await this.close();
|
257
271
|
}
|
@@ -302,7 +316,10 @@ export class SignalClient {
|
|
302
316
|
} else if (ev.data instanceof ArrayBuffer) {
|
303
317
|
resp = SignalResponse.fromBinary(new Uint8Array(ev.data));
|
304
318
|
} else {
|
305
|
-
log.error(
|
319
|
+
this.log.error(
|
320
|
+
`could not decode websocket message: ${typeof ev.data}`,
|
321
|
+
this.logContext,
|
322
|
+
);
|
306
323
|
return;
|
307
324
|
}
|
308
325
|
|
@@ -316,7 +333,8 @@ export class SignalClient {
|
|
316
333
|
this.pingIntervalDuration = resp.message.value.pingInterval;
|
317
334
|
|
318
335
|
if (this.pingTimeoutDuration && this.pingTimeoutDuration > 0) {
|
319
|
-
log.debug('ping config', {
|
336
|
+
this.log.debug('ping config', {
|
337
|
+
...this.logContext,
|
320
338
|
timeout: this.pingTimeoutDuration,
|
321
339
|
interval: this.pingIntervalDuration,
|
322
340
|
});
|
@@ -354,7 +372,7 @@ export class SignalClient {
|
|
354
372
|
};
|
355
373
|
|
356
374
|
this.ws.onclose = (ev: CloseEvent) => {
|
357
|
-
log.warn(`websocket closed`, { ev });
|
375
|
+
this.log.warn(`websocket closed`, { ...this.logContext, reason: ev.reason });
|
358
376
|
this.handleOnClose(ev.reason);
|
359
377
|
};
|
360
378
|
} finally {
|
@@ -414,7 +432,7 @@ export class SignalClient {
|
|
414
432
|
|
415
433
|
// initial offer after joining
|
416
434
|
sendOffer(offer: RTCSessionDescriptionInit) {
|
417
|
-
log.debug('sending offer', offer);
|
435
|
+
this.log.debug('sending offer', { ...this.logContext, offerSdp: offer.sdp });
|
418
436
|
this.sendRequest({
|
419
437
|
case: 'offer',
|
420
438
|
value: toProtoSessionDescription(offer),
|
@@ -423,7 +441,7 @@ export class SignalClient {
|
|
423
441
|
|
424
442
|
// answer a server-initiated offer
|
425
443
|
sendAnswer(answer: RTCSessionDescriptionInit) {
|
426
|
-
log.debug('sending answer');
|
444
|
+
this.log.debug('sending answer', { ...this.logContext, answerSdp: answer.sdp });
|
427
445
|
return this.sendRequest({
|
428
446
|
case: 'answer',
|
429
447
|
value: toProtoSessionDescription(answer),
|
@@ -431,7 +449,7 @@ export class SignalClient {
|
|
431
449
|
}
|
432
450
|
|
433
451
|
sendIceCandidate(candidate: RTCIceCandidateInit, target: SignalTarget) {
|
434
|
-
log.trace('sending ice candidate', candidate);
|
452
|
+
this.log.trace('sending ice candidate', { ...this.logContext, candidate });
|
435
453
|
return this.sendRequest({
|
436
454
|
case: 'trickle',
|
437
455
|
value: new TrickleRequest({
|
@@ -561,7 +579,10 @@ export class SignalClient {
|
|
561
579
|
await sleep(this.signalLatency);
|
562
580
|
}
|
563
581
|
if (!this.ws || this.ws.readyState !== this.ws.OPEN) {
|
564
|
-
log.error(
|
582
|
+
this.log.error(
|
583
|
+
`cannot send signal request before connected, type: ${message?.case}`,
|
584
|
+
this.logContext,
|
585
|
+
);
|
565
586
|
return;
|
566
587
|
}
|
567
588
|
const req = new SignalRequest({ message });
|
@@ -573,14 +594,14 @@ export class SignalClient {
|
|
573
594
|
this.ws.send(req.toBinary());
|
574
595
|
}
|
575
596
|
} catch (e) {
|
576
|
-
log.error('error sending signal message', { error: e });
|
597
|
+
this.log.error('error sending signal message', { ...this.logContext, error: e });
|
577
598
|
}
|
578
599
|
}
|
579
600
|
|
580
601
|
private handleSignalResponse(res: SignalResponse) {
|
581
602
|
const msg = res.message;
|
582
603
|
if (msg == undefined) {
|
583
|
-
log.debug('received unsupported message');
|
604
|
+
this.log.debug('received unsupported message', this.logContext);
|
584
605
|
return;
|
585
606
|
}
|
586
607
|
|
@@ -658,7 +679,7 @@ export class SignalClient {
|
|
658
679
|
this.resetPingTimeout();
|
659
680
|
pingHandled = true;
|
660
681
|
} else {
|
661
|
-
log.debug('unsupported message', msg);
|
682
|
+
this.log.debug('unsupported message', { ...this.logContext, msgCase: msg.case });
|
662
683
|
}
|
663
684
|
|
664
685
|
if (!pingHandled) {
|
@@ -679,14 +700,14 @@ export class SignalClient {
|
|
679
700
|
if (this.state === SignalConnectionState.DISCONNECTED) return;
|
680
701
|
const onCloseCallback = this.onClose;
|
681
702
|
await this.close();
|
682
|
-
log.debug(`websocket connection closed: ${reason}
|
703
|
+
this.log.debug(`websocket connection closed: ${reason}`, { ...this.logContext, reason });
|
683
704
|
if (onCloseCallback) {
|
684
705
|
onCloseCallback(reason);
|
685
706
|
}
|
686
707
|
}
|
687
708
|
|
688
709
|
private handleWSError(ev: Event) {
|
689
|
-
log.error('websocket error', ev);
|
710
|
+
this.log.error('websocket error', { ...this.logContext, error: ev });
|
690
711
|
}
|
691
712
|
|
692
713
|
/**
|
@@ -696,14 +717,15 @@ export class SignalClient {
|
|
696
717
|
private resetPingTimeout() {
|
697
718
|
this.clearPingTimeout();
|
698
719
|
if (!this.pingTimeoutDuration) {
|
699
|
-
log.warn('ping timeout duration not set');
|
720
|
+
this.log.warn('ping timeout duration not set', this.logContext);
|
700
721
|
return;
|
701
722
|
}
|
702
723
|
this.pingTimeout = CriticalTimers.setTimeout(() => {
|
703
|
-
log.warn(
|
724
|
+
this.log.warn(
|
704
725
|
`ping timeout triggered. last pong received at: ${new Date(
|
705
726
|
Date.now() - this.pingTimeoutDuration! * 1000,
|
706
727
|
).toUTCString()}`,
|
728
|
+
this.logContext,
|
707
729
|
);
|
708
730
|
this.handleOnClose('ping timeout');
|
709
731
|
}, this.pingTimeoutDuration * 1000);
|
@@ -722,17 +744,17 @@ export class SignalClient {
|
|
722
744
|
this.clearPingInterval();
|
723
745
|
this.resetPingTimeout();
|
724
746
|
if (!this.pingIntervalDuration) {
|
725
|
-
log.warn('ping interval duration not set');
|
747
|
+
this.log.warn('ping interval duration not set', this.logContext);
|
726
748
|
return;
|
727
749
|
}
|
728
|
-
log.debug('start ping interval');
|
750
|
+
this.log.debug('start ping interval', this.logContext);
|
729
751
|
this.pingInterval = CriticalTimers.setInterval(() => {
|
730
752
|
this.sendPing();
|
731
753
|
}, this.pingIntervalDuration * 1000);
|
732
754
|
}
|
733
755
|
|
734
756
|
private clearPingInterval() {
|
735
|
-
log.debug('clearing ping interval');
|
757
|
+
this.log.debug('clearing ping interval', this.logContext);
|
736
758
|
this.clearPingTimeout();
|
737
759
|
if (this.pingInterval) {
|
738
760
|
CriticalTimers.clearInterval(this.pingInterval);
|
package/src/index.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { LogLevel, setLogExtension, setLogLevel } from './logger';
|
1
|
+
import { LogLevel, getLogger, setLogExtension, setLogLevel } from './logger';
|
2
2
|
import { DataPacket_Kind, DisconnectReason, VideoQuality } from './proto/livekit_models_pb';
|
3
3
|
import DefaultReconnectPolicy from './room/DefaultReconnectPolicy';
|
4
4
|
import Room, { ConnectionState, RoomState } from './room/Room';
|
@@ -55,6 +55,7 @@ export {
|
|
55
55
|
supportsVP9,
|
56
56
|
createAudioAnalyser,
|
57
57
|
LogLevel,
|
58
|
+
getLogger,
|
58
59
|
Room,
|
59
60
|
ConnectionState,
|
60
61
|
RoomState,
|
package/src/logger.ts
CHANGED
@@ -9,9 +9,22 @@ export enum LogLevel {
|
|
9
9
|
silent = 5,
|
10
10
|
}
|
11
11
|
|
12
|
+
export enum LoggerNames {
|
13
|
+
Default = 'livekit',
|
14
|
+
Room = 'livekit-room',
|
15
|
+
Participant = 'livekit-participant',
|
16
|
+
Track = 'livekit-track',
|
17
|
+
Publication = 'livekit-track-publication',
|
18
|
+
Engine = 'livekit-engine',
|
19
|
+
Signal = 'livekit-signal',
|
20
|
+
PCManager = 'livekit-pc-manager',
|
21
|
+
PCTransport = 'livekit-pc-transport',
|
22
|
+
E2EE = 'lk-e2ee',
|
23
|
+
}
|
24
|
+
|
12
25
|
type LogLevelString = keyof typeof LogLevel;
|
13
26
|
|
14
|
-
type StructuredLogger = {
|
27
|
+
export type StructuredLogger = {
|
15
28
|
trace: (msg: string, context?: object) => void;
|
16
29
|
debug: (msg: string, context?: object) => void;
|
17
30
|
info: (msg: string, context?: object) => void;
|
@@ -20,17 +33,28 @@ type StructuredLogger = {
|
|
20
33
|
setDefaultLevel: (level: log.LogLevelDesc) => void;
|
21
34
|
};
|
22
35
|
|
23
|
-
|
36
|
+
let livekitLogger = log.getLogger('livekit');
|
24
37
|
|
25
38
|
livekitLogger.setDefaultLevel(LogLevel.info);
|
26
39
|
|
27
40
|
export default livekitLogger as StructuredLogger;
|
28
41
|
|
29
|
-
|
42
|
+
/**
|
43
|
+
* @internal
|
44
|
+
*/
|
45
|
+
export function getLogger(name: string) {
|
46
|
+
const logger = log.getLogger(name);
|
47
|
+
logger.setDefaultLevel(livekitLogger.getLevel());
|
48
|
+
return logger as StructuredLogger;
|
49
|
+
}
|
50
|
+
|
51
|
+
export function setLogLevel(level: LogLevel | LogLevelString, loggerName?: LoggerNames) {
|
30
52
|
if (loggerName) {
|
31
53
|
log.getLogger(loggerName).setLevel(level);
|
32
54
|
}
|
33
|
-
for (const logger of Object.
|
55
|
+
for (const logger of Object.entries(log.getLoggers())
|
56
|
+
.filter(([logrName]) => logrName.startsWith('livekit'))
|
57
|
+
.map(([, logr]) => logr)) {
|
34
58
|
logger.setLevel(level);
|
35
59
|
}
|
36
60
|
}
|
@@ -41,10 +65,10 @@ export type LogExtension = (level: LogLevel, msg: string, context?: object) => v
|
|
41
65
|
* use this to hook into the logging function to allow sending internal livekit logs to third party services
|
42
66
|
* if set, the browser logs will lose their stacktrace information (see https://github.com/pimterry/loglevel#writing-plugins)
|
43
67
|
*/
|
44
|
-
export function setLogExtension(extension: LogExtension) {
|
45
|
-
const originalFactory =
|
68
|
+
export function setLogExtension(extension: LogExtension, logger = livekitLogger) {
|
69
|
+
const originalFactory = logger.methodFactory;
|
46
70
|
|
47
|
-
|
71
|
+
logger.methodFactory = (methodName, configLevel, loggerName) => {
|
48
72
|
const rawMethod = originalFactory(methodName, configLevel, loggerName);
|
49
73
|
|
50
74
|
const logLevel = LogLevel[methodName as LogLevelString];
|
@@ -58,7 +82,7 @@ export function setLogExtension(extension: LogExtension) {
|
|
58
82
|
}
|
59
83
|
};
|
60
84
|
};
|
61
|
-
|
85
|
+
logger.setLevel(logger.getLevel()); // Be sure to call setLevel method in order to apply plugin
|
62
86
|
}
|
63
87
|
|
64
88
|
export const workerLogger = log.getLogger('lk-e2ee') as StructuredLogger;
|
package/src/options.ts
CHANGED
package/src/room/PCTransport.ts
CHANGED
@@ -2,8 +2,9 @@ import { EventEmitter } from 'events';
|
|
2
2
|
import type { MediaDescription } from 'sdp-transform';
|
3
3
|
import { parse, write } from 'sdp-transform';
|
4
4
|
import { debounce } from 'ts-debounce';
|
5
|
-
import log from '../logger';
|
5
|
+
import log, { LoggerNames, getLogger } from '../logger';
|
6
6
|
import { NegotiationError, UnexpectedConnectionState } from './errors';
|
7
|
+
import type { LoggerOptions } from './types';
|
7
8
|
import { ddExtensionURI, isChromiumBased, isSVCCodec } from './utils';
|
8
9
|
|
9
10
|
/** @internal */
|
@@ -43,6 +44,10 @@ export default class PCTransport extends EventEmitter {
|
|
43
44
|
|
44
45
|
private mediaConstraints: Record<string, unknown>;
|
45
46
|
|
47
|
+
private log = log;
|
48
|
+
|
49
|
+
private loggerOptions: LoggerOptions;
|
50
|
+
|
46
51
|
pendingCandidates: RTCIceCandidateInit[] = [];
|
47
52
|
|
48
53
|
restartingIce: boolean = false;
|
@@ -71,8 +76,14 @@ export default class PCTransport extends EventEmitter {
|
|
71
76
|
|
72
77
|
onTrack?: (ev: RTCTrackEvent) => void;
|
73
78
|
|
74
|
-
constructor(
|
79
|
+
constructor(
|
80
|
+
config?: RTCConfiguration,
|
81
|
+
mediaConstraints: Record<string, unknown> = {},
|
82
|
+
loggerOptions: LoggerOptions = {},
|
83
|
+
) {
|
75
84
|
super();
|
85
|
+
this.log = getLogger(loggerOptions.loggerName ?? LoggerNames.PCTransport);
|
86
|
+
this.loggerOptions = loggerOptions;
|
76
87
|
this.config = config;
|
77
88
|
this.mediaConstraints = mediaConstraints;
|
78
89
|
this._pc = this.createPC();
|
@@ -112,6 +123,12 @@ export default class PCTransport extends EventEmitter {
|
|
112
123
|
return pc;
|
113
124
|
}
|
114
125
|
|
126
|
+
private get logContext() {
|
127
|
+
return {
|
128
|
+
...this.loggerOptions.loggerContextCb?.(),
|
129
|
+
};
|
130
|
+
}
|
131
|
+
|
115
132
|
get isICEConnected(): boolean {
|
116
133
|
return (
|
117
134
|
this._pc !== null &&
|
@@ -229,7 +246,7 @@ export default class PCTransport extends EventEmitter {
|
|
229
246
|
}
|
230
247
|
|
231
248
|
if (options?.iceRestart) {
|
232
|
-
log.debug('restarting ICE');
|
249
|
+
this.log.debug('restarting ICE', this.logContext);
|
233
250
|
this.restartingIce = true;
|
234
251
|
}
|
235
252
|
|
@@ -246,12 +263,12 @@ export default class PCTransport extends EventEmitter {
|
|
246
263
|
return;
|
247
264
|
}
|
248
265
|
} else if (!this._pc || this._pc.signalingState === 'closed') {
|
249
|
-
log.warn('could not createOffer with closed peer connection');
|
266
|
+
this.log.warn('could not createOffer with closed peer connection', this.logContext);
|
250
267
|
return;
|
251
268
|
}
|
252
269
|
|
253
270
|
// actually negotiate
|
254
|
-
log.debug('starting to negotiate');
|
271
|
+
this.log.debug('starting to negotiate', this.logContext);
|
255
272
|
const offer = await this.pc.createOffer(options);
|
256
273
|
|
257
274
|
const sdpParsed = parse(offer.sdp ?? '');
|
@@ -452,7 +469,10 @@ export default class PCTransport extends EventEmitter {
|
|
452
469
|
const originalSdp = sd.sdp;
|
453
470
|
sd.sdp = munged;
|
454
471
|
try {
|
455
|
-
log.debug(
|
472
|
+
this.log.debug(
|
473
|
+
`setting munged ${remote ? 'remote' : 'local'} description`,
|
474
|
+
this.logContext,
|
475
|
+
);
|
456
476
|
if (remote) {
|
457
477
|
await this.pc.setRemoteDescription(sd);
|
458
478
|
} else {
|
@@ -460,7 +480,8 @@ export default class PCTransport extends EventEmitter {
|
|
460
480
|
}
|
461
481
|
return;
|
462
482
|
} catch (e) {
|
463
|
-
log.warn(`not able to set ${sd.type}, falling back to unmodified sdp`, {
|
483
|
+
this.log.warn(`not able to set ${sd.type}, falling back to unmodified sdp`, {
|
484
|
+
...this.logContext,
|
464
485
|
error: e,
|
465
486
|
sdp: munged,
|
466
487
|
});
|
@@ -491,7 +512,7 @@ export default class PCTransport extends EventEmitter {
|
|
491
512
|
if (!remote && this.pc.remoteDescription) {
|
492
513
|
fields.remoteSdp = this.pc.remoteDescription;
|
493
514
|
}
|
494
|
-
log.error(`unable to set ${sd.type}`, fields);
|
515
|
+
this.log.error(`unable to set ${sd.type}`, { ...this.logContext, fields });
|
495
516
|
throw new NegotiationError(msg);
|
496
517
|
}
|
497
518
|
}
|