livekit-client 0.18.4 → 0.18.5
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/dist/livekit-client.esm.mjs +130 -46
- 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/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/room/participant/publishUtils.d.ts.map +1 -1
- package/dist/room/track/RemoteVideoTrack.d.ts +1 -0
- package/dist/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/room/track/Track.d.ts +7 -3
- package/dist/room/track/Track.d.ts.map +1 -1
- package/dist/room/track/defaults.d.ts.map +1 -1
- package/dist/room/track/options.d.ts +9 -0
- package/dist/room/track/options.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/room/participant/LocalParticipant.ts +33 -9
- package/src/room/participant/publishUtils.ts +34 -5
- package/src/room/track/LocalAudioTrack.ts +2 -2
- package/src/room/track/LocalTrack.ts +17 -17
- package/src/room/track/LocalVideoTrack.ts +3 -3
- package/src/room/track/RemoteVideoTrack.ts +11 -2
- package/src/room/track/Track.ts +20 -13
- package/src/room/track/defaults.ts +1 -2
- package/src/room/track/options.ts +11 -0
- package/src/version.ts +1 -1
@@ -9783,7 +9783,7 @@ class DeviceManager {
|
|
9783
9783
|
}
|
9784
9784
|
DeviceManager.mediaDeviceKinds = ['audioinput', 'audiooutput', 'videoinput'];
|
9785
9785
|
|
9786
|
-
const version = '0.18.
|
9786
|
+
const version = '0.18.5';
|
9787
9787
|
const protocolVersion = 7;
|
9788
9788
|
|
9789
9789
|
const separator = '|';
|
@@ -10351,7 +10351,7 @@ class Track extends events.exports.EventEmitter {
|
|
10351
10351
|
};
|
10352
10352
|
|
10353
10353
|
this.kind = kind;
|
10354
|
-
this.
|
10354
|
+
this._mediaStreamTrack = mediaTrack;
|
10355
10355
|
this.source = Track.Source.Unknown;
|
10356
10356
|
|
10357
10357
|
if (isWeb()) {
|
@@ -10368,6 +10368,10 @@ class Track extends events.exports.EventEmitter {
|
|
10368
10368
|
return this._currentBitrate;
|
10369
10369
|
}
|
10370
10370
|
|
10371
|
+
get mediaStreamTrack() {
|
10372
|
+
return this._mediaStreamTrack;
|
10373
|
+
}
|
10374
|
+
|
10371
10375
|
attach(element) {
|
10372
10376
|
let elementType = 'audio';
|
10373
10377
|
|
@@ -10401,7 +10405,7 @@ class Track extends events.exports.EventEmitter {
|
|
10401
10405
|
// we'll want to re-attach it in that case
|
10402
10406
|
|
10403
10407
|
|
10404
|
-
attachToElement(this.
|
10408
|
+
attachToElement(this._mediaStreamTrack, element);
|
10405
10409
|
|
10406
10410
|
if (element instanceof HTMLAudioElement) {
|
10407
10411
|
// manually play audio to detect audio playback status
|
@@ -10419,7 +10423,7 @@ class Track extends events.exports.EventEmitter {
|
|
10419
10423
|
detach(element) {
|
10420
10424
|
// detach from a single element
|
10421
10425
|
if (element) {
|
10422
|
-
detachTrack(this.
|
10426
|
+
detachTrack(this._mediaStreamTrack, element);
|
10423
10427
|
const idx = this.attachedElements.indexOf(element);
|
10424
10428
|
|
10425
10429
|
if (idx >= 0) {
|
@@ -10433,7 +10437,7 @@ class Track extends events.exports.EventEmitter {
|
|
10433
10437
|
|
10434
10438
|
const detached = [];
|
10435
10439
|
this.attachedElements.forEach(elm => {
|
10436
|
-
detachTrack(this.
|
10440
|
+
detachTrack(this._mediaStreamTrack, elm);
|
10437
10441
|
detached.push(elm);
|
10438
10442
|
this.recycleElement(elm);
|
10439
10443
|
this.emit(TrackEvent.ElementDetached, elm);
|
@@ -10444,7 +10448,7 @@ class Track extends events.exports.EventEmitter {
|
|
10444
10448
|
}
|
10445
10449
|
|
10446
10450
|
stop() {
|
10447
|
-
this.
|
10451
|
+
this._mediaStreamTrack.stop();
|
10448
10452
|
|
10449
10453
|
if (isWeb()) {
|
10450
10454
|
document.removeEventListener('visibilitychange', this.appVisibilityChangedListener);
|
@@ -10452,11 +10456,11 @@ class Track extends events.exports.EventEmitter {
|
|
10452
10456
|
}
|
10453
10457
|
|
10454
10458
|
enable() {
|
10455
|
-
this.
|
10459
|
+
this._mediaStreamTrack.enabled = true;
|
10456
10460
|
}
|
10457
10461
|
|
10458
10462
|
disable() {
|
10459
|
-
this.
|
10463
|
+
this._mediaStreamTrack.enabled = false;
|
10460
10464
|
}
|
10461
10465
|
|
10462
10466
|
recycleElement(element) {
|
@@ -10686,14 +10690,15 @@ class LocalTrack extends Track {
|
|
10686
10690
|
this.emit(TrackEvent.Ended, this);
|
10687
10691
|
};
|
10688
10692
|
|
10689
|
-
this.
|
10693
|
+
this._mediaStreamTrack.addEventListener('ended', this.handleEnded);
|
10694
|
+
|
10690
10695
|
this.constraints = constraints !== null && constraints !== void 0 ? constraints : mediaTrack.getConstraints();
|
10691
10696
|
this.reacquireTrack = false;
|
10692
10697
|
this.wasMuted = false;
|
10693
10698
|
}
|
10694
10699
|
|
10695
10700
|
get id() {
|
10696
|
-
return this.
|
10701
|
+
return this._mediaStreamTrack.id;
|
10697
10702
|
}
|
10698
10703
|
|
10699
10704
|
get dimensions() {
|
@@ -10704,7 +10709,7 @@ class LocalTrack extends Track {
|
|
10704
10709
|
const {
|
10705
10710
|
width,
|
10706
10711
|
height
|
10707
|
-
} = this.
|
10712
|
+
} = this._mediaStreamTrack.getSettings();
|
10708
10713
|
|
10709
10714
|
if (width && height) {
|
10710
10715
|
return {
|
@@ -10733,7 +10738,8 @@ class LocalTrack extends Track {
|
|
10733
10738
|
const {
|
10734
10739
|
deviceId,
|
10735
10740
|
groupId
|
10736
|
-
} = this.
|
10741
|
+
} = this._mediaStreamTrack.getSettings();
|
10742
|
+
|
10737
10743
|
const kind = this.kind === Track.Kind.Audio ? 'audioinput' : 'videoinput';
|
10738
10744
|
return DeviceManager.getInstance().normalizeDeviceId(kind, deviceId, groupId);
|
10739
10745
|
}
|
@@ -10755,17 +10761,20 @@ class LocalTrack extends Track {
|
|
10755
10761
|
|
10756
10762
|
|
10757
10763
|
this.attachedElements.forEach(el => {
|
10758
|
-
detachTrack(this.
|
10764
|
+
detachTrack(this._mediaStreamTrack, el);
|
10759
10765
|
});
|
10760
|
-
|
10766
|
+
|
10767
|
+
this._mediaStreamTrack.removeEventListener('ended', this.handleEnded); // on Safari, the old audio track must be stopped before attempting to acquire
|
10761
10768
|
// the new track, otherwise the new track will stop with
|
10762
10769
|
// 'A MediaStreamTrack ended due to a capture failure`
|
10763
10770
|
|
10764
|
-
|
10771
|
+
|
10772
|
+
this._mediaStreamTrack.stop();
|
10773
|
+
|
10765
10774
|
track.addEventListener('ended', this.handleEnded);
|
10766
10775
|
livekitLogger.debug('replace MediaStreamTrack');
|
10767
10776
|
await this.sender.replaceTrack(track);
|
10768
|
-
this.
|
10777
|
+
this._mediaStreamTrack = track;
|
10769
10778
|
this.attachedElements.forEach(el => {
|
10770
10779
|
attachToElement(track, el);
|
10771
10780
|
});
|
@@ -10796,20 +10805,23 @@ class LocalTrack extends Track {
|
|
10796
10805
|
|
10797
10806
|
|
10798
10807
|
this.attachedElements.forEach(el => {
|
10799
|
-
detachTrack(this.
|
10808
|
+
detachTrack(this._mediaStreamTrack, el);
|
10800
10809
|
});
|
10801
|
-
|
10810
|
+
|
10811
|
+
this._mediaStreamTrack.removeEventListener('ended', this.handleEnded); // on Safari, the old audio track must be stopped before attempting to acquire
|
10802
10812
|
// the new track, otherwise the new track will stop with
|
10803
10813
|
// 'A MediaStreamTrack ended due to a capture failure`
|
10804
10814
|
|
10805
|
-
|
10815
|
+
|
10816
|
+
this._mediaStreamTrack.stop(); // create new track and attach
|
10817
|
+
|
10806
10818
|
|
10807
10819
|
const mediaStream = await navigator.mediaDevices.getUserMedia(streamConstraints);
|
10808
10820
|
const newTrack = mediaStream.getTracks()[0];
|
10809
10821
|
newTrack.addEventListener('ended', this.handleEnded);
|
10810
10822
|
livekitLogger.debug('re-acquired MediaStreamTrack');
|
10811
10823
|
await this.sender.replaceTrack(newTrack);
|
10812
|
-
this.
|
10824
|
+
this._mediaStreamTrack = newTrack;
|
10813
10825
|
this.attachedElements.forEach(el => {
|
10814
10826
|
attachToElement(newTrack, el);
|
10815
10827
|
});
|
@@ -10824,12 +10836,12 @@ class LocalTrack extends Track {
|
|
10824
10836
|
}
|
10825
10837
|
|
10826
10838
|
this.isMuted = muted;
|
10827
|
-
this.
|
10839
|
+
this._mediaStreamTrack.enabled = !muted;
|
10828
10840
|
this.emit(muted ? TrackEvent.Muted : TrackEvent.Unmuted, this);
|
10829
10841
|
}
|
10830
10842
|
|
10831
10843
|
get needsReAcquisition() {
|
10832
|
-
return this.
|
10844
|
+
return this._mediaStreamTrack.readyState !== 'live' || this._mediaStreamTrack.muted || !this._mediaStreamTrack.enabled || this.reacquireTrack;
|
10833
10845
|
}
|
10834
10846
|
|
10835
10847
|
async handleAppVisibilityChanged() {
|
@@ -10879,7 +10891,7 @@ class LocalTrack extends Track {
|
|
10879
10891
|
|
10880
10892
|
this._isUpstreamPaused = false;
|
10881
10893
|
this.emit(TrackEvent.UpstreamResumed, this);
|
10882
|
-
await this.sender.replaceTrack(this.
|
10894
|
+
await this.sender.replaceTrack(this._mediaStreamTrack);
|
10883
10895
|
}
|
10884
10896
|
|
10885
10897
|
}
|
@@ -11004,7 +11016,9 @@ class LocalAudioTrack extends LocalTrack {
|
|
11004
11016
|
try {
|
11005
11017
|
stats = await this.getSenderStats();
|
11006
11018
|
} catch (e) {
|
11007
|
-
livekitLogger.error('could not get audio sender stats',
|
11019
|
+
livekitLogger.error('could not get audio sender stats', {
|
11020
|
+
error: e
|
11021
|
+
});
|
11008
11022
|
return;
|
11009
11023
|
}
|
11010
11024
|
|
@@ -11038,7 +11052,7 @@ class LocalAudioTrack extends LocalTrack {
|
|
11038
11052
|
if (this.source === Track.Source.Microphone && this.stopOnMute) {
|
11039
11053
|
livekitLogger.debug('stopping mic track'); // also stop the track, so that microphone indicator is turned off
|
11040
11054
|
|
11041
|
-
this.
|
11055
|
+
this._mediaStreamTrack.stop();
|
11042
11056
|
}
|
11043
11057
|
|
11044
11058
|
await super.mute();
|
@@ -11192,7 +11206,9 @@ class LocalVideoTrack extends LocalTrack {
|
|
11192
11206
|
|
11193
11207
|
stop() {
|
11194
11208
|
this.sender = undefined;
|
11195
|
-
|
11209
|
+
|
11210
|
+
this._mediaStreamTrack.getConstraints();
|
11211
|
+
|
11196
11212
|
super.stop();
|
11197
11213
|
}
|
11198
11214
|
|
@@ -11200,7 +11216,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
11200
11216
|
if (this.source === Track.Source.Camera) {
|
11201
11217
|
livekitLogger.debug('stopping camera track'); // also stop the track, so that camera indicator is turned off
|
11202
11218
|
|
11203
|
-
this.
|
11219
|
+
this._mediaStreamTrack.stop();
|
11204
11220
|
}
|
11205
11221
|
|
11206
11222
|
await super.mute();
|
@@ -11381,7 +11397,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
11381
11397
|
if (!isMobile()) return;
|
11382
11398
|
|
11383
11399
|
if (this.isInBackground && this.source === Track.Source.Camera) {
|
11384
|
-
this.
|
11400
|
+
this._mediaStreamTrack.enabled = false;
|
11385
11401
|
}
|
11386
11402
|
}
|
11387
11403
|
|
@@ -11672,6 +11688,14 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
11672
11688
|
get isAdaptiveStream() {
|
11673
11689
|
return this.adaptiveStreamSettings !== undefined;
|
11674
11690
|
}
|
11691
|
+
|
11692
|
+
get mediaStreamTrack() {
|
11693
|
+
if (this.isAdaptiveStream && this.attachedElements.length === 0) {
|
11694
|
+
throw Error('When using adaptiveStream, you need to use remoteVideoTrack.attach() to add the track to a HTMLVideoElement, direct usage of mediaStreamTrack is unsupported in this case');
|
11695
|
+
}
|
11696
|
+
|
11697
|
+
return this._mediaStreamTrack;
|
11698
|
+
}
|
11675
11699
|
/** @internal */
|
11676
11700
|
|
11677
11701
|
|
@@ -11680,9 +11704,9 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
11680
11704
|
this.attachedElements.forEach(element => {
|
11681
11705
|
// detach or attach
|
11682
11706
|
if (muted) {
|
11683
|
-
detachTrack(this.
|
11707
|
+
detachTrack(this._mediaStreamTrack, element);
|
11684
11708
|
} else {
|
11685
|
-
attachToElement(this.
|
11709
|
+
attachToElement(this._mediaStreamTrack, element);
|
11686
11710
|
}
|
11687
11711
|
});
|
11688
11712
|
}
|
@@ -12432,9 +12456,10 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
12432
12456
|
}
|
12433
12457
|
|
12434
12458
|
const useSimulcast = options === null || options === void 0 ? void 0 : options.simulcast;
|
12459
|
+
const scalabilityMode = options === null || options === void 0 ? void 0 : options.scalabilityMode;
|
12435
12460
|
|
12436
|
-
if (!videoEncoding && !useSimulcast || !width || !height) {
|
12437
|
-
// when we aren't simulcasting, will need to return a single encoding without
|
12461
|
+
if (!videoEncoding && !useSimulcast && !scalabilityMode || !width || !height) {
|
12462
|
+
// when we aren't simulcasting or svc, will need to return a single encoding without
|
12438
12463
|
// capping bandwidth. we always require a encoding for dynacast
|
12439
12464
|
return [{}];
|
12440
12465
|
}
|
@@ -12445,11 +12470,41 @@ function computeVideoEncodings(isScreenShare, width, height, options) {
|
|
12445
12470
|
livekitLogger.debug('using video encoding', videoEncoding);
|
12446
12471
|
}
|
12447
12472
|
|
12473
|
+
const original = new VideoPreset(width, height, videoEncoding.maxBitrate, videoEncoding.maxFramerate);
|
12474
|
+
livekitLogger.debug("scalabilityMode ".concat(scalabilityMode));
|
12475
|
+
|
12476
|
+
if (scalabilityMode) {
|
12477
|
+
const encodings = []; // svc use first encoding as the original, so we sort encoding from high to low
|
12478
|
+
|
12479
|
+
switch (scalabilityMode) {
|
12480
|
+
case 'L3T3':
|
12481
|
+
for (let i = 0; i < 3; i += 1) {
|
12482
|
+
encodings.push({
|
12483
|
+
rid: videoRids[2 - i],
|
12484
|
+
scaleResolutionDownBy: 2 ** i,
|
12485
|
+
maxBitrate: videoEncoding ? videoEncoding.maxBitrate / 2 ** i : 0,
|
12486
|
+
|
12487
|
+
/* @ts-ignore */
|
12488
|
+
maxFramerate: original.encoding.maxFramerate,
|
12489
|
+
|
12490
|
+
/* @ts-ignore */
|
12491
|
+
scalabilityMode: 'L3T3'
|
12492
|
+
});
|
12493
|
+
}
|
12494
|
+
|
12495
|
+
livekitLogger.debug('encodings', encodings);
|
12496
|
+
return encodings;
|
12497
|
+
|
12498
|
+
default:
|
12499
|
+
// TODO : support other scalability modes
|
12500
|
+
throw new Error("unsupported scalabilityMode: ".concat(scalabilityMode));
|
12501
|
+
}
|
12502
|
+
}
|
12503
|
+
|
12448
12504
|
if (!useSimulcast) {
|
12449
12505
|
return [videoEncoding];
|
12450
12506
|
}
|
12451
12507
|
|
12452
|
-
const original = new VideoPreset(width, height, videoEncoding.maxBitrate, videoEncoding.maxFramerate);
|
12453
12508
|
let presets = [];
|
12454
12509
|
|
12455
12510
|
if (isScreenShare) {
|
@@ -13441,7 +13496,7 @@ class LocalParticipant extends Participant {
|
|
13441
13496
|
|
13442
13497
|
|
13443
13498
|
async publishTrack(track, options) {
|
13444
|
-
var _a, _b, _c, _d, _e, _f;
|
13499
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
13445
13500
|
|
13446
13501
|
const opts = _objectSpread2(_objectSpread2({}, (_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.publishDefaults), options); // convert raw media track into audio or video track
|
13447
13502
|
|
@@ -13514,7 +13569,19 @@ class LocalParticipant extends Participant {
|
|
13514
13569
|
const height = (_e = settings.height) !== null && _e !== void 0 ? _e : (_f = track.dimensions) === null || _f === void 0 ? void 0 : _f.height; // width and height should be defined for video
|
13515
13570
|
|
13516
13571
|
req.width = width !== null && width !== void 0 ? width : 0;
|
13517
|
-
req.height = height !== null && height !== void 0 ? height : 0;
|
13572
|
+
req.height = height !== null && height !== void 0 ? height : 0; // for svc codecs, disable simulcast and enable scalability L3T3
|
13573
|
+
// by default
|
13574
|
+
|
13575
|
+
if (track instanceof LocalVideoTrack) {
|
13576
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'vp9' || (opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'av1') {
|
13577
|
+
opts.simulcast = false;
|
13578
|
+
opts.scalabilityMode = (_g = opts.scalabilityMode) !== null && _g !== void 0 ? _g : 'L3T3';
|
13579
|
+
} else {
|
13580
|
+
// other codecs, unset scalability
|
13581
|
+
opts.scalabilityMode = undefined;
|
13582
|
+
}
|
13583
|
+
}
|
13584
|
+
|
13518
13585
|
encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, opts);
|
13519
13586
|
req.layers = videoLayersFromEncodings(req.width, req.height, encodings);
|
13520
13587
|
} else if (track.kind === Track.Kind.Audio && opts.audioBitrate) {
|
@@ -13544,6 +13611,11 @@ class LocalParticipant extends Participant {
|
|
13544
13611
|
}
|
13545
13612
|
|
13546
13613
|
const transceiver = this.engine.publisher.pc.addTransceiver(track.mediaStreamTrack, transceiverInit);
|
13614
|
+
|
13615
|
+
if (opts.videoCodec) {
|
13616
|
+
this.setPreferredCodec(transceiver, track.kind, opts.videoCodec);
|
13617
|
+
}
|
13618
|
+
|
13547
13619
|
this.engine.negotiate(); // store RTPSender
|
13548
13620
|
|
13549
13621
|
track.sender = transceiver.sender;
|
@@ -13554,10 +13626,6 @@ class LocalParticipant extends Participant {
|
|
13554
13626
|
track.startMonitor();
|
13555
13627
|
}
|
13556
13628
|
|
13557
|
-
if (opts.videoCodec) {
|
13558
|
-
this.setPreferredCodec(transceiver, track.kind, opts.videoCodec);
|
13559
|
-
}
|
13560
|
-
|
13561
13629
|
this.addTrackPublication(publication); // send event for publication
|
13562
13630
|
|
13563
13631
|
this.emit(ParticipantEvent.LocalTrackPublished, publication);
|
@@ -13739,21 +13807,38 @@ class LocalParticipant extends Participant {
|
|
13739
13807
|
|
13740
13808
|
const cap = RTCRtpSender.getCapabilities(kind);
|
13741
13809
|
if (!cap) return;
|
13742
|
-
|
13810
|
+
let selected;
|
13811
|
+
const codecs = [];
|
13812
|
+
cap.codecs.forEach(c => {
|
13743
13813
|
const codec = c.mimeType.toLowerCase();
|
13744
|
-
const matchesVideoCodec = codec === "video/".concat(videoCodec);
|
13814
|
+
const matchesVideoCodec = codec === "video/".concat(videoCodec);
|
13815
|
+
|
13816
|
+
if (selected !== undefined) {
|
13817
|
+
codecs.push(c);
|
13818
|
+
return;
|
13819
|
+
} // for h264 codecs that have sdpFmtpLine available, use only if the
|
13745
13820
|
// profile-level-id is 42e01f for cross-browser compatibility
|
13746
13821
|
|
13822
|
+
|
13747
13823
|
if (videoCodec === 'h264' && c.sdpFmtpLine) {
|
13748
|
-
|
13824
|
+
if (matchesVideoCodec && c.sdpFmtpLine.includes('profile-level-id=42e01f')) {
|
13825
|
+
selected = c;
|
13826
|
+
return;
|
13827
|
+
}
|
13828
|
+
}
|
13829
|
+
|
13830
|
+
if (matchesVideoCodec || codec === 'audio/opus') {
|
13831
|
+
selected = c;
|
13832
|
+
return;
|
13749
13833
|
}
|
13750
13834
|
|
13751
|
-
|
13835
|
+
codecs.push(c);
|
13752
13836
|
});
|
13753
13837
|
|
13754
13838
|
if (selected && 'setCodecPreferences' in transceiver) {
|
13755
13839
|
// @ts-ignore
|
13756
|
-
|
13840
|
+
codecs.unshift(selected);
|
13841
|
+
transceiver.setCodecPreferences(codecs);
|
13757
13842
|
}
|
13758
13843
|
}
|
13759
13844
|
/** @internal */
|
@@ -18525,12 +18610,11 @@ const publishDefaults = {
|
|
18525
18610
|
};
|
18526
18611
|
const audioDefaults = {
|
18527
18612
|
autoGainControl: true,
|
18528
|
-
channelCount: 1,
|
18529
18613
|
echoCancellation: true,
|
18530
18614
|
noiseSuppression: true
|
18531
18615
|
};
|
18532
18616
|
const videoDefaults = {
|
18533
|
-
resolution: VideoPresets.
|
18617
|
+
resolution: VideoPresets.h720.resolution
|
18534
18618
|
};
|
18535
18619
|
|
18536
18620
|
var RoomState;
|