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.
Files changed (117) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +14 -1
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +556 -348
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/api/SignalClient.d.ts +5 -1
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/index.d.ts +2 -2
  12. package/dist/src/index.d.ts.map +1 -1
  13. package/dist/src/logger.d.ts +19 -3
  14. package/dist/src/logger.d.ts.map +1 -1
  15. package/dist/src/options.d.ts +1 -0
  16. package/dist/src/options.d.ts.map +1 -1
  17. package/dist/src/room/PCTransport.d.ts +5 -1
  18. package/dist/src/room/PCTransport.d.ts.map +1 -1
  19. package/dist/src/room/PCTransportManager.d.ts +5 -1
  20. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  21. package/dist/src/room/RTCEngine.d.ts +8 -0
  22. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  23. package/dist/src/room/Room.d.ts +2 -0
  24. package/dist/src/room/Room.d.ts.map +1 -1
  25. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  26. package/dist/src/room/participant/Participant.d.ts +9 -1
  27. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  28. package/dist/src/room/participant/RemoteParticipant.d.ts +2 -1
  29. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  30. package/dist/src/room/participant/publishUtils.d.ts +2 -1
  31. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  32. package/dist/src/room/timers.d.ts +5 -4
  33. package/dist/src/room/timers.d.ts.map +1 -1
  34. package/dist/src/room/track/LocalAudioTrack.d.ts +2 -1
  35. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  36. package/dist/src/room/track/LocalTrack.d.ts +2 -1
  37. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  38. package/dist/src/room/track/LocalTrackPublication.d.ts +2 -1
  39. package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -1
  40. package/dist/src/room/track/LocalVideoTrack.d.ts +2 -1
  41. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  42. package/dist/src/room/track/RemoteAudioTrack.d.ts +2 -1
  43. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  44. package/dist/src/room/track/RemoteTrack.d.ts +2 -1
  45. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  46. package/dist/src/room/track/RemoteTrackPublication.d.ts +2 -1
  47. package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
  48. package/dist/src/room/track/RemoteVideoTrack.d.ts +2 -1
  49. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  50. package/dist/src/room/track/Track.d.ts +10 -1
  51. package/dist/src/room/track/Track.d.ts.map +1 -1
  52. package/dist/src/room/track/TrackPublication.d.ts +7 -1
  53. package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
  54. package/dist/src/room/track/create.d.ts.map +1 -1
  55. package/dist/src/room/track/options.d.ts +8 -3
  56. package/dist/src/room/track/options.d.ts.map +1 -1
  57. package/dist/src/room/track/utils.d.ts +1 -0
  58. package/dist/src/room/track/utils.d.ts.map +1 -1
  59. package/dist/src/room/types.d.ts +4 -0
  60. package/dist/src/room/types.d.ts.map +1 -1
  61. package/dist/src/room/utils.d.ts +1 -0
  62. package/dist/src/room/utils.d.ts.map +1 -1
  63. package/dist/ts4.2/src/api/SignalClient.d.ts +5 -1
  64. package/dist/ts4.2/src/index.d.ts +2 -2
  65. package/dist/ts4.2/src/logger.d.ts +19 -3
  66. package/dist/ts4.2/src/options.d.ts +1 -0
  67. package/dist/ts4.2/src/room/PCTransport.d.ts +5 -1
  68. package/dist/ts4.2/src/room/PCTransportManager.d.ts +5 -1
  69. package/dist/ts4.2/src/room/RTCEngine.d.ts +8 -0
  70. package/dist/ts4.2/src/room/Room.d.ts +2 -0
  71. package/dist/ts4.2/src/room/participant/Participant.d.ts +9 -1
  72. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +2 -1
  73. package/dist/ts4.2/src/room/participant/publishUtils.d.ts +2 -1
  74. package/dist/ts4.2/src/room/timers.d.ts +5 -4
  75. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +2 -1
  76. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +2 -1
  77. package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +2 -1
  78. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +2 -1
  79. package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +2 -1
  80. package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +2 -1
  81. package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +2 -1
  82. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +2 -1
  83. package/dist/ts4.2/src/room/track/Track.d.ts +10 -1
  84. package/dist/ts4.2/src/room/track/TrackPublication.d.ts +7 -1
  85. package/dist/ts4.2/src/room/track/options.d.ts +8 -3
  86. package/dist/ts4.2/src/room/track/utils.d.ts +1 -0
  87. package/dist/ts4.2/src/room/types.d.ts +4 -0
  88. package/dist/ts4.2/src/room/utils.d.ts +1 -0
  89. package/package.json +2 -2
  90. package/src/api/SignalClient.ts +43 -21
  91. package/src/index.ts +2 -1
  92. package/src/logger.ts +32 -8
  93. package/src/options.ts +2 -0
  94. package/src/room/PCTransport.ts +29 -8
  95. package/src/room/PCTransportManager.ts +29 -9
  96. package/src/room/RTCEngine.ts +71 -34
  97. package/src/room/Room.ts +91 -60
  98. package/src/room/participant/LocalParticipant.ts +165 -47
  99. package/src/room/participant/Participant.ts +26 -3
  100. package/src/room/participant/RemoteParticipant.ts +23 -15
  101. package/src/room/participant/publishUtils.test.ts +2 -2
  102. package/src/room/participant/publishUtils.ts +7 -4
  103. package/src/room/track/LocalAudioTrack.ts +8 -7
  104. package/src/room/track/LocalTrack.ts +23 -19
  105. package/src/room/track/LocalTrackPublication.ts +3 -2
  106. package/src/room/track/LocalVideoTrack.ts +31 -13
  107. package/src/room/track/RemoteAudioTrack.ts +4 -3
  108. package/src/room/track/RemoteTrack.ts +4 -1
  109. package/src/room/track/RemoteTrackPublication.ts +21 -13
  110. package/src/room/track/RemoteVideoTrack.ts +5 -4
  111. package/src/room/track/Track.ts +32 -2
  112. package/src/room/track/TrackPublication.ts +18 -3
  113. package/src/room/track/create.ts +4 -3
  114. package/src/room/track/options.ts +12 -5
  115. package/src/room/track/utils.ts +23 -1
  116. package/src/room/types.ts +5 -0
  117. 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 constructor(mediaTrack: MediaStreamTrack, kind: Track.Kind);
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
- constructor(kind: Track.Kind, id: string, name: string);
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 screen resolution
153
- * NOTE: In Safari 17, specifying any resolution at all would lead to a low-resolution
154
- * capture. https://bugs.webkit.org/show_bug.cgi?id=263015
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.6",
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.js",
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",
@@ -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
- constructor(useJSON: boolean = false) {
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('attempted to reconnect without signal options being set, ignoring');
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(`could not decode websocket message: ${typeof ev.data}`);
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(`cannot send signal request before connected, type: ${message?.case}`);
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
- const livekitLogger = log.getLogger('livekit');
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
- export function setLogLevel(level: LogLevel | LogLevelString, loggerName?: 'livekit' | 'lk-e2ee') {
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.values(log.getLoggers())) {
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 = livekitLogger.methodFactory;
68
+ export function setLogExtension(extension: LogExtension, logger = livekitLogger) {
69
+ const originalFactory = logger.methodFactory;
46
70
 
47
- livekitLogger.methodFactory = (methodName, configLevel, loggerName) => {
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
- livekitLogger.setLevel(livekitLogger.getLevel()); // Be sure to call setLevel method in order to apply plugin
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
@@ -92,6 +92,8 @@ export interface InternalRoomOptions {
92
92
  * @experimental
93
93
  */
94
94
  e2ee?: E2EEOptions;
95
+
96
+ loggerName?: string;
95
97
  }
96
98
 
97
99
  /**
@@ -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(config?: RTCConfiguration, mediaConstraints: Record<string, unknown> = {}) {
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(`setting munged ${remote ? 'remote' : 'local'} description`);
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
  }