livekit-client 1.15.6 → 1.15.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) 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 +558 -327
  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/track/LocalAudioTrack.d.ts +2 -1
  33. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  34. package/dist/src/room/track/LocalTrack.d.ts +2 -1
  35. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  36. package/dist/src/room/track/LocalTrackPublication.d.ts +2 -1
  37. package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -1
  38. package/dist/src/room/track/LocalVideoTrack.d.ts +2 -1
  39. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  40. package/dist/src/room/track/RemoteAudioTrack.d.ts +2 -1
  41. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  42. package/dist/src/room/track/RemoteTrack.d.ts +2 -1
  43. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  44. package/dist/src/room/track/RemoteTrackPublication.d.ts +2 -1
  45. package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
  46. package/dist/src/room/track/RemoteVideoTrack.d.ts +2 -1
  47. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  48. package/dist/src/room/track/Track.d.ts +10 -1
  49. package/dist/src/room/track/Track.d.ts.map +1 -1
  50. package/dist/src/room/track/TrackPublication.d.ts +7 -1
  51. package/dist/src/room/track/TrackPublication.d.ts.map +1 -1
  52. package/dist/src/room/track/create.d.ts.map +1 -1
  53. package/dist/src/room/track/options.d.ts +8 -3
  54. package/dist/src/room/track/options.d.ts.map +1 -1
  55. package/dist/src/room/track/utils.d.ts +1 -0
  56. package/dist/src/room/track/utils.d.ts.map +1 -1
  57. package/dist/src/room/types.d.ts +4 -0
  58. package/dist/src/room/types.d.ts.map +1 -1
  59. package/dist/src/room/utils.d.ts +1 -0
  60. package/dist/src/room/utils.d.ts.map +1 -1
  61. package/dist/ts4.2/src/api/SignalClient.d.ts +5 -1
  62. package/dist/ts4.2/src/index.d.ts +2 -2
  63. package/dist/ts4.2/src/logger.d.ts +19 -3
  64. package/dist/ts4.2/src/options.d.ts +1 -0
  65. package/dist/ts4.2/src/room/PCTransport.d.ts +5 -1
  66. package/dist/ts4.2/src/room/PCTransportManager.d.ts +5 -1
  67. package/dist/ts4.2/src/room/RTCEngine.d.ts +8 -0
  68. package/dist/ts4.2/src/room/Room.d.ts +2 -0
  69. package/dist/ts4.2/src/room/participant/Participant.d.ts +9 -1
  70. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +2 -1
  71. package/dist/ts4.2/src/room/participant/publishUtils.d.ts +2 -1
  72. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +2 -1
  73. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +2 -1
  74. package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +2 -1
  75. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +2 -1
  76. package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +2 -1
  77. package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +2 -1
  78. package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +2 -1
  79. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +2 -1
  80. package/dist/ts4.2/src/room/track/Track.d.ts +10 -1
  81. package/dist/ts4.2/src/room/track/TrackPublication.d.ts +7 -1
  82. package/dist/ts4.2/src/room/track/options.d.ts +8 -3
  83. package/dist/ts4.2/src/room/track/utils.d.ts +1 -0
  84. package/dist/ts4.2/src/room/types.d.ts +4 -0
  85. package/dist/ts4.2/src/room/utils.d.ts +1 -0
  86. package/package.json +2 -2
  87. package/src/api/SignalClient.ts +43 -21
  88. package/src/index.ts +2 -1
  89. package/src/logger.ts +32 -8
  90. package/src/options.ts +2 -0
  91. package/src/room/PCTransport.ts +29 -8
  92. package/src/room/PCTransportManager.ts +29 -9
  93. package/src/room/RTCEngine.ts +71 -34
  94. package/src/room/Room.ts +94 -30
  95. package/src/room/participant/LocalParticipant.ts +163 -47
  96. package/src/room/participant/Participant.ts +26 -3
  97. package/src/room/participant/RemoteParticipant.ts +23 -15
  98. package/src/room/participant/publishUtils.test.ts +2 -2
  99. package/src/room/participant/publishUtils.ts +7 -4
  100. package/src/room/track/LocalAudioTrack.ts +8 -7
  101. package/src/room/track/LocalTrack.ts +23 -19
  102. package/src/room/track/LocalTrackPublication.ts +3 -2
  103. package/src/room/track/LocalVideoTrack.ts +31 -13
  104. package/src/room/track/RemoteAudioTrack.ts +4 -3
  105. package/src/room/track/RemoteTrack.ts +4 -1
  106. package/src/room/track/RemoteTrackPublication.ts +21 -13
  107. package/src/room/track/RemoteVideoTrack.ts +5 -4
  108. package/src/room/track/Track.ts +32 -2
  109. package/src/room/track/TrackPublication.ts +18 -3
  110. package/src/room/track/create.ts +4 -3
  111. package/src/room/track/options.ts +12 -5
  112. package/src/room/track/utils.ts +23 -1
  113. package/src/room/types.ts +5 -0
  114. package/src/room/utils.ts +5 -0
@@ -1,4 +1,3 @@
1
- import log from '../../logger';
2
1
  import type { InternalRoomOptions } from '../../options';
3
2
  import {
4
3
  DataPacket,
@@ -32,15 +31,25 @@ import type {
32
31
  TrackPublishOptions,
33
32
  VideoCaptureOptions,
34
33
  } from '../track/options';
35
- import { VideoPresets, isBackupCodec } from '../track/options';
34
+ import { ScreenSharePresets, VideoPresets, isBackupCodec } from '../track/options';
36
35
  import {
37
36
  constraintsForOptions,
37
+ getLogContextFromTrack,
38
38
  mergeDefaultOptions,
39
39
  mimeTypeToVideoCodecString,
40
40
  screenCaptureToDisplayMediaStreamOptions,
41
41
  } from '../track/utils';
42
42
  import type { DataPublishOptions } from '../types';
43
- import { Future, isFireFox, isSVCCodec, isSafari, isWeb, supportsAV1, supportsVP9 } from '../utils';
43
+ import {
44
+ Future,
45
+ isFireFox,
46
+ isSVCCodec,
47
+ isSafari,
48
+ isSafari17,
49
+ isWeb,
50
+ supportsAV1,
51
+ supportsVP9,
52
+ } from '../utils';
44
53
  import Participant from './Participant';
45
54
  import type { ParticipantTrackPermission } from './ParticipantTrackPermission';
46
55
  import { trackPermissionToProto } from './ParticipantTrackPermission';
@@ -86,7 +95,10 @@ export default class LocalParticipant extends Participant {
86
95
 
87
96
  /** @internal */
88
97
  constructor(sid: string, identity: string, engine: RTCEngine, options: InternalRoomOptions) {
89
- super(sid, identity);
98
+ super(sid, identity, undefined, undefined, {
99
+ loggerName: options.loggerName,
100
+ loggerContextCb: () => this.engine.logContext,
101
+ });
90
102
  this.audioTracks = new Map();
91
103
  this.videoTracks = new Map();
92
104
  this.tracks = new Map();
@@ -164,7 +176,7 @@ export default class LocalParticipant extends Participant {
164
176
 
165
177
  private handleDisconnected = () => {
166
178
  if (this.reconnectFuture) {
167
- this.reconnectFuture.promise.catch((e) => log.warn(e));
179
+ this.reconnectFuture.promise.catch((e) => this.log.warn(e.message, this.logContext));
168
180
  this.reconnectFuture?.reject?.('Got disconnected during reconnection attempt');
169
181
  this.reconnectFuture = undefined;
170
182
  }
@@ -277,7 +289,7 @@ export default class LocalParticipant extends Participant {
277
289
  options?: VideoCaptureOptions | AudioCaptureOptions | ScreenShareCaptureOptions,
278
290
  publishOptions?: TrackPublishOptions,
279
291
  ) {
280
- log.debug('setTrackEnabled', { source, enabled });
292
+ this.log.debug('setTrackEnabled', { ...this.logContext, source, enabled });
281
293
  let track = this.getTrack(source);
282
294
  if (enabled) {
283
295
  if (track) {
@@ -285,7 +297,7 @@ export default class LocalParticipant extends Participant {
285
297
  } else {
286
298
  let localTracks: Array<LocalTrack> | undefined;
287
299
  if (this.pendingPublishing.has(source)) {
288
- log.info('skipping duplicate published source', { source });
300
+ this.log.info('skipping duplicate published source', { ...this.logContext, source });
289
301
  // no-op it's already been requested
290
302
  return;
291
303
  }
@@ -313,7 +325,10 @@ export default class LocalParticipant extends Participant {
313
325
  }
314
326
  const publishPromises: Array<Promise<LocalTrackPublication>> = [];
315
327
  for (const localTrack of localTracks) {
316
- log.info('publishing track', { localTrack });
328
+ this.log.info('publishing track', {
329
+ ...this.logContext,
330
+ ...getLogContextFromTrack(localTrack),
331
+ });
317
332
  publishPromises.push(this.publishTrack(localTrack, publishOptions));
318
333
  }
319
334
  const publishedTracks = await Promise.all(publishPromises);
@@ -423,7 +438,10 @@ export default class LocalParticipant extends Participant {
423
438
  if (typeof conOrBool !== 'boolean') {
424
439
  trackConstraints = conOrBool;
425
440
  }
426
- const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints);
441
+ const track = mediaTrackToLocalTrack(mediaStreamTrack, trackConstraints, {
442
+ loggerName: this.roomOptions.loggerName,
443
+ loggerContextCb: () => this.logContext,
444
+ });
427
445
  if (track.kind === Track.Kind.Video) {
428
446
  track.source = Track.Source.Camera;
429
447
  } else if (track.kind === Track.Kind.Audio) {
@@ -448,6 +466,13 @@ export default class LocalParticipant extends Participant {
448
466
  throw new DeviceUnsupportedError('getDisplayMedia not supported');
449
467
  }
450
468
 
469
+ if (options.resolution === undefined && !isSafari17()) {
470
+ // we need to constrain the dimensions, otherwise it could lead to low bitrate
471
+ // due to encoding a huge video. Encoding such large surfaces is really expensive
472
+ // unfortunately Safari 17 has a but and cannot be constrained by default
473
+ options.resolution = ScreenSharePresets.h1080fps30.resolution;
474
+ }
475
+
451
476
  const constraints = screenCaptureToDisplayMediaStreamOptions(options);
452
477
  const stream: MediaStream = await navigator.mediaDevices.getDisplayMedia(constraints);
453
478
 
@@ -455,8 +480,15 @@ export default class LocalParticipant extends Participant {
455
480
  if (tracks.length === 0) {
456
481
  throw new TrackInvalidError('no video track found');
457
482
  }
458
- const screenVideo = new LocalVideoTrack(tracks[0], undefined, false);
483
+ const screenVideo = new LocalVideoTrack(tracks[0], undefined, false, {
484
+ loggerName: this.roomOptions.loggerName,
485
+ loggerContextCb: () => this.logContext,
486
+ });
459
487
  screenVideo.source = Track.Source.ScreenShare;
488
+ if (options.contentHint) {
489
+ screenVideo.mediaStreamTrack.contentHint = options.contentHint;
490
+ }
491
+
460
492
  const localTracks: Array<LocalTrack> = [screenVideo];
461
493
  if (stream.getAudioTracks().length > 0) {
462
494
  this.emit(ParticipantEvent.AudioStreamAcquired);
@@ -465,6 +497,7 @@ export default class LocalParticipant extends Participant {
465
497
  undefined,
466
498
  false,
467
499
  this.audioContext,
500
+ { loggerName: this.roomOptions.loggerName, loggerContextCb: () => this.logContext },
468
501
  );
469
502
  screenAudio.source = Track.Source.ScreenShareAudio;
470
503
  localTracks.push(screenAudio);
@@ -513,14 +546,25 @@ export default class LocalParticipant extends Participant {
513
546
  if (track instanceof MediaStreamTrack) {
514
547
  switch (track.kind) {
515
548
  case 'audio':
516
- track = new LocalAudioTrack(track, defaultConstraints, true, this.audioContext);
549
+ track = new LocalAudioTrack(track, defaultConstraints, true, this.audioContext, {
550
+ loggerName: this.roomOptions.loggerName,
551
+ loggerContextCb: () => this.logContext,
552
+ });
517
553
  break;
518
554
  case 'video':
519
- track = new LocalVideoTrack(track, defaultConstraints, true);
555
+ track = new LocalVideoTrack(track, defaultConstraints, true, {
556
+ loggerName: this.roomOptions.loggerName,
557
+ loggerContextCb: () => this.logContext,
558
+ });
520
559
  break;
521
560
  default:
522
561
  throw new TrackInvalidError(`unsupported MediaStreamTrack kind ${track.kind}`);
523
562
  }
563
+ } else {
564
+ track.updateLoggerOptions({
565
+ loggerName: this.roomOptions.loggerName,
566
+ loggerContextCb: () => this.logContext,
567
+ });
524
568
  }
525
569
 
526
570
  if (track instanceof LocalAudioTrack) {
@@ -539,7 +583,10 @@ export default class LocalParticipant extends Participant {
539
583
  });
540
584
 
541
585
  if (existingPublication) {
542
- log.warn('track has already been published, skipping');
586
+ this.log.warn('track has already been published, skipping', {
587
+ ...this.logContext,
588
+ ...getLogContextFromTrack(existingPublication),
589
+ });
543
590
  return existingPublication;
544
591
  }
545
592
 
@@ -556,12 +603,16 @@ export default class LocalParticipant extends Participant {
556
603
  options = {};
557
604
  }
558
605
  if (options.dtx === undefined) {
559
- log.info(
606
+ this.log.info(
560
607
  `Opus DTX will be disabled for stereo tracks by default. Enable them explicitly to make it work.`,
608
+ {
609
+ ...this.logContext,
610
+ ...getLogContextFromTrack(track),
611
+ },
561
612
  );
562
613
  }
563
614
  if (options.red === undefined) {
564
- log.info(
615
+ this.log.info(
565
616
  `Opus RED will be disabled for stereo tracks by default. Enable them explicitly to make it work.`,
566
617
  );
567
618
  }
@@ -575,7 +626,12 @@ export default class LocalParticipant extends Participant {
575
626
 
576
627
  // disable simulcast if e2ee is set on safari
577
628
  if (isSafari() && this.roomOptions.e2ee) {
578
- log.info(`End-to-end encryption is set up, simulcast publishing will be disabled on Safari`);
629
+ this.log.info(
630
+ `End-to-end encryption is set up, simulcast publishing will be disabled on Safari`,
631
+ {
632
+ ...this.logContext,
633
+ },
634
+ );
579
635
  opts.simulcast = false;
580
636
  }
581
637
 
@@ -599,7 +655,10 @@ export default class LocalParticipant extends Participant {
599
655
  (publishedTrack) => track instanceof LocalTrack && publishedTrack.source === track.source,
600
656
  );
601
657
  if (existingTrackOfSource && track.source !== Track.Source.Unknown) {
602
- log.info(`publishing a second track with the same source: ${track.source}`);
658
+ this.log.info(`publishing a second track with the same source: ${track.source}`, {
659
+ ...this.logContext,
660
+ ...getLogContextFromTrack(track),
661
+ });
603
662
  }
604
663
  if (opts.stopMicTrackOnMute && track instanceof LocalAudioTrack) {
605
664
  track.stopOnMute = true;
@@ -664,7 +723,11 @@ export default class LocalParticipant extends Participant {
664
723
  height: defaultRes.height,
665
724
  };
666
725
  // log failure
667
- log.error('could not determine track dimensions, using defaults', dims);
726
+ this.log.error('could not determine track dimensions, using defaults', {
727
+ ...this.logContext,
728
+ ...getLogContextFromTrack(track),
729
+ dims,
730
+ });
668
731
  }
669
732
  // width and height should be defined for video
670
733
  req.width = dims.width;
@@ -748,7 +811,11 @@ export default class LocalParticipant extends Participant {
748
811
  if (primaryCodecMime && track.kind === Track.Kind.Video) {
749
812
  const updatedCodec = mimeTypeToVideoCodecString(primaryCodecMime);
750
813
  if (updatedCodec !== videoCodec) {
751
- log.debug('falling back to server selected codec', { codec: updatedCodec });
814
+ this.log.debug('falling back to server selected codec', {
815
+ ...this.logContext,
816
+ ...getLogContextFromTrack(track),
817
+ codec: updatedCodec,
818
+ });
752
819
  /* @ts-ignore */
753
820
  opts.videoCodec = updatedCodec;
754
821
 
@@ -762,7 +829,10 @@ export default class LocalParticipant extends Participant {
762
829
  }
763
830
  }
764
831
 
765
- const publication = new LocalTrackPublication(track.kind, ti, track);
832
+ const publication = new LocalTrackPublication(track.kind, ti, track, {
833
+ loggerName: this.roomOptions.loggerName,
834
+ loggerContextCb: () => this.logContext,
835
+ });
766
836
  // save options for when it needs to be republished again
767
837
  publication.options = opts;
768
838
  track.sid = ti.sid;
@@ -770,7 +840,11 @@ export default class LocalParticipant extends Participant {
770
840
  if (!this.engine.pcManager) {
771
841
  throw new UnexpectedConnectionState('pcManager is not ready');
772
842
  }
773
- log.debug(`publishing ${track.kind} with encodings`, { encodings, trackInfo: ti });
843
+ this.log.debug(`publishing ${track.kind} with encodings`, {
844
+ ...this.logContext,
845
+ encodings,
846
+ trackInfo: ti,
847
+ });
774
848
 
775
849
  track.sender = await this.engine.createSender(track, opts, encodings);
776
850
 
@@ -863,8 +937,12 @@ export default class LocalParticipant extends Participant {
863
937
 
864
938
  const encodings = computeTrackBackupEncodings(track, videoCodec, opts);
865
939
  if (!encodings) {
866
- log.info(
940
+ this.log.info(
867
941
  `backup codec has been disabled, ignoring request to add additional codec for track`,
942
+ {
943
+ ...this.logContext,
944
+ ...getLogContextFromTrack(track),
945
+ },
868
946
  );
869
947
  return;
870
948
  }
@@ -897,7 +975,11 @@ export default class LocalParticipant extends Participant {
897
975
  await this.engine.createSimulcastSender(track, simulcastTrack, opts, encodings);
898
976
 
899
977
  await this.engine.negotiate();
900
- log.debug(`published ${videoCodec} for track ${track.sid}`, { encodings, trackInfo: ti });
978
+ this.log.debug(`published ${videoCodec} for track ${track.sid}`, {
979
+ ...this.logContext,
980
+ encodings,
981
+ trackInfo: ti,
982
+ });
901
983
  }
902
984
 
903
985
  async unpublishTrack(
@@ -907,12 +989,17 @@ export default class LocalParticipant extends Participant {
907
989
  // look through all published tracks to find the right ones
908
990
  const publication = this.getPublicationForTrack(track);
909
991
 
910
- log.debug('unpublishing track', { track, method: 'unpublishTrack' });
992
+ const pubLogContext = publication ? getLogContextFromTrack(publication) : undefined;
993
+
994
+ this.log.debug('unpublishing track', {
995
+ ...this.logContext,
996
+ ...pubLogContext,
997
+ });
911
998
 
912
999
  if (!publication || !publication.track) {
913
- log.warn('track was not unpublished because no publication was found', {
914
- track,
915
- method: 'unpublishTrack',
1000
+ this.log.warn('track was not unpublished because no publication was found', {
1001
+ ...this.logContext,
1002
+ ...pubLogContext,
916
1003
  });
917
1004
  return undefined;
918
1005
  }
@@ -965,7 +1052,11 @@ export default class LocalParticipant extends Participant {
965
1052
  track.simulcastCodecs.clear();
966
1053
  }
967
1054
  } catch (e) {
968
- log.warn('failed to unpublish track', { error: e, method: 'unpublishTrack' });
1055
+ this.log.warn('failed to unpublish track', {
1056
+ ...this.logContext,
1057
+ ...pubLogContext,
1058
+ error: e,
1059
+ });
969
1060
  }
970
1061
  }
971
1062
 
@@ -1023,7 +1114,8 @@ export default class LocalParticipant extends Participant {
1023
1114
  ) {
1024
1115
  // generally we need to restart the track before publishing, often a full reconnect
1025
1116
  // is necessary because computer had gone to sleep.
1026
- log.debug('restarting existing track', {
1117
+ this.log.debug('restarting existing track', {
1118
+ ...this.logContext,
1027
1119
  track: pub.trackSid,
1028
1120
  });
1029
1121
  await track.restartTrack();
@@ -1152,9 +1244,10 @@ export default class LocalParticipant extends Participant {
1152
1244
  if (pub) {
1153
1245
  const mutedOnServer = pub.isMuted || (pub.track?.isUpstreamPaused ?? false);
1154
1246
  if (mutedOnServer !== ti.muted) {
1155
- log.debug('updating server mute state after reconcile', {
1156
- sid: ti.sid,
1157
- muted: mutedOnServer,
1247
+ this.log.debug('updating server mute state after reconcile', {
1248
+ ...this.logContext,
1249
+ ...getLogContextFromTrack(pub),
1250
+ mutedOnServer,
1158
1251
  });
1159
1252
  this.engine.client.sendMuteTrack(ti.sid, mutedOnServer);
1160
1253
  }
@@ -1164,7 +1257,8 @@ export default class LocalParticipant extends Participant {
1164
1257
  }
1165
1258
 
1166
1259
  private updateTrackSubscriptionPermissions = () => {
1167
- log.debug('updating track subscription permissions', {
1260
+ this.log.debug('updating track subscription permissions', {
1261
+ ...this.logContext,
1168
1262
  allParticipantsAllowed: this.allParticipantsAllowedToSubscribe,
1169
1263
  participantTrackPermissions: this.participantTrackPermissions,
1170
1264
  });
@@ -1187,7 +1281,10 @@ export default class LocalParticipant extends Participant {
1187
1281
  }
1188
1282
 
1189
1283
  if (!track.sid) {
1190
- log.error('could not update mute status for unpublished track', track);
1284
+ this.log.error('could not update mute status for unpublished track', {
1285
+ ...this.logContext,
1286
+ ...getLogContextFromTrack(track),
1287
+ });
1191
1288
  return;
1192
1289
  }
1193
1290
 
@@ -1195,12 +1292,18 @@ export default class LocalParticipant extends Participant {
1195
1292
  };
1196
1293
 
1197
1294
  private onTrackUpstreamPaused = (track: LocalTrack) => {
1198
- log.debug('upstream paused');
1295
+ this.log.debug('upstream paused', {
1296
+ ...this.logContext,
1297
+ ...getLogContextFromTrack(track),
1298
+ });
1199
1299
  this.onTrackMuted(track, true);
1200
1300
  };
1201
1301
 
1202
1302
  private onTrackUpstreamResumed = (track: LocalTrack) => {
1203
- log.debug('upstream resumed');
1303
+ this.log.debug('upstream resumed', {
1304
+ ...this.logContext,
1305
+ ...getLogContextFromTrack(track),
1306
+ });
1204
1307
  this.onTrackMuted(track, track.isMuted);
1205
1308
  };
1206
1309
 
@@ -1210,9 +1313,9 @@ export default class LocalParticipant extends Participant {
1210
1313
  }
1211
1314
  const pub = this.videoTracks.get(update.trackSid);
1212
1315
  if (!pub) {
1213
- log.warn('received subscribed quality update for unknown track', {
1214
- method: 'handleSubscribedQualityUpdate',
1215
- sid: update.trackSid,
1316
+ this.log.warn('received subscribed quality update for unknown track', {
1317
+ ...this.logContext,
1318
+ trackSid: update.trackSid,
1216
1319
  });
1217
1320
  return;
1218
1321
  }
@@ -1223,7 +1326,10 @@ export default class LocalParticipant extends Participant {
1223
1326
  const newCodecs = await pub.videoTrack.setPublishingCodecs(update.subscribedCodecs);
1224
1327
  for await (const codec of newCodecs) {
1225
1328
  if (isBackupCodec(codec)) {
1226
- log.debug(`publish ${codec} for ${pub.videoTrack.sid}`);
1329
+ this.log.debug(`publish ${codec} for ${pub.videoTrack.sid}`, {
1330
+ ...this.logContext,
1331
+ ...getLogContextFromTrack(pub),
1332
+ });
1227
1333
  await this.publishAdditionalCodecForTrack(pub.videoTrack, codec, pub.options);
1228
1334
  }
1229
1335
  }
@@ -1235,8 +1341,8 @@ export default class LocalParticipant extends Participant {
1235
1341
  private handleLocalTrackUnpublished = (unpublished: TrackUnpublishedResponse) => {
1236
1342
  const track = this.tracks.get(unpublished.trackSid);
1237
1343
  if (!track) {
1238
- log.warn('received unpublished event for unknown track', {
1239
- method: 'handleLocalTrackUnpublished',
1344
+ this.log.warn('received unpublished event for unknown track', {
1345
+ ...this.logContext,
1240
1346
  trackSid: unpublished.trackSid,
1241
1347
  });
1242
1348
  return;
@@ -1249,8 +1355,9 @@ export default class LocalParticipant extends Participant {
1249
1355
  track.source === Track.Source.ScreenShare ||
1250
1356
  track.source === Track.Source.ScreenShareAudio
1251
1357
  ) {
1252
- log.debug('unpublishing local track due to TrackEnded', {
1253
- track: track.sid,
1358
+ this.log.debug('unpublishing local track due to TrackEnded', {
1359
+ ...this.logContext,
1360
+ ...getLogContextFromTrack(track),
1254
1361
  });
1255
1362
  this.unpublishTrack(track);
1256
1363
  } else if (track.isUserProvided) {
@@ -1265,7 +1372,10 @@ export default class LocalParticipant extends Participant {
1265
1372
  name: track.source === Track.Source.Camera ? 'camera' : 'microphone',
1266
1373
  });
1267
1374
  if (currentPermissions && currentPermissions.state === 'denied') {
1268
- log.warn(`user has revoked access to ${track.source}`);
1375
+ this.log.warn(`user has revoked access to ${track.source}`, {
1376
+ ...this.logContext,
1377
+ ...getLogContextFromTrack(track),
1378
+ });
1269
1379
 
1270
1380
  // detect granted change after permissions were denied to try and resume then
1271
1381
  currentPermissions.onchange = () => {
@@ -1283,11 +1393,17 @@ export default class LocalParticipant extends Participant {
1283
1393
  }
1284
1394
  }
1285
1395
  if (!track.isMuted) {
1286
- log.debug('track ended, attempting to use a different device');
1396
+ this.log.debug('track ended, attempting to use a different device', {
1397
+ ...this.logContext,
1398
+ ...getLogContextFromTrack(track),
1399
+ });
1287
1400
  await track.restartTrack();
1288
1401
  }
1289
1402
  } catch (e) {
1290
- log.warn(`could not restart track, muting instead`);
1403
+ this.log.warn(`could not restart track, muting instead`, {
1404
+ ...this.logContext,
1405
+ ...getLogContextFromTrack(track),
1406
+ });
1291
1407
  await track.mute();
1292
1408
  }
1293
1409
  }
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter } from 'events';
2
2
  import type TypedEmitter from 'typed-emitter';
3
- import log from '../../logger';
3
+ import log, { LoggerNames, StructuredLogger, getLogger } from '../../logger';
4
4
  import {
5
5
  DataPacket_Kind,
6
6
  ParticipantInfo,
@@ -16,6 +16,7 @@ import type RemoteTrack from '../track/RemoteTrack';
16
16
  import type RemoteTrackPublication from '../track/RemoteTrackPublication';
17
17
  import { Track } from '../track/Track';
18
18
  import type { TrackPublication } from '../track/TrackPublication';
19
+ import type { LoggerOptions } from '../types';
19
20
 
20
21
  export enum ConnectionQuality {
21
22
  Excellent = 'excellent',
@@ -80,6 +81,18 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
80
81
 
81
82
  protected audioContext?: AudioContext;
82
83
 
84
+ protected log: StructuredLogger = log;
85
+
86
+ protected loggerOptions?: LoggerOptions;
87
+
88
+ protected get logContext() {
89
+ return {
90
+ ...this.loggerOptions?.loggerContextCb?.(),
91
+ participantSid: this.sid,
92
+ participantId: this.identity,
93
+ };
94
+ }
95
+
83
96
  get isEncrypted() {
84
97
  return this.tracks.size > 0 && Array.from(this.tracks.values()).every((tr) => tr.isEncrypted);
85
98
  }
@@ -89,8 +102,18 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
89
102
  }
90
103
 
91
104
  /** @internal */
92
- constructor(sid: string, identity: string, name?: string, metadata?: string) {
105
+ constructor(
106
+ sid: string,
107
+ identity: string,
108
+ name?: string,
109
+ metadata?: string,
110
+ loggerOptions?: LoggerOptions,
111
+ ) {
93
112
  super();
113
+
114
+ this.log = getLogger(loggerOptions?.loggerName ?? LoggerNames.Participant);
115
+ this.loggerOptions = loggerOptions;
116
+
94
117
  this.setMaxListeners(100);
95
118
  this.sid = sid;
96
119
  this.identity = identity;
@@ -187,7 +210,7 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
187
210
  }
188
211
  // set this last so setMetadata can detect changes
189
212
  this.participantInfo = info;
190
- log.trace('update participant info', { info });
213
+ this.log.trace('update participant info', { ...this.logContext, info });
191
214
  return true;
192
215
  }
193
216
 
@@ -1,5 +1,4 @@
1
1
  import type { SignalClient } from '../../api/SignalClient';
2
- import log from '../../logger';
3
2
  import type { ParticipantInfo, SubscriptionError } from '../../proto/livekit_models_pb';
4
3
  import type { UpdateSubscription, UpdateTrackSettings } from '../../proto/livekit_rtc_pb';
5
4
  import { ParticipantEvent, TrackEvent } from '../events';
@@ -11,6 +10,8 @@ import { Track } from '../track/Track';
11
10
  import type { TrackPublication } from '../track/TrackPublication';
12
11
  import type { AudioOutputOptions } from '../track/options';
13
12
  import type { AdaptiveStreamSettings } from '../track/types';
13
+ import { getLogContextFromTrack } from '../track/utils';
14
+ import type { LoggerOptions } from '../types';
14
15
  import Participant from './Participant';
15
16
  import type { ParticipantEventCallbacks } from './Participant';
16
17
 
@@ -39,8 +40,9 @@ export default class RemoteParticipant extends Participant {
39
40
  identity?: string,
40
41
  name?: string,
41
42
  metadata?: string,
43
+ loggerOptions?: LoggerOptions,
42
44
  ) {
43
- super(sid, identity || '', name, metadata);
45
+ super(sid, identity || '', name, metadata, loggerOptions);
44
46
  this.signalClient = signalClient;
45
47
  this.tracks = new Map();
46
48
  this.audioTracks = new Map();
@@ -53,7 +55,10 @@ export default class RemoteParticipant extends Participant {
53
55
 
54
56
  // register action events
55
57
  publication.on(TrackEvent.UpdateSettings, (settings: UpdateTrackSettings) => {
56
- log.debug('send update settings', settings);
58
+ this.log.debug('send update settings', {
59
+ ...this.logContext,
60
+ ...getLogContextFromTrack(publication),
61
+ });
57
62
  this.signalClient.sendUpdateTrackSettings(settings);
58
63
  });
59
64
  publication.on(TrackEvent.UpdateSubscription, (sub: UpdateSubscription) => {
@@ -159,7 +164,10 @@ export default class RemoteParticipant extends Participant {
159
164
  // yet arrived. Wait a bit longer for it to arrive, or fire an error
160
165
  if (!publication) {
161
166
  if (triesLeft === 0) {
162
- log.error('could not find published track', { participant: this.sid, trackSid: sid });
167
+ this.log.error('could not find published track', {
168
+ ...this.logContext,
169
+ trackSid: sid,
170
+ });
163
171
  this.emit(ParticipantEvent.TrackSubscriptionFailed, sid);
164
172
  return;
165
173
  }
@@ -179,9 +187,9 @@ export default class RemoteParticipant extends Participant {
179
187
  }
180
188
 
181
189
  if (mediaTrack.readyState === 'ended') {
182
- log.error(
190
+ this.log.error(
183
191
  'unable to subscribe because MediaStreamTrack is ended. Do not call MediaStreamTrack.stop()',
184
- { participant: this.sid, trackSid: sid },
192
+ { ...this.logContext, ...getLogContextFromTrack(publication) },
185
193
  );
186
194
  this.emit(ParticipantEvent.TrackSubscriptionFailed, sid);
187
195
  return;
@@ -246,6 +254,7 @@ export default class RemoteParticipant extends Participant {
246
254
  kind,
247
255
  ti,
248
256
  this.signalClient.connectOptions?.autoSubscribe,
257
+ { loggerContextCb: () => this.logContext, loggerName: this.loggerOptions?.loggerName },
249
258
  );
250
259
  publication.updateInfo(ti);
251
260
  newTracks.set(ti.sid, publication);
@@ -253,13 +262,12 @@ export default class RemoteParticipant extends Participant {
253
262
  (publishedTrack) => publishedTrack.source === publication?.source,
254
263
  );
255
264
  if (existingTrackOfSource && publication.source !== Track.Source.Unknown) {
256
- log.debug(
265
+ this.log.debug(
257
266
  `received a second track publication for ${this.identity} with the same source: ${publication.source}`,
258
267
  {
259
- oldTrack: existingTrackOfSource,
260
- newTrack: publication,
261
- participant: this,
262
- participantInfo: info,
268
+ ...this.logContext,
269
+ oldTrack: getLogContextFromTrack(existingTrackOfSource),
270
+ newTrack: getLogContextFromTrack(publication),
263
271
  },
264
272
  );
265
273
  }
@@ -273,9 +281,9 @@ export default class RemoteParticipant extends Participant {
273
281
  // detect removed tracks
274
282
  this.tracks.forEach((publication) => {
275
283
  if (!validTracks.has(publication.trackSid)) {
276
- log.trace('detected removed track on remote participant, unpublishing', {
277
- publication,
278
- participantSid: this.sid,
284
+ this.log.trace('detected removed track on remote participant, unpublishing', {
285
+ ...this.logContext,
286
+ ...getLogContextFromTrack(publication),
279
287
  });
280
288
  this.unpublishTrack(publication.trackSid, true);
281
289
  }
@@ -341,7 +349,7 @@ export default class RemoteParticipant extends Participant {
341
349
  event: E,
342
350
  ...args: Parameters<ParticipantEventCallbacks[E]>
343
351
  ): boolean {
344
- log.trace('participant event', { participant: this.sid, event, args });
352
+ this.log.trace('participant event', { ...this.logContext, event, args });
345
353
  return super.emit(event, ...args);
346
354
  }
347
355
  }
@@ -183,7 +183,7 @@ describe('screenShareSimulcastDefaults', () => {
183
183
  );
184
184
  expect(defaultSimulcastLayers[0].width).toBe(640);
185
185
  expect(defaultSimulcastLayers[0].height).toBe(360);
186
- expect(defaultSimulcastLayers[0].encoding.maxFramerate).toBe(3);
187
- expect(defaultSimulcastLayers[0].encoding.maxBitrate).toBe(150_000);
186
+ expect(defaultSimulcastLayers[0].encoding.maxFramerate).toBe(15);
187
+ expect(defaultSimulcastLayers[0].encoding.maxBitrate).toBe(375000);
188
188
  });
189
189
  });