livekit-client 1.6.5 → 1.6.7
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/livekit-client.esm.mjs +149 -130
- 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/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +10 -3
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +2 -1
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +1 -0
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts +1 -1
- package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -1
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +2 -1
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/room/track/options.d.ts +2 -2
- package/dist/ts4.2/src/room/RTCEngine.d.ts +10 -3
- package/dist/ts4.2/src/room/events.d.ts +2 -1
- package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +1 -0
- package/dist/ts4.2/src/room/track/RemoteTrackPublication.d.ts +1 -1
- package/dist/ts4.2/src/room/track/Track.d.ts +2 -1
- package/dist/ts4.2/src/room/track/options.d.ts +2 -2
- package/package.json +13 -13
- package/src/room/PCTransport.ts +2 -0
- package/src/room/RTCEngine.ts +46 -51
- package/src/room/Room.ts +13 -3
- package/src/room/events.ts +2 -1
- package/src/room/participant/LocalParticipant.ts +20 -8
- package/src/room/participant/RemoteParticipant.ts +2 -3
- package/src/room/track/LocalVideoTrack.ts +62 -46
- package/src/room/track/RemoteTrackPublication.ts +3 -2
- package/src/room/track/RemoteVideoTrack.ts +0 -3
- package/src/room/track/Track.ts +2 -1
- package/src/room/track/options.ts +2 -2
@@ -12877,7 +12877,8 @@ var RoomEvent;
|
|
12877
12877
|
*/
|
12878
12878
|
RoomEvent["SignalConnected"] = "signalConnected";
|
12879
12879
|
/**
|
12880
|
-
* Recording of a room has started/stopped.
|
12880
|
+
* Recording of a room has started/stopped. Room.isRecording will be updated too.
|
12881
|
+
* args: (isRecording: boolean)
|
12881
12882
|
*/
|
12882
12883
|
RoomEvent["RecordingStatusChanged"] = "recordingStatusChanged";
|
12883
12884
|
})(RoomEvent || (RoomEvent = {}));
|
@@ -13799,7 +13800,7 @@ var uaParser = {
|
|
13799
13800
|
})(uaParser, uaParserExports);
|
13800
13801
|
var UAParser = uaParserExports;
|
13801
13802
|
|
13802
|
-
var version$1 = "1.6.
|
13803
|
+
var version$1 = "1.6.7";
|
13803
13804
|
|
13804
13805
|
const version = version$1;
|
13805
13806
|
const protocolVersion = 8;
|
@@ -14780,7 +14781,8 @@ class Track extends eventsExports.EventEmitter {
|
|
14780
14781
|
this.attachedElements = [];
|
14781
14782
|
this.isMuted = false;
|
14782
14783
|
/**
|
14783
|
-
* indicates current state of stream
|
14784
|
+
* indicates current state of stream, it'll indicate `paused` if the track
|
14785
|
+
* has been paused by congestion controller
|
14784
14786
|
*/
|
14785
14787
|
this.streamState = Track.StreamState.Active;
|
14786
14788
|
this._currentBitrate = 0;
|
@@ -15465,6 +15467,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
15465
15467
|
}
|
15466
15468
|
this.prevStats = statsMap;
|
15467
15469
|
};
|
15470
|
+
this.senderLock = new Mutex();
|
15468
15471
|
}
|
15469
15472
|
get isSimulcast() {
|
15470
15473
|
if (this.sender && this.sender.getParameters().encodings.length > 1) {
|
@@ -15657,7 +15660,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
15657
15660
|
}
|
15658
15661
|
} else if (simulcastCodecInfo.encodings) {
|
15659
15662
|
livekitLogger.debug("try setPublishingLayersForSender ".concat(codec.codec));
|
15660
|
-
await setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities);
|
15663
|
+
await setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities, this.senderLock);
|
15661
15664
|
}
|
15662
15665
|
}
|
15663
15666
|
}
|
@@ -15687,7 +15690,7 @@ class LocalVideoTrack extends LocalTrack {
|
|
15687
15690
|
if (!this.sender || !this.encodings) {
|
15688
15691
|
return;
|
15689
15692
|
}
|
15690
|
-
await setPublishingLayersForSender(this.sender, this.encodings, qualities);
|
15693
|
+
await setPublishingLayersForSender(this.sender, this.encodings, qualities, this.senderLock);
|
15691
15694
|
}
|
15692
15695
|
async handleAppVisibilityChanged() {
|
15693
15696
|
await super.handleAppVisibilityChanged();
|
@@ -15697,59 +15700,64 @@ class LocalVideoTrack extends LocalTrack {
|
|
15697
15700
|
}
|
15698
15701
|
}
|
15699
15702
|
}
|
15700
|
-
async function setPublishingLayersForSender(sender, senderEncodings, qualities) {
|
15703
|
+
async function setPublishingLayersForSender(sender, senderEncodings, qualities, senderLock) {
|
15704
|
+
const unlock = await senderLock.lock();
|
15701
15705
|
livekitLogger.debug('setPublishingLayersForSender', {
|
15702
15706
|
sender,
|
15703
15707
|
qualities,
|
15704
15708
|
senderEncodings
|
15705
15709
|
});
|
15706
|
-
|
15707
|
-
|
15708
|
-
|
15709
|
-
|
15710
|
-
|
15711
|
-
|
15712
|
-
|
15713
|
-
if (encodings.length !== senderEncodings.length) {
|
15714
|
-
livekitLogger.warn('cannot set publishing layers, encodings mismatch');
|
15715
|
-
return;
|
15716
|
-
}
|
15717
|
-
let hasChanged = false;
|
15718
|
-
encodings.forEach((encoding, idx) => {
|
15719
|
-
var _a;
|
15720
|
-
let rid = (_a = encoding.rid) !== null && _a !== void 0 ? _a : '';
|
15721
|
-
if (rid === '') {
|
15722
|
-
rid = 'q';
|
15710
|
+
try {
|
15711
|
+
const params = sender.getParameters();
|
15712
|
+
const {
|
15713
|
+
encodings
|
15714
|
+
} = params;
|
15715
|
+
if (!encodings) {
|
15716
|
+
return;
|
15723
15717
|
}
|
15724
|
-
|
15725
|
-
|
15726
|
-
if (!subscribedQuality) {
|
15718
|
+
if (encodings.length !== senderEncodings.length) {
|
15719
|
+
livekitLogger.warn('cannot set publishing layers, encodings mismatch');
|
15727
15720
|
return;
|
15728
15721
|
}
|
15729
|
-
|
15730
|
-
|
15731
|
-
|
15732
|
-
|
15733
|
-
|
15734
|
-
|
15735
|
-
|
15736
|
-
|
15737
|
-
|
15738
|
-
|
15739
|
-
|
15740
|
-
|
15741
|
-
|
15742
|
-
|
15743
|
-
|
15744
|
-
|
15745
|
-
|
15722
|
+
let hasChanged = false;
|
15723
|
+
encodings.forEach((encoding, idx) => {
|
15724
|
+
var _a;
|
15725
|
+
let rid = (_a = encoding.rid) !== null && _a !== void 0 ? _a : '';
|
15726
|
+
if (rid === '') {
|
15727
|
+
rid = 'q';
|
15728
|
+
}
|
15729
|
+
const quality = videoQualityForRid(rid);
|
15730
|
+
const subscribedQuality = qualities.find(q => q.quality === quality);
|
15731
|
+
if (!subscribedQuality) {
|
15732
|
+
return;
|
15733
|
+
}
|
15734
|
+
if (encoding.active !== subscribedQuality.enabled) {
|
15735
|
+
hasChanged = true;
|
15736
|
+
encoding.active = subscribedQuality.enabled;
|
15737
|
+
livekitLogger.debug("setting layer ".concat(subscribedQuality.quality, " to ").concat(encoding.active ? 'enabled' : 'disabled'));
|
15738
|
+
// FireFox does not support setting encoding.active to false, so we
|
15739
|
+
// have a workaround of lowering its bitrate and resolution to the min.
|
15740
|
+
if (isFireFox()) {
|
15741
|
+
if (subscribedQuality.enabled) {
|
15742
|
+
encoding.scaleResolutionDownBy = senderEncodings[idx].scaleResolutionDownBy;
|
15743
|
+
encoding.maxBitrate = senderEncodings[idx].maxBitrate;
|
15744
|
+
/* @ts-ignore */
|
15745
|
+
encoding.maxFrameRate = senderEncodings[idx].maxFrameRate;
|
15746
|
+
} else {
|
15747
|
+
encoding.scaleResolutionDownBy = 4;
|
15748
|
+
encoding.maxBitrate = 10;
|
15749
|
+
/* @ts-ignore */
|
15750
|
+
encoding.maxFrameRate = 2;
|
15751
|
+
}
|
15746
15752
|
}
|
15747
15753
|
}
|
15754
|
+
});
|
15755
|
+
if (hasChanged) {
|
15756
|
+
params.encodings = encodings;
|
15757
|
+
await sender.setParameters(params);
|
15748
15758
|
}
|
15749
|
-
}
|
15750
|
-
|
15751
|
-
params.encodings = encodings;
|
15752
|
-
await sender.setParameters(params);
|
15759
|
+
} finally {
|
15760
|
+
unlock();
|
15753
15761
|
}
|
15754
15762
|
}
|
15755
15763
|
function videoQualityForRid(rid) {
|
@@ -16108,9 +16116,6 @@ class RemoteVideoTrack extends RemoteTrack {
|
|
16108
16116
|
this.updateDimensions();
|
16109
16117
|
}, REACTION_DELAY);
|
16110
16118
|
this.adaptiveStreamSettings = adaptiveStreamSettings;
|
16111
|
-
if (this.isAdaptiveStream) {
|
16112
|
-
this.streamState = Track.StreamState.Paused;
|
16113
|
-
}
|
16114
16119
|
}
|
16115
16120
|
get isAdaptiveStream() {
|
16116
16121
|
return this.adaptiveStreamSettings !== undefined;
|
@@ -17016,8 +17021,8 @@ function sortPresets(presets) {
|
|
17016
17021
|
}
|
17017
17022
|
|
17018
17023
|
class RemoteTrackPublication extends TrackPublication {
|
17019
|
-
constructor(kind,
|
17020
|
-
super(kind,
|
17024
|
+
constructor(kind, ti, autoSubscribe) {
|
17025
|
+
super(kind, ti.sid, ti.name);
|
17021
17026
|
this.track = undefined;
|
17022
17027
|
/** @internal */
|
17023
17028
|
this.allowed = true;
|
@@ -17042,6 +17047,7 @@ class RemoteTrackPublication extends TrackPublication {
|
|
17042
17047
|
this.emitTrackUpdate();
|
17043
17048
|
};
|
17044
17049
|
this.subscribed = autoSubscribe;
|
17050
|
+
this.updateInfo(ti);
|
17045
17051
|
}
|
17046
17052
|
/**
|
17047
17053
|
* Subscribe or unsubscribe to this remote track
|
@@ -17408,12 +17414,12 @@ class RemoteParticipant extends Participant {
|
|
17408
17414
|
if (!kind) {
|
17409
17415
|
return;
|
17410
17416
|
}
|
17411
|
-
publication = new RemoteTrackPublication(kind, ti
|
17417
|
+
publication = new RemoteTrackPublication(kind, ti, (_a = this.signalClient.connectOptions) === null || _a === void 0 ? void 0 : _a.autoSubscribe);
|
17412
17418
|
publication.updateInfo(ti);
|
17413
17419
|
newTracks.set(ti.sid, publication);
|
17414
17420
|
const existingTrackOfSource = Array.from(this.tracks.values()).find(publishedTrack => publishedTrack.source === (publication === null || publication === void 0 ? void 0 : publication.source));
|
17415
17421
|
if (existingTrackOfSource && publication.source !== Track.Source.Unknown) {
|
17416
|
-
livekitLogger.
|
17422
|
+
livekitLogger.debug("received a second track publication for ".concat(this.identity, " with the same source: ").concat(publication.source), {
|
17417
17423
|
oldTrack: existingTrackOfSource,
|
17418
17424
|
newTrack: publication,
|
17419
17425
|
participant: this,
|
@@ -17588,7 +17594,7 @@ class LocalParticipant extends Participant {
|
|
17588
17594
|
}
|
17589
17595
|
}
|
17590
17596
|
} else if (update.subscribedQualities.length > 0) {
|
17591
|
-
(_b = pub.videoTrack) === null || _b === void 0 ? void 0 : _b.setPublishingLayers(update.subscribedQualities);
|
17597
|
+
await ((_b = pub.videoTrack) === null || _b === void 0 ? void 0 : _b.setPublishingLayers(update.subscribedQualities));
|
17592
17598
|
}
|
17593
17599
|
};
|
17594
17600
|
this.handleLocalTrackUnpublished = unpublished => {
|
@@ -17921,7 +17927,7 @@ class LocalParticipant extends Participant {
|
|
17921
17927
|
* @param options
|
17922
17928
|
*/
|
17923
17929
|
async publishTrack(track, options) {
|
17924
|
-
var _a, _b, _c, _d, _e;
|
17930
|
+
var _a, _b, _c, _d, _e, _f;
|
17925
17931
|
// convert raw media track into audio or video track
|
17926
17932
|
if (track instanceof MediaStreamTrack) {
|
17927
17933
|
switch (track.kind) {
|
@@ -17946,7 +17952,11 @@ class LocalParticipant extends Participant {
|
|
17946
17952
|
if (options.dtx === undefined) {
|
17947
17953
|
livekitLogger.info("Opus DTX will be disabled for stereo tracks by default. Enable them explicitly to make it work.");
|
17948
17954
|
}
|
17955
|
+
if (options.red === undefined) {
|
17956
|
+
livekitLogger.info("Opus RED will be disabled for stereo tracks by default. Enable them explicitly to make it work.");
|
17957
|
+
}
|
17949
17958
|
(_a = options.dtx) !== null && _a !== void 0 ? _a : options.dtx = false;
|
17959
|
+
(_b = options.red) !== null && _b !== void 0 ? _b : options.red = false;
|
17950
17960
|
}
|
17951
17961
|
const opts = _objectSpread2(_objectSpread2({}, this.roomOptions.publishDefaults), options);
|
17952
17962
|
// is it already published? if so skip
|
@@ -18004,9 +18014,9 @@ class LocalParticipant extends Participant {
|
|
18004
18014
|
type: Track.kindToProto(track.kind),
|
18005
18015
|
muted: track.isMuted,
|
18006
18016
|
source: Track.sourceToProto(track.source),
|
18007
|
-
disableDtx: !((
|
18017
|
+
disableDtx: !((_c = opts.dtx) !== null && _c !== void 0 ? _c : true),
|
18008
18018
|
stereo: isStereo,
|
18009
|
-
disableRed: !((
|
18019
|
+
disableRed: !((_d = opts.red) !== null && _d !== void 0 ? _d : true)
|
18010
18020
|
});
|
18011
18021
|
// compute encodings and layers for video
|
18012
18022
|
let encodings;
|
@@ -18029,7 +18039,7 @@ class LocalParticipant extends Participant {
|
|
18029
18039
|
if (track instanceof LocalVideoTrack) {
|
18030
18040
|
if ((opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'av1') {
|
18031
18041
|
// set scalabilityMode to 'L3T3' by default
|
18032
|
-
opts.scalabilityMode = (
|
18042
|
+
opts.scalabilityMode = (_e = opts.scalabilityMode) !== null && _e !== void 0 ? _e : 'L3T3';
|
18033
18043
|
}
|
18034
18044
|
// set up backup
|
18035
18045
|
if (opts.videoCodec && opts.backupCodec && opts.videoCodec !== opts.backupCodec.codec) {
|
@@ -18071,7 +18081,7 @@ class LocalParticipant extends Participant {
|
|
18071
18081
|
});
|
18072
18082
|
// store RTPSender
|
18073
18083
|
track.sender = await this.engine.createSender(track, opts, encodings);
|
18074
|
-
if (track.codec === 'av1' && encodings && ((
|
18084
|
+
if (track.codec === 'av1' && encodings && ((_f = encodings[0]) === null || _f === void 0 ? void 0 : _f.maxBitrate)) {
|
18075
18085
|
this.engine.publisher.setTrackCodecBitrate(req.cid, track.codec, encodings[0].maxBitrate / 1000);
|
18076
18086
|
}
|
18077
18087
|
this.engine.negotiate();
|
@@ -18167,13 +18177,20 @@ class LocalParticipant extends Participant {
|
|
18167
18177
|
if (stopOnUnpublish) {
|
18168
18178
|
track.stop();
|
18169
18179
|
}
|
18170
|
-
|
18180
|
+
let negotiationNeeded = false;
|
18181
|
+
const trackSender = track.sender;
|
18182
|
+
track.sender = undefined;
|
18183
|
+
if (this.engine.publisher && this.engine.publisher.pc.connectionState !== 'closed' && trackSender) {
|
18171
18184
|
try {
|
18172
|
-
this.engine.removeTrack(
|
18185
|
+
if (this.engine.removeTrack(trackSender)) {
|
18186
|
+
negotiationNeeded = true;
|
18187
|
+
}
|
18173
18188
|
if (track instanceof LocalVideoTrack) {
|
18174
18189
|
for (const [, trackInfo] of track.simulcastCodecs) {
|
18175
18190
|
if (trackInfo.sender) {
|
18176
|
-
this.engine.removeTrack(trackInfo.sender)
|
18191
|
+
if (this.engine.removeTrack(trackInfo.sender)) {
|
18192
|
+
negotiationNeeded = true;
|
18193
|
+
}
|
18177
18194
|
trackInfo.sender = undefined;
|
18178
18195
|
}
|
18179
18196
|
}
|
@@ -18184,11 +18201,8 @@ class LocalParticipant extends Participant {
|
|
18184
18201
|
error: e,
|
18185
18202
|
method: 'unpublishTrack'
|
18186
18203
|
});
|
18187
|
-
} finally {
|
18188
|
-
await this.engine.negotiate();
|
18189
18204
|
}
|
18190
18205
|
}
|
18191
|
-
track.sender = undefined;
|
18192
18206
|
// remove from our maps
|
18193
18207
|
this.tracks.delete(publication.trackSid);
|
18194
18208
|
switch (publication.kind) {
|
@@ -18201,6 +18215,9 @@ class LocalParticipant extends Participant {
|
|
18201
18215
|
}
|
18202
18216
|
this.emit(ParticipantEvent.LocalTrackUnpublished, publication);
|
18203
18217
|
publication.setTrack(undefined);
|
18218
|
+
if (negotiationNeeded) {
|
18219
|
+
await this.engine.negotiate();
|
18220
|
+
}
|
18204
18221
|
return publication;
|
18205
18222
|
}
|
18206
18223
|
async unpublishTracks(tracks) {
|
@@ -19750,6 +19767,8 @@ class PCTransport extends eventsExports {
|
|
19750
19767
|
});
|
19751
19768
|
}
|
19752
19769
|
close() {
|
19770
|
+
this.pc.onconnectionstatechange = null;
|
19771
|
+
this.pc.oniceconnectionstatechange = null;
|
19753
19772
|
this.pc.close();
|
19754
19773
|
}
|
19755
19774
|
async setMungedLocalDescription(sd, munged) {
|
@@ -19868,9 +19887,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
19868
19887
|
return this._isClosed;
|
19869
19888
|
}
|
19870
19889
|
constructor(options) {
|
19871
|
-
var _this;
|
19872
19890
|
super();
|
19873
|
-
_this = this;
|
19874
19891
|
this.options = options;
|
19875
19892
|
this.rtcConfig = {};
|
19876
19893
|
this.peerConnectionTimeout = roomConnectOptionDefaults.peerConnectionTimeout;
|
@@ -19889,6 +19906,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
19889
19906
|
this.joinAttempts = 0;
|
19890
19907
|
/** specifies how often an initial join connection is allowed to retry */
|
19891
19908
|
this.maxJoinAttempts = 1;
|
19909
|
+
this.shouldFailNext = false;
|
19892
19910
|
this.handleDataChannel = async _ref => {
|
19893
19911
|
let {
|
19894
19912
|
channel
|
@@ -19941,26 +19959,24 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
19941
19959
|
// websocket reconnect behavior. if websocket is interrupted, and the PeerConnection
|
19942
19960
|
// continues to work, we can reconnect to websocket to continue the session
|
19943
19961
|
// after a number of retries, we'll close and give up permanently
|
19944
|
-
this.handleDisconnect =
|
19945
|
-
|
19946
|
-
let disconnectReason = arguments.length > 2 ? arguments[2] : undefined;
|
19947
|
-
if (_this._isClosed) {
|
19962
|
+
this.handleDisconnect = (connection, disconnectReason) => {
|
19963
|
+
if (this._isClosed) {
|
19948
19964
|
return;
|
19949
19965
|
}
|
19950
19966
|
livekitLogger.warn("".concat(connection, " disconnected"));
|
19951
|
-
if (
|
19967
|
+
if (this.reconnectAttempts === 0) {
|
19952
19968
|
// only reset start time on the first try
|
19953
|
-
|
19969
|
+
this.reconnectStart = Date.now();
|
19954
19970
|
}
|
19955
19971
|
const disconnect = duration => {
|
19956
|
-
livekitLogger.warn("could not recover connection after ".concat(
|
19957
|
-
|
19958
|
-
|
19972
|
+
livekitLogger.warn("could not recover connection after ".concat(this.reconnectAttempts, " attempts, ").concat(duration, "ms. giving up"));
|
19973
|
+
this.emit(EngineEvent.Disconnected);
|
19974
|
+
this.close();
|
19959
19975
|
};
|
19960
|
-
const duration = Date.now() -
|
19961
|
-
let delay =
|
19976
|
+
const duration = Date.now() - this.reconnectStart;
|
19977
|
+
let delay = this.getNextRetryDelay({
|
19962
19978
|
elapsedMs: duration,
|
19963
|
-
retryCount:
|
19979
|
+
retryCount: this.reconnectAttempts
|
19964
19980
|
});
|
19965
19981
|
if (delay === null) {
|
19966
19982
|
disconnect(duration);
|
@@ -19970,14 +19986,14 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
19970
19986
|
delay = 0;
|
19971
19987
|
}
|
19972
19988
|
livekitLogger.debug("reconnecting in ".concat(delay, "ms"));
|
19973
|
-
|
19974
|
-
|
19989
|
+
this.clearReconnectTimeout();
|
19990
|
+
this.reconnectTimeout = CriticalTimers.setTimeout(() => this.attemptReconnect(disconnectReason), delay);
|
19975
19991
|
};
|
19976
19992
|
this.handleBrowserOnLine = () => {
|
19977
19993
|
// in case the engine is currently reconnecting, attempt a reconnect immediately after the browser state has changed to 'onLine'
|
19978
19994
|
if (this.client.isReconnecting) {
|
19979
19995
|
this.clearReconnectTimeout();
|
19980
|
-
this.attemptReconnect(
|
19996
|
+
this.attemptReconnect(ReconnectReason.REASON_SIGNAL_DISCONNECTED);
|
19981
19997
|
}
|
19982
19998
|
};
|
19983
19999
|
this.client = new SignalClient();
|
@@ -20076,6 +20092,12 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20076
20092
|
this.client.sendAddTrack(req);
|
20077
20093
|
});
|
20078
20094
|
}
|
20095
|
+
/**
|
20096
|
+
* Removes sender from PeerConnection, returning true if it was removed successfully
|
20097
|
+
* and a negotiation is necessary
|
20098
|
+
* @param sender
|
20099
|
+
* @returns
|
20100
|
+
*/
|
20079
20101
|
removeTrack(sender) {
|
20080
20102
|
var _a;
|
20081
20103
|
if (sender.track && this.pendingTrackResolvers[sender.track.id]) {
|
@@ -20089,12 +20111,14 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20089
20111
|
}
|
20090
20112
|
try {
|
20091
20113
|
(_a = this.publisher) === null || _a === void 0 ? void 0 : _a.pc.removeTrack(sender);
|
20114
|
+
return true;
|
20092
20115
|
} catch (e) {
|
20093
20116
|
livekitLogger.warn('failed to remove track', {
|
20094
20117
|
error: e,
|
20095
20118
|
method: 'removeTrack'
|
20096
20119
|
});
|
20097
20120
|
}
|
20121
|
+
return false;
|
20098
20122
|
}
|
20099
20123
|
updateMuteStatus(trackSid, muted) {
|
20100
20124
|
this.client.sendMuteTrack(trackSid, muted);
|
@@ -20103,8 +20127,11 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20103
20127
|
var _a;
|
20104
20128
|
return (_a = this.reliableDCSub) === null || _a === void 0 ? void 0 : _a.readyState;
|
20105
20129
|
}
|
20106
|
-
|
20107
|
-
|
20130
|
+
async getConnectedServerAddress() {
|
20131
|
+
if (this.primaryPC === undefined) {
|
20132
|
+
return undefined;
|
20133
|
+
}
|
20134
|
+
return getConnectedAddress(this.primaryPC);
|
20108
20135
|
}
|
20109
20136
|
configure(joinResponse) {
|
20110
20137
|
var _a;
|
@@ -20142,13 +20169,6 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20142
20169
|
primaryPC.onconnectionstatechange = async () => {
|
20143
20170
|
livekitLogger.debug("primary PC state changed ".concat(primaryPC.connectionState));
|
20144
20171
|
if (primaryPC.connectionState === 'connected') {
|
20145
|
-
try {
|
20146
|
-
this.connectedServerAddr = await getConnectedAddress(primaryPC);
|
20147
|
-
} catch (e) {
|
20148
|
-
livekitLogger.warn('could not get connected server address', {
|
20149
|
-
error: e
|
20150
|
-
});
|
20151
|
-
}
|
20152
20172
|
const shouldEmit = this.pcState === PCState.New;
|
20153
20173
|
this.pcState = PCState.Connected;
|
20154
20174
|
if (shouldEmit) {
|
@@ -20158,7 +20178,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20158
20178
|
// on Safari, PeerConnection will switch to 'disconnected' during renegotiation
|
20159
20179
|
if (this.pcState === PCState.Connected) {
|
20160
20180
|
this.pcState = PCState.Disconnected;
|
20161
|
-
this.handleDisconnect('primary peerconnection',
|
20181
|
+
this.handleDisconnect('primary peerconnection', subscriberPrimary ? ReconnectReason.REASON_SUBSCRIBER_FAILED : ReconnectReason.REASON_PUBLISHER_FAILED);
|
20162
20182
|
}
|
20163
20183
|
}
|
20164
20184
|
};
|
@@ -20166,7 +20186,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20166
20186
|
livekitLogger.debug("secondary PC state changed ".concat(secondaryPC.connectionState));
|
20167
20187
|
// also reconnect if secondary peerconnection fails
|
20168
20188
|
if (secondaryPC.connectionState === 'failed') {
|
20169
|
-
this.handleDisconnect('secondary peerconnection',
|
20189
|
+
this.handleDisconnect('secondary peerconnection', subscriberPrimary ? ReconnectReason.REASON_PUBLISHER_FAILED : ReconnectReason.REASON_SUBSCRIBER_FAILED);
|
20170
20190
|
}
|
20171
20191
|
};
|
20172
20192
|
this.subscriber.pc.ontrack = ev => {
|
@@ -20229,7 +20249,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20229
20249
|
this.token = token;
|
20230
20250
|
};
|
20231
20251
|
this.client.onClose = () => {
|
20232
|
-
this.handleDisconnect('signal',
|
20252
|
+
this.handleDisconnect('signal', ReconnectReason.REASON_SIGNAL_DISCONNECTED);
|
20233
20253
|
};
|
20234
20254
|
this.client.onLeave = leave => {
|
20235
20255
|
if (leave === null || leave === void 0 ? void 0 : leave.canReconnect) {
|
@@ -20403,9 +20423,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20403
20423
|
}
|
20404
20424
|
return this.publisher.pc.addTrack(track);
|
20405
20425
|
}
|
20406
|
-
async attemptReconnect() {
|
20407
|
-
let signalEvents = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
20408
|
-
let reason = arguments.length > 1 ? arguments[1] : undefined;
|
20426
|
+
async attemptReconnect(reason) {
|
20409
20427
|
var _a, _b, _c;
|
20410
20428
|
if (this._isClosed) {
|
20411
20429
|
return;
|
@@ -20423,17 +20441,15 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20423
20441
|
try {
|
20424
20442
|
this.attemptingReconnect = true;
|
20425
20443
|
if (this.fullReconnectOnNext) {
|
20426
|
-
await this.restartConnection(
|
20444
|
+
await this.restartConnection();
|
20427
20445
|
} else {
|
20428
|
-
await this.resumeConnection(
|
20446
|
+
await this.resumeConnection(reason);
|
20429
20447
|
}
|
20430
20448
|
this.clearPendingReconnect();
|
20431
20449
|
this.fullReconnectOnNext = false;
|
20432
20450
|
} catch (e) {
|
20433
20451
|
this.reconnectAttempts += 1;
|
20434
|
-
let reconnectRequired = false;
|
20435
20452
|
let recoverable = true;
|
20436
|
-
let requireSignalEvents = false;
|
20437
20453
|
if (e instanceof UnexpectedConnectionState) {
|
20438
20454
|
livekitLogger.debug('received unrecoverable error', {
|
20439
20455
|
error: e
|
@@ -20442,16 +20458,10 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20442
20458
|
recoverable = false;
|
20443
20459
|
} else if (!(e instanceof SignalReconnectError)) {
|
20444
20460
|
// cannot resume
|
20445
|
-
reconnectRequired = true;
|
20446
|
-
}
|
20447
|
-
// when we flip from resume to reconnect
|
20448
|
-
// we need to fire the right reconnecting events
|
20449
|
-
if (reconnectRequired && !this.fullReconnectOnNext) {
|
20450
20461
|
this.fullReconnectOnNext = true;
|
20451
|
-
requireSignalEvents = true;
|
20452
20462
|
}
|
20453
20463
|
if (recoverable) {
|
20454
|
-
this.handleDisconnect('reconnect',
|
20464
|
+
this.handleDisconnect('reconnect', ReconnectReason.REASON_UNKOWN);
|
20455
20465
|
} else {
|
20456
20466
|
livekitLogger.info("could not recover connection after ".concat(this.reconnectAttempts, " attempts, ").concat(Date.now() - this.reconnectStart, "ms. giving up"));
|
20457
20467
|
this.emit(EngineEvent.Disconnected);
|
@@ -20473,16 +20483,13 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20473
20483
|
return null;
|
20474
20484
|
}
|
20475
20485
|
async restartConnection() {
|
20476
|
-
let emitRestarting = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
20477
20486
|
var _a, _b;
|
20478
20487
|
if (!this.url || !this.token) {
|
20479
20488
|
// permanent failure, don't attempt reconnection
|
20480
20489
|
throw new UnexpectedConnectionState('could not reconnect, url or token not saved');
|
20481
20490
|
}
|
20482
20491
|
livekitLogger.info("reconnecting, attempt: ".concat(this.reconnectAttempts));
|
20483
|
-
|
20484
|
-
this.emit(EngineEvent.Restarting);
|
20485
|
-
}
|
20492
|
+
this.emit(EngineEvent.Restarting);
|
20486
20493
|
if (this.client.isConnected) {
|
20487
20494
|
await this.client.sendLeave();
|
20488
20495
|
}
|
@@ -20502,14 +20509,16 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20502
20509
|
} catch (e) {
|
20503
20510
|
throw new SignalReconnectError();
|
20504
20511
|
}
|
20512
|
+
if (this.shouldFailNext) {
|
20513
|
+
this.shouldFailNext = false;
|
20514
|
+
throw new Error('simulated failure');
|
20515
|
+
}
|
20505
20516
|
await this.waitForPCConnected();
|
20506
20517
|
this.client.setReconnected();
|
20507
20518
|
// reconnect success
|
20508
20519
|
this.emit(EngineEvent.Restarted, joinResponse);
|
20509
20520
|
}
|
20510
|
-
async resumeConnection() {
|
20511
|
-
let emitResuming = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
20512
|
-
let reason = arguments.length > 1 ? arguments[1] : undefined;
|
20521
|
+
async resumeConnection(reason) {
|
20513
20522
|
var _a;
|
20514
20523
|
if (!this.url || !this.token) {
|
20515
20524
|
// permanent failure, don't attempt reconnection
|
@@ -20520,9 +20529,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20520
20529
|
throw new UnexpectedConnectionState('publisher and subscriber connections unset');
|
20521
20530
|
}
|
20522
20531
|
livekitLogger.info("resuming signal connection, attempt ".concat(this.reconnectAttempts));
|
20523
|
-
|
20524
|
-
this.emit(EngineEvent.Resuming);
|
20525
|
-
}
|
20532
|
+
this.emit(EngineEvent.Resuming);
|
20526
20533
|
try {
|
20527
20534
|
const res = await this.client.reconnect(this.url, this.token, this.participantSid, reason);
|
20528
20535
|
if (res) {
|
@@ -20538,6 +20545,10 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20538
20545
|
throw new SignalReconnectError(message);
|
20539
20546
|
}
|
20540
20547
|
this.emit(EngineEvent.SignalResumed);
|
20548
|
+
if (this.shouldFailNext) {
|
20549
|
+
this.shouldFailNext = false;
|
20550
|
+
throw new Error('simulated failure');
|
20551
|
+
}
|
20541
20552
|
this.subscriber.restartingIce = true;
|
20542
20553
|
// only restart publisher if it's needed
|
20543
20554
|
if (this.hasPublished) {
|
@@ -20571,13 +20582,6 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20571
20582
|
// manually
|
20572
20583
|
now - startTime > minReconnectWait && ((_a = this.primaryPC) === null || _a === void 0 ? void 0 : _a.connectionState) === 'connected') {
|
20573
20584
|
this.pcState = PCState.Connected;
|
20574
|
-
try {
|
20575
|
-
this.connectedServerAddr = await getConnectedAddress(this.primaryPC);
|
20576
|
-
} catch (e) {
|
20577
|
-
livekitLogger.warn('could not get connected server address', {
|
20578
|
-
error: e
|
20579
|
-
});
|
20580
|
-
}
|
20581
20585
|
}
|
20582
20586
|
if (this.pcState === PCState.Connected) {
|
20583
20587
|
return;
|
@@ -20649,7 +20653,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20649
20653
|
this.on(EngineEvent.Closing, handleClosed);
|
20650
20654
|
const negotiationTimeout = setTimeout(() => {
|
20651
20655
|
reject('negotiation timed out');
|
20652
|
-
this.handleDisconnect('negotiation',
|
20656
|
+
this.handleDisconnect('negotiation', ReconnectReason.REASON_SIGNAL_DISCONNECTED);
|
20653
20657
|
}, this.peerConnectionTimeout);
|
20654
20658
|
const cleanup = () => {
|
20655
20659
|
clearTimeout(negotiationTimeout);
|
@@ -20668,7 +20672,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20668
20672
|
if (e instanceof NegotiationError) {
|
20669
20673
|
this.fullReconnectOnNext = true;
|
20670
20674
|
}
|
20671
|
-
this.handleDisconnect('negotiation',
|
20675
|
+
this.handleDisconnect('negotiation', ReconnectReason.REASON_UNKOWN);
|
20672
20676
|
});
|
20673
20677
|
});
|
20674
20678
|
}
|
@@ -20689,6 +20693,11 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
20689
20693
|
}
|
20690
20694
|
}
|
20691
20695
|
}
|
20696
|
+
/* @internal */
|
20697
|
+
failNext() {
|
20698
|
+
// debugging method to fail the next reconnect/resume attempt
|
20699
|
+
this.shouldFailNext = true;
|
20700
|
+
}
|
20692
20701
|
clearReconnectTimeout() {
|
20693
20702
|
if (this.reconnectTimeout) {
|
20694
20703
|
CriticalTimers.clearTimeout(this.reconnectTimeout);
|
@@ -21008,6 +21017,9 @@ class Room extends eventsExports.EventEmitter {
|
|
21008
21017
|
});
|
21009
21018
|
await track.restartTrack();
|
21010
21019
|
}
|
21020
|
+
livekitLogger.debug('publishing new track', {
|
21021
|
+
track: pub.trackSid
|
21022
|
+
});
|
21011
21023
|
await this.localParticipant.publishTrack(track, pub.options);
|
21012
21024
|
}
|
21013
21025
|
}));
|
@@ -21330,6 +21342,13 @@ class Room extends eventsExports.EventEmitter {
|
|
21330
21342
|
}
|
21331
21343
|
});
|
21332
21344
|
break;
|
21345
|
+
case 'resume-reconnect':
|
21346
|
+
this.engine.failNext();
|
21347
|
+
await this.engine.client.close();
|
21348
|
+
if (this.engine.client.onClose) {
|
21349
|
+
this.engine.client.onClose('simulate resume-reconnect');
|
21350
|
+
}
|
21351
|
+
break;
|
21333
21352
|
case 'force-tcp':
|
21334
21353
|
case 'force-tls':
|
21335
21354
|
req = SimulateScenario.fromPartial({
|
@@ -21564,7 +21583,7 @@ class Room extends eventsExports.EventEmitter {
|
|
21564
21583
|
participant.tracks.forEach(publication => {
|
21565
21584
|
participant.unpublishTrack(publication.trackSid, true);
|
21566
21585
|
});
|
21567
|
-
this.
|
21586
|
+
this.emit(RoomEvent.ParticipantDisconnected, participant);
|
21568
21587
|
}
|
21569
21588
|
async acquireAudioContext() {
|
21570
21589
|
var _a, _b;
|
@@ -21625,7 +21644,7 @@ class Room extends eventsExports.EventEmitter {
|
|
21625
21644
|
}
|
21626
21645
|
this.emit(RoomEvent.TrackSubscribed, track, publication, participant);
|
21627
21646
|
}).on(ParticipantEvent.TrackUnpublished, publication => {
|
21628
|
-
this.
|
21647
|
+
this.emit(RoomEvent.TrackUnpublished, publication, participant);
|
21629
21648
|
}).on(ParticipantEvent.TrackUnsubscribed, (track, publication) => {
|
21630
21649
|
this.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);
|
21631
21650
|
}).on(ParticipantEvent.TrackSubscriptionFailed, sid => {
|