livekit-client 0.18.6 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/livekit-client.esm.mjs +1034 -438
- 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/{api → src/api}/RequestQueue.d.ts +0 -0
- package/dist/src/api/RequestQueue.d.ts.map +1 -0
- package/dist/{api → src/api}/SignalClient.d.ts +3 -3
- package/dist/src/api/SignalClient.d.ts.map +1 -0
- package/dist/{index.d.ts → src/index.d.ts} +3 -4
- package/dist/src/index.d.ts.map +1 -0
- package/dist/{logger.d.ts → src/logger.d.ts} +0 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/options.d.ts +61 -0
- package/dist/src/options.d.ts.map +1 -0
- package/dist/{proto → src/proto}/google/protobuf/timestamp.d.ts +0 -0
- package/dist/src/proto/google/protobuf/timestamp.d.ts.map +1 -0
- package/dist/{proto → src/proto}/livekit_models.d.ts +80 -0
- package/dist/src/proto/livekit_models.d.ts.map +1 -0
- package/dist/{proto → src/proto}/livekit_rtc.d.ts +661 -0
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -0
- package/dist/{room → src/room}/DeviceManager.d.ts +0 -0
- package/dist/src/room/DeviceManager.d.ts.map +1 -0
- package/dist/{room → src/room}/PCTransport.d.ts +0 -0
- package/dist/src/room/PCTransport.d.ts.map +1 -0
- package/dist/{room → src/room}/RTCEngine.d.ts +4 -2
- package/dist/src/room/RTCEngine.d.ts.map +1 -0
- package/dist/{room → src/room}/Room.d.ts +13 -7
- package/dist/src/room/Room.d.ts.map +1 -0
- package/dist/{room → src/room}/errors.d.ts +0 -0
- package/dist/src/room/errors.d.ts.map +1 -0
- package/dist/{room → src/room}/events.d.ts +11 -13
- package/dist/src/room/events.d.ts.map +1 -0
- package/dist/{room → src/room}/participant/LocalParticipant.d.ts +4 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -0
- package/dist/{room → src/room}/participant/Participant.d.ts +0 -4
- package/dist/src/room/participant/Participant.d.ts.map +1 -0
- package/dist/{room → src/room}/participant/ParticipantTrackPermission.d.ts +0 -0
- package/dist/src/room/participant/ParticipantTrackPermission.d.ts.map +1 -0
- package/dist/{room → src/room}/participant/RemoteParticipant.d.ts +3 -2
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -0
- package/dist/{room → src/room}/participant/publishUtils.d.ts +0 -0
- package/dist/src/room/participant/publishUtils.d.ts.map +1 -0
- package/dist/{room → src/room}/stats.d.ts +1 -0
- package/dist/src/room/stats.d.ts.map +1 -0
- package/dist/{room → src/room}/track/LocalAudioTrack.d.ts +0 -0
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -0
- package/dist/{room → src/room}/track/LocalTrack.d.ts +3 -0
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -0
- package/dist/{room → src/room}/track/LocalTrackPublication.d.ts +0 -0
- package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -0
- package/dist/{room → src/room}/track/LocalVideoTrack.d.ts +17 -2
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -0
- package/dist/{room → src/room}/track/RemoteAudioTrack.d.ts +0 -0
- package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -0
- package/dist/{room → src/room}/track/RemoteTrack.d.ts +0 -1
- package/dist/src/room/track/RemoteTrack.d.ts.map +1 -0
- package/dist/{room → src/room}/track/RemoteTrackPublication.d.ts +0 -0
- package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -0
- package/dist/{room → src/room}/track/RemoteVideoTrack.d.ts +25 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -0
- package/dist/{room → src/room}/track/Track.d.ts +6 -1
- package/dist/src/room/track/Track.d.ts.map +1 -0
- package/dist/{room → src/room}/track/TrackPublication.d.ts +0 -0
- package/dist/src/room/track/TrackPublication.d.ts.map +1 -0
- package/dist/{room → src/room}/track/create.d.ts +0 -0
- package/dist/src/room/track/create.d.ts.map +1 -0
- package/dist/{room → src/room}/track/defaults.d.ts +0 -0
- package/dist/src/room/track/defaults.d.ts.map +1 -0
- package/dist/{room → src/room}/track/options.d.ts +2 -31
- package/dist/src/room/track/options.d.ts.map +1 -0
- package/dist/{room → src/room}/track/types.d.ts +5 -0
- package/dist/src/room/track/types.d.ts.map +1 -0
- package/dist/{room → src/room}/track/utils.d.ts +0 -0
- package/dist/src/room/track/utils.d.ts.map +1 -0
- package/dist/{room → src/room}/utils.d.ts +0 -0
- package/dist/src/room/utils.d.ts.map +1 -0
- package/dist/src/test/MockMediaStreamTrack.d.ts +26 -0
- package/dist/src/test/MockMediaStreamTrack.d.ts.map +1 -0
- package/dist/{test → src/test}/mocks.d.ts +0 -0
- package/dist/src/test/mocks.d.ts.map +1 -0
- package/dist/src/version.d.ts +3 -0
- package/dist/src/version.d.ts.map +1 -0
- package/package.json +6 -2
- package/src/api/SignalClient.ts +34 -9
- package/src/index.ts +4 -3
- package/src/options.ts +0 -82
- package/src/proto/livekit_models.ts +90 -0
- package/src/proto/livekit_rtc.ts +235 -1
- package/src/room/DeviceManager.ts +4 -1
- package/src/room/RTCEngine.ts +46 -9
- package/src/room/Room.ts +122 -53
- package/src/room/events.ts +12 -14
- package/src/room/participant/LocalParticipant.ts +108 -23
- package/src/room/participant/Participant.ts +0 -5
- package/src/room/participant/RemoteParticipant.ts +17 -5
- package/src/room/participant/publishUtils.test.ts +2 -2
- package/src/room/stats.ts +2 -0
- package/src/room/track/LocalAudioTrack.ts +4 -0
- package/src/room/track/LocalTrack.ts +12 -5
- package/src/room/track/LocalVideoTrack.ts +144 -56
- package/src/room/track/RemoteTrack.ts +0 -2
- package/src/room/track/RemoteVideoTrack.test.ts +149 -0
- package/src/room/track/RemoteVideoTrack.ts +118 -37
- package/src/room/track/Track.ts +23 -2
- package/src/room/track/create.ts +1 -1
- package/src/room/track/options.ts +2 -31
- package/src/room/track/types.ts +5 -0
- package/src/room/track/utils.test.ts +6 -6
- package/src/test/MockMediaStreamTrack.ts +83 -0
- package/src/version.ts +4 -2
- package/dist/api/RequestQueue.d.ts.map +0 -1
- package/dist/api/SignalClient.d.ts.map +0 -1
- package/dist/connect.d.ts +0 -24
- package/dist/connect.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/options.d.ts +0 -128
- package/dist/options.d.ts.map +0 -1
- package/dist/proto/google/protobuf/timestamp.d.ts.map +0 -1
- package/dist/proto/livekit_models.d.ts.map +0 -1
- package/dist/proto/livekit_rtc.d.ts.map +0 -1
- package/dist/room/DeviceManager.d.ts.map +0 -1
- package/dist/room/PCTransport.d.ts.map +0 -1
- package/dist/room/RTCEngine.d.ts.map +0 -1
- package/dist/room/Room.d.ts.map +0 -1
- package/dist/room/errors.d.ts.map +0 -1
- package/dist/room/events.d.ts.map +0 -1
- package/dist/room/participant/LocalParticipant.d.ts.map +0 -1
- package/dist/room/participant/Participant.d.ts.map +0 -1
- package/dist/room/participant/ParticipantTrackPermission.d.ts.map +0 -1
- package/dist/room/participant/RemoteParticipant.d.ts.map +0 -1
- package/dist/room/participant/publishUtils.d.ts.map +0 -1
- package/dist/room/stats.d.ts.map +0 -1
- package/dist/room/track/LocalAudioTrack.d.ts.map +0 -1
- package/dist/room/track/LocalTrack.d.ts.map +0 -1
- package/dist/room/track/LocalTrackPublication.d.ts.map +0 -1
- package/dist/room/track/LocalVideoTrack.d.ts.map +0 -1
- package/dist/room/track/RemoteAudioTrack.d.ts.map +0 -1
- package/dist/room/track/RemoteTrack.d.ts.map +0 -1
- package/dist/room/track/RemoteTrackPublication.d.ts.map +0 -1
- package/dist/room/track/RemoteVideoTrack.d.ts.map +0 -1
- package/dist/room/track/Track.d.ts.map +0 -1
- package/dist/room/track/TrackPublication.d.ts.map +0 -1
- package/dist/room/track/create.d.ts.map +0 -1
- package/dist/room/track/defaults.d.ts.map +0 -1
- package/dist/room/track/options.d.ts.map +0 -1
- package/dist/room/track/types.d.ts.map +0 -1
- package/dist/room/track/utils.d.ts.map +0 -1
- package/dist/room/utils.d.ts.map +0 -1
- package/dist/test/mocks.d.ts.map +0 -1
- package/dist/version.d.ts +0 -3
- package/dist/version.d.ts.map +0 -1
- package/src/connect.ts +0 -98
@@ -10,12 +10,15 @@ import {
|
|
10
10
|
TrackUnpublishedResponse,
|
11
11
|
} from '../../proto/livekit_rtc';
|
12
12
|
import { TrackInvalidError, UnexpectedConnectionState } from '../errors';
|
13
|
-
import { ParticipantEvent, TrackEvent } from '../events';
|
13
|
+
import { EngineEvent, ParticipantEvent, TrackEvent } from '../events';
|
14
14
|
import RTCEngine from '../RTCEngine';
|
15
15
|
import LocalAudioTrack from '../track/LocalAudioTrack';
|
16
16
|
import LocalTrack from '../track/LocalTrack';
|
17
17
|
import LocalTrackPublication from '../track/LocalTrackPublication';
|
18
|
-
import LocalVideoTrack, {
|
18
|
+
import LocalVideoTrack, {
|
19
|
+
SimulcastTrackInfo,
|
20
|
+
videoLayersFromEncodings,
|
21
|
+
} from '../track/LocalVideoTrack';
|
19
22
|
import {
|
20
23
|
CreateLocalTracksOptions,
|
21
24
|
ScreenShareCaptureOptions,
|
@@ -31,6 +34,7 @@ import { ParticipantTrackPermission, trackPermissionToProto } from './Participan
|
|
31
34
|
import { computeVideoEncodings, mediaTrackToLocalTrack } from './publishUtils';
|
32
35
|
import RemoteParticipant from './RemoteParticipant';
|
33
36
|
|
37
|
+
const compatibleCodecForSVC = 'vp8';
|
34
38
|
export default class LocalParticipant extends Participant {
|
35
39
|
audioTracks: Map<string, LocalTrackPublication>;
|
36
40
|
|
@@ -47,6 +51,10 @@ export default class LocalParticipant extends Participant {
|
|
47
51
|
|
48
52
|
private engine: RTCEngine;
|
49
53
|
|
54
|
+
private participantTrackPermissions: Array<ParticipantTrackPermission> = [];
|
55
|
+
|
56
|
+
private allParticipantsAllowedToSubscribe: boolean = true;
|
57
|
+
|
50
58
|
// keep a pointer to room options
|
51
59
|
private roomOptions?: RoomOptions;
|
52
60
|
|
@@ -74,6 +82,11 @@ export default class LocalParticipant extends Participant {
|
|
74
82
|
this.engine.client.onSubscribedQualityUpdate = this.handleSubscribedQualityUpdate;
|
75
83
|
|
76
84
|
this.engine.client.onLocalTrackUnpublished = this.handleLocalTrackUnpublished;
|
85
|
+
|
86
|
+
this.engine
|
87
|
+
.on(EngineEvent.Connected, this.updateTrackSubscriptionPermissions)
|
88
|
+
.on(EngineEvent.Restarted, this.updateTrackSubscriptionPermissions)
|
89
|
+
.on(EngineEvent.Resumed, this.updateTrackSubscriptionPermissions);
|
77
90
|
}
|
78
91
|
|
79
92
|
get lastCameraError(): Error | undefined {
|
@@ -384,7 +397,7 @@ export default class LocalParticipant extends Participant {
|
|
384
397
|
// handle track actions
|
385
398
|
track.on(TrackEvent.Muted, this.onTrackMuted);
|
386
399
|
track.on(TrackEvent.Unmuted, this.onTrackUnmuted);
|
387
|
-
track.on(TrackEvent.Ended, this.
|
400
|
+
track.on(TrackEvent.Ended, this.handleTrackEnded);
|
388
401
|
track.on(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
|
389
402
|
track.on(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed);
|
390
403
|
|
@@ -401,6 +414,8 @@ export default class LocalParticipant extends Participant {
|
|
401
414
|
|
402
415
|
// compute encodings and layers for video
|
403
416
|
let encodings: RTCRtpEncodingParameters[] | undefined;
|
417
|
+
let simEncodings: RTCRtpEncodingParameters[] | undefined;
|
418
|
+
let simulcastTracks: SimulcastTrackInfo[] | undefined;
|
404
419
|
if (track.kind === Track.Kind.Video) {
|
405
420
|
// TODO: support react native, which doesn't expose getSettings
|
406
421
|
const settings = track.mediaStreamTrack.getSettings();
|
@@ -409,16 +424,38 @@ export default class LocalParticipant extends Participant {
|
|
409
424
|
// width and height should be defined for video
|
410
425
|
req.width = width ?? 0;
|
411
426
|
req.height = height ?? 0;
|
412
|
-
// for svc codecs, disable simulcast and
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
}
|
427
|
+
// for svc codecs, disable simulcast and use vp8 for backup codec
|
428
|
+
if (
|
429
|
+
track instanceof LocalVideoTrack &&
|
430
|
+
(opts?.videoCodec === 'vp9' || opts?.videoCodec === 'av1')
|
431
|
+
) {
|
432
|
+
// set scalabilityMode to 'L3T3' by default
|
433
|
+
opts.scalabilityMode = opts.scalabilityMode ?? 'L3T3';
|
434
|
+
|
435
|
+
// add backup codec track
|
436
|
+
const simOpts = { ...opts };
|
437
|
+
simOpts.simulcast = true;
|
438
|
+
simOpts.scalabilityMode = undefined;
|
439
|
+
simEncodings = computeVideoEncodings(
|
440
|
+
track.source === Track.Source.ScreenShare,
|
441
|
+
width,
|
442
|
+
height,
|
443
|
+
simOpts,
|
444
|
+
);
|
445
|
+
const simulcastTrack = track.addSimulcastTrack(compatibleCodecForSVC, simEncodings);
|
446
|
+
simulcastTracks = [simulcastTrack];
|
447
|
+
req.simulcastCodecs = [
|
448
|
+
{
|
449
|
+
codec: opts.videoCodec,
|
450
|
+
cid: track.mediaStreamTrack.id,
|
451
|
+
enableSimulcastLayers: true,
|
452
|
+
},
|
453
|
+
{
|
454
|
+
codec: simulcastTrack.codec,
|
455
|
+
cid: simulcastTrack.mediaStreamTrack.id,
|
456
|
+
enableSimulcastLayers: true,
|
457
|
+
},
|
458
|
+
];
|
422
459
|
}
|
423
460
|
|
424
461
|
encodings = computeVideoEncodings(
|
@@ -427,7 +464,7 @@ export default class LocalParticipant extends Participant {
|
|
427
464
|
height,
|
428
465
|
opts,
|
429
466
|
);
|
430
|
-
req.layers = videoLayersFromEncodings(req.width, req.height, encodings);
|
467
|
+
req.layers = videoLayersFromEncodings(req.width, req.height, simEncodings ?? encodings);
|
431
468
|
} else if (track.kind === Track.Kind.Audio && opts.audioBitrate) {
|
432
469
|
encodings = [
|
433
470
|
{
|
@@ -436,8 +473,14 @@ export default class LocalParticipant extends Participant {
|
|
436
473
|
];
|
437
474
|
}
|
438
475
|
|
476
|
+
if (!this.engine || this.engine.isClosed) {
|
477
|
+
throw new UnexpectedConnectionState('cannot publish track when not connected');
|
478
|
+
}
|
479
|
+
|
439
480
|
const ti = await this.engine.addTrack(req);
|
440
481
|
const publication = new LocalTrackPublication(track.kind, ti, track);
|
482
|
+
// save options for when it needs to be republished again
|
483
|
+
publication.options = opts;
|
441
484
|
track.sid = ti.sid;
|
442
485
|
|
443
486
|
if (!this.engine.publisher) {
|
@@ -448,13 +491,32 @@ export default class LocalParticipant extends Participant {
|
|
448
491
|
if (encodings) {
|
449
492
|
transceiverInit.sendEncodings = encodings;
|
450
493
|
}
|
451
|
-
|
494
|
+
// addTransceiver for react-native is async. web is synchronous, but await won't effect it.
|
495
|
+
const transceiver = await this.engine.publisher.pc.addTransceiver(
|
452
496
|
track.mediaStreamTrack,
|
453
497
|
transceiverInit,
|
454
498
|
);
|
455
|
-
if (opts.videoCodec) {
|
499
|
+
if (track.kind === Track.Kind.Video && opts.videoCodec) {
|
456
500
|
this.setPreferredCodec(transceiver, track.kind, opts.videoCodec);
|
501
|
+
track.codec = opts.videoCodec;
|
502
|
+
}
|
503
|
+
|
504
|
+
const localTrack = track as LocalVideoTrack;
|
505
|
+
if (simulcastTracks) {
|
506
|
+
for await (const simulcastTrack of simulcastTracks) {
|
507
|
+
const simTransceiverInit: RTCRtpTransceiverInit = { direction: 'sendonly' };
|
508
|
+
if (simulcastTrack.encodings) {
|
509
|
+
simTransceiverInit.sendEncodings = simulcastTrack.encodings;
|
510
|
+
}
|
511
|
+
const simTransceiver = await this.engine.publisher!.pc.addTransceiver(
|
512
|
+
simulcastTrack.mediaStreamTrack,
|
513
|
+
simTransceiverInit,
|
514
|
+
);
|
515
|
+
this.setPreferredCodec(simTransceiver, localTrack.kind, simulcastTrack.codec);
|
516
|
+
localTrack.setSimulcastTrackSender(simulcastTrack.codec, simTransceiver.sender);
|
517
|
+
}
|
457
518
|
}
|
519
|
+
|
458
520
|
this.engine.negotiate();
|
459
521
|
|
460
522
|
// store RTPSender
|
@@ -464,6 +526,7 @@ export default class LocalParticipant extends Participant {
|
|
464
526
|
} else if (track instanceof LocalAudioTrack) {
|
465
527
|
track.startMonitor();
|
466
528
|
}
|
529
|
+
|
467
530
|
this.addTrackPublication(publication);
|
468
531
|
|
469
532
|
// send event for publication
|
@@ -490,9 +553,10 @@ export default class LocalParticipant extends Participant {
|
|
490
553
|
|
491
554
|
track = publication.track;
|
492
555
|
|
556
|
+
track.sender = undefined;
|
493
557
|
track.off(TrackEvent.Muted, this.onTrackMuted);
|
494
558
|
track.off(TrackEvent.Unmuted, this.onTrackUnmuted);
|
495
|
-
track.off(TrackEvent.Ended, this.
|
559
|
+
track.off(TrackEvent.Ended, this.handleTrackEnded);
|
496
560
|
track.off(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
|
497
561
|
track.off(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed);
|
498
562
|
|
@@ -505,7 +569,7 @@ export default class LocalParticipant extends Participant {
|
|
505
569
|
|
506
570
|
const { mediaStreamTrack } = track;
|
507
571
|
|
508
|
-
if (this.engine.publisher) {
|
572
|
+
if (this.engine.publisher && this.engine.publisher.pc.connectionState !== 'closed') {
|
509
573
|
const senders = this.engine.publisher.pc.getSenders();
|
510
574
|
senders.forEach((sender) => {
|
511
575
|
if (sender.track === mediaStreamTrack) {
|
@@ -609,11 +673,23 @@ export default class LocalParticipant extends Participant {
|
|
609
673
|
allParticipantsAllowed: boolean,
|
610
674
|
participantTrackPermissions: ParticipantTrackPermission[] = [],
|
611
675
|
) {
|
676
|
+
this.participantTrackPermissions = participantTrackPermissions;
|
677
|
+
this.allParticipantsAllowedToSubscribe = allParticipantsAllowed;
|
678
|
+
if (this.engine.client.isConnected) {
|
679
|
+
this.updateTrackSubscriptionPermissions();
|
680
|
+
}
|
681
|
+
}
|
682
|
+
|
683
|
+
private updateTrackSubscriptionPermissions = () => {
|
684
|
+
log.debug('updating track subscription permissions', {
|
685
|
+
allParticipantsAllowed: this.allParticipantsAllowedToSubscribe,
|
686
|
+
participantTrackPermissions: this.participantTrackPermissions,
|
687
|
+
});
|
612
688
|
this.engine.client.sendUpdateSubscriptionPermissions(
|
613
|
-
|
614
|
-
participantTrackPermissions.map((p) => trackPermissionToProto(p)),
|
689
|
+
this.allParticipantsAllowedToSubscribe,
|
690
|
+
this.participantTrackPermissions.map((p) => trackPermissionToProto(p)),
|
615
691
|
);
|
616
|
-
}
|
692
|
+
};
|
617
693
|
|
618
694
|
/** @internal */
|
619
695
|
private onTrackUnmuted = (track: LocalTrack) => {
|
@@ -657,7 +733,11 @@ export default class LocalParticipant extends Participant {
|
|
657
733
|
});
|
658
734
|
return;
|
659
735
|
}
|
660
|
-
|
736
|
+
if (update.subscribedCodecs.length > 0) {
|
737
|
+
pub.videoTrack?.setPublishingCodecs(update.subscribedCodecs);
|
738
|
+
} else if (update.subscribedQualities.length > 0) {
|
739
|
+
pub.videoTrack?.setPublishingLayers(update.subscribedQualities);
|
740
|
+
}
|
661
741
|
};
|
662
742
|
|
663
743
|
private handleLocalTrackUnpublished = (unpublished: TrackUnpublishedResponse) => {
|
@@ -672,7 +752,10 @@ export default class LocalParticipant extends Participant {
|
|
672
752
|
this.unpublishTrack(track.track!);
|
673
753
|
};
|
674
754
|
|
675
|
-
private
|
755
|
+
private handleTrackEnded = (track: LocalTrack) => {
|
756
|
+
log.debug('unpublishing local track due to TrackEnded', {
|
757
|
+
track: track.sid,
|
758
|
+
});
|
676
759
|
this.unpublishTrack(track);
|
677
760
|
};
|
678
761
|
|
@@ -710,6 +793,7 @@ export default class LocalParticipant extends Participant {
|
|
710
793
|
}
|
711
794
|
const cap = RTCRtpSender.getCapabilities(kind);
|
712
795
|
if (!cap) return;
|
796
|
+
log.debug('get capabilities', cap);
|
713
797
|
let selected: RTCRtpCodecCapability | undefined;
|
714
798
|
const codecs: RTCRtpCodecCapability[] = [];
|
715
799
|
cap.codecs.forEach((c) => {
|
@@ -734,6 +818,7 @@ export default class LocalParticipant extends Participant {
|
|
734
818
|
}
|
735
819
|
codecs.push(c);
|
736
820
|
});
|
821
|
+
|
737
822
|
if (selected && 'setCodecPreferences' in transceiver) {
|
738
823
|
// @ts-ignore
|
739
824
|
codecs.unshift(selected);
|
@@ -188,7 +188,6 @@ export default class Participant extends (EventEmitter as new () => TypedEmitter
|
|
188
188
|
this.metadata = md;
|
189
189
|
|
190
190
|
if (changed) {
|
191
|
-
this.emit(ParticipantEvent.MetadataChanged, prevMetadata);
|
192
191
|
this.emit(ParticipantEvent.ParticipantMetadataChanged, prevMetadata);
|
193
192
|
}
|
194
193
|
}
|
@@ -266,10 +265,6 @@ export type ParticipantEventCallbacks = {
|
|
266
265
|
trackUnmuted: (publication: TrackPublication) => void;
|
267
266
|
localTrackPublished: (publication: LocalTrackPublication) => void;
|
268
267
|
localTrackUnpublished: (publication: LocalTrackPublication) => void;
|
269
|
-
/**
|
270
|
-
* @deprecated use [[participantMetadataChanged]] instead
|
271
|
-
*/
|
272
|
-
metadataChanged: (prevMetadata: string | undefined, participant?: any) => void;
|
273
268
|
participantMetadataChanged: (prevMetadata: string | undefined, participant?: any) => void;
|
274
269
|
dataReceived: (payload: Uint8Array, kind: DataPacket_Kind) => void;
|
275
270
|
isSpeakingChanged: (speaking: boolean) => void;
|
@@ -19,6 +19,8 @@ export default class RemoteParticipant extends Participant {
|
|
19
19
|
|
20
20
|
signalClient: SignalClient;
|
21
21
|
|
22
|
+
private volume?: number;
|
23
|
+
|
22
24
|
/** @internal */
|
23
25
|
static fromParticipantInfo(signalClient: SignalClient, pi: ParticipantInfo): RemoteParticipant {
|
24
26
|
const rp = new RemoteParticipant(signalClient, pi.sid, pi.identity);
|
@@ -40,6 +42,7 @@ export default class RemoteParticipant extends Participant {
|
|
40
42
|
|
41
43
|
// register action events
|
42
44
|
publication.on(TrackEvent.UpdateSettings, (settings: UpdateTrackSettings) => {
|
45
|
+
log.debug('send update settings', settings);
|
43
46
|
this.signalClient.sendUpdateTrackSettings(settings);
|
44
47
|
});
|
45
48
|
publication.on(TrackEvent.UpdateSubscription, (sub: UpdateSubscription) => {
|
@@ -68,24 +71,26 @@ export default class RemoteParticipant extends Participant {
|
|
68
71
|
}
|
69
72
|
|
70
73
|
/**
|
71
|
-
* sets the volume on the participant's microphone track
|
74
|
+
* sets the volume on the participant's microphone track
|
75
|
+
* if no track exists the volume will be applied when the microphone track is added
|
72
76
|
*/
|
73
77
|
setVolume(volume: number) {
|
78
|
+
this.volume = volume;
|
74
79
|
const audioPublication = this.getTrack(Track.Source.Microphone);
|
75
|
-
if (audioPublication) {
|
80
|
+
if (audioPublication && audioPublication.track) {
|
76
81
|
(audioPublication.track as RemoteAudioTrack).setVolume(volume);
|
77
82
|
}
|
78
83
|
}
|
79
84
|
|
80
85
|
/**
|
81
86
|
* gets the volume on the participant's microphone track
|
82
|
-
* returns undefined if no microphone track exists
|
83
87
|
*/
|
84
88
|
getVolume() {
|
85
89
|
const audioPublication = this.getTrack(Track.Source.Microphone);
|
86
|
-
if (audioPublication) {
|
90
|
+
if (audioPublication && audioPublication.track) {
|
87
91
|
return (audioPublication.track as RemoteAudioTrack).getVolume();
|
88
92
|
}
|
93
|
+
return this.volume;
|
89
94
|
}
|
90
95
|
|
91
96
|
/** @internal */
|
@@ -153,7 +158,14 @@ export default class RemoteParticipant extends Participant {
|
|
153
158
|
track.start();
|
154
159
|
|
155
160
|
publication.setTrack(track);
|
156
|
-
|
161
|
+
// set participant volume on new microphone tracks
|
162
|
+
if (
|
163
|
+
this.volume !== undefined &&
|
164
|
+
track instanceof RemoteAudioTrack &&
|
165
|
+
track.source === Track.Source.Microphone
|
166
|
+
) {
|
167
|
+
track.setVolume(this.volume);
|
168
|
+
}
|
157
169
|
this.emit(ParticipantEvent.TrackSubscribed, track, publication);
|
158
170
|
|
159
171
|
return publication;
|
@@ -28,11 +28,11 @@ describe('presetsForResolution', () => {
|
|
28
28
|
|
29
29
|
describe('determineAppropriateEncoding', () => {
|
30
30
|
it('uses higher encoding', () => {
|
31
|
-
expect(determineAppropriateEncoding(false, 600, 300)).toEqual(VideoPresets.
|
31
|
+
expect(determineAppropriateEncoding(false, 600, 300)).toEqual(VideoPresets.h360.encoding);
|
32
32
|
});
|
33
33
|
|
34
34
|
it('handles portrait', () => {
|
35
|
-
expect(determineAppropriateEncoding(false, 300, 600)).toEqual(VideoPresets.
|
35
|
+
expect(determineAppropriateEncoding(false, 300, 600)).toEqual(VideoPresets.h360.encoding);
|
36
36
|
});
|
37
37
|
});
|
38
38
|
|
package/src/room/stats.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import log from '../../logger';
|
2
2
|
import { TrackEvent } from '../events';
|
3
3
|
import { AudioSenderStats, computeBitrate, monitorFrequency } from '../stats';
|
4
|
+
import { isWeb } from '../utils';
|
4
5
|
import LocalTrack from './LocalTrack';
|
5
6
|
import { AudioCaptureOptions } from './options';
|
6
7
|
import { Track } from './Track';
|
@@ -68,6 +69,9 @@ export default class LocalAudioTrack extends LocalTrack {
|
|
68
69
|
|
69
70
|
/* @internal */
|
70
71
|
startMonitor() {
|
72
|
+
if (!isWeb()) {
|
73
|
+
return;
|
74
|
+
}
|
71
75
|
setTimeout(() => {
|
72
76
|
this.monitorSender();
|
73
77
|
}, monitorFrequency);
|
@@ -2,6 +2,7 @@ import log from '../../logger';
|
|
2
2
|
import DeviceManager from '../DeviceManager';
|
3
3
|
import { TrackInvalidError } from '../errors';
|
4
4
|
import { TrackEvent } from '../events';
|
5
|
+
import { VideoCodec } from './options';
|
5
6
|
import { getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, isMobile } from '../utils';
|
6
7
|
import { attachToElement, detachTrack, Track } from './Track';
|
7
8
|
|
@@ -9,6 +10,9 @@ export default class LocalTrack extends Track {
|
|
9
10
|
/** @internal */
|
10
11
|
sender?: RTCRtpSender;
|
11
12
|
|
13
|
+
/** @internal */
|
14
|
+
codec?: VideoCodec;
|
15
|
+
|
12
16
|
protected constraints: MediaTrackConstraints;
|
13
17
|
|
14
18
|
protected wasMuted: boolean;
|
@@ -94,7 +98,9 @@ export default class LocalTrack extends Track {
|
|
94
98
|
track.addEventListener('ended', this.handleEnded);
|
95
99
|
log.debug('replace MediaStreamTrack');
|
96
100
|
|
97
|
-
|
101
|
+
if (this.sender) {
|
102
|
+
await this.sender.replaceTrack(track);
|
103
|
+
}
|
98
104
|
this._mediaStreamTrack = track;
|
99
105
|
|
100
106
|
this.attachedElements.forEach((el) => {
|
@@ -106,9 +112,6 @@ export default class LocalTrack extends Track {
|
|
106
112
|
}
|
107
113
|
|
108
114
|
protected async restart(constraints?: MediaTrackConstraints): Promise<LocalTrack> {
|
109
|
-
if (!this.sender) {
|
110
|
-
throw new TrackInvalidError('unable to restart an unpublished track');
|
111
|
-
}
|
112
115
|
if (!constraints) {
|
113
116
|
constraints = this.constraints;
|
114
117
|
}
|
@@ -141,7 +144,11 @@ export default class LocalTrack extends Track {
|
|
141
144
|
newTrack.addEventListener('ended', this.handleEnded);
|
142
145
|
log.debug('re-acquired MediaStreamTrack');
|
143
146
|
|
144
|
-
|
147
|
+
if (this.sender) {
|
148
|
+
// Track can be restarted after it's unpublished
|
149
|
+
await this.sender.replaceTrack(newTrack);
|
150
|
+
}
|
151
|
+
|
145
152
|
this._mediaStreamTrack = newTrack;
|
146
153
|
|
147
154
|
this.attachedElements.forEach((el) => {
|