livekit-client 1.15.5 → 1.15.7
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 +561 -328
- 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 +4 -5
- 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 +4 -5
- 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 +15 -15
- 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 +94 -30
- package/src/room/participant/LocalParticipant.ts +163 -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 +27 -20
- 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
@@ -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 {
|
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', {
|
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(
|
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',
|
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', {
|
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`, {
|
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}`, {
|
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
|
-
|
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
|
-
|
915
|
-
|
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', {
|
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
|
-
|
1157
|
-
|
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',
|
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
|
-
|
1215
|
-
|
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
|
-
|
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
|
-
|
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(
|
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',
|
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', {
|
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
|
-
{
|
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
|
-
|
260
|
-
|
261
|
-
|
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
|
-
|
278
|
-
|
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', {
|
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(
|
187
|
-
expect(defaultSimulcastLayers[0].encoding.maxBitrate).toBe(
|
186
|
+
expect(defaultSimulcastLayers[0].encoding.maxFramerate).toBe(15);
|
187
|
+
expect(defaultSimulcastLayers[0].encoding.maxBitrate).toBe(375000);
|
188
188
|
});
|
189
189
|
});
|