livekit-client 2.13.4 → 2.13.6
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.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +11 -3
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +329 -76
- 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 -5
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/connectionHelper/checks/publishVideo.d.ts.map +1 -1
- package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
- package/dist/src/e2ee/types.d.ts +1 -0
- package/dist/src/e2ee/types.d.ts.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts +2 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +3 -2
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts +3 -3
- 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 +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/utils/dataPacketBuffer.d.ts +15 -0
- package/dist/src/utils/dataPacketBuffer.d.ts.map +1 -0
- package/dist/src/utils/ttlmap.d.ts +20 -0
- package/dist/src/utils/ttlmap.d.ts.map +1 -0
- package/dist/ts4.2/src/api/SignalClient.d.ts +5 -5
- package/dist/ts4.2/src/e2ee/types.d.ts +1 -0
- package/dist/ts4.2/src/e2ee/worker/FrameCryptor.d.ts +2 -1
- package/dist/ts4.2/src/room/PCTransport.d.ts +3 -2
- package/dist/ts4.2/src/room/PCTransportManager.d.ts +3 -3
- package/dist/ts4.2/src/room/RTCEngine.d.ts +8 -0
- package/dist/ts4.2/src/room/Room.d.ts +1 -1
- package/dist/ts4.2/src/utils/dataPacketBuffer.d.ts +15 -0
- package/dist/ts4.2/src/utils/ttlmap.d.ts +20 -0
- package/package.json +8 -8
- package/src/api/SignalClient.ts +12 -10
- package/src/connectionHelper/checks/publishVideo.ts +1 -0
- package/src/e2ee/E2eeManager.ts +3 -0
- package/src/e2ee/types.ts +1 -0
- package/src/e2ee/worker/FrameCryptor.ts +15 -0
- package/src/e2ee/worker/e2ee.worker.ts +2 -0
- package/src/room/PCTransport.ts +30 -4
- package/src/room/PCTransportManager.ts +10 -7
- package/src/room/RTCEngine.ts +78 -9
- package/src/room/Room.ts +11 -11
- package/src/room/track/LocalVideoTrack.ts +14 -15
- package/src/utils/dataPacketBuffer.ts +52 -0
- package/src/utils/ttlmap.ts +96 -0
@@ -2966,7 +2966,17 @@ function makeUtilCommon() {
|
|
2966
2966
|
}
|
2967
2967
|
switch (m.kind) {
|
2968
2968
|
case "message":
|
2969
|
-
|
2969
|
+
let a = va;
|
2970
|
+
let b = vb;
|
2971
|
+
if (m.T.fieldWrapper) {
|
2972
|
+
if (a !== undefined && !isMessage(a)) {
|
2973
|
+
a = m.T.fieldWrapper.wrapField(a);
|
2974
|
+
}
|
2975
|
+
if (b !== undefined && !isMessage(b)) {
|
2976
|
+
b = m.T.fieldWrapper.wrapField(b);
|
2977
|
+
}
|
2978
|
+
}
|
2979
|
+
return m.T.equals(a, b);
|
2970
2980
|
case "enum":
|
2971
2981
|
return scalarEquals(ScalarType.INT32, va, vb);
|
2972
2982
|
case "scalar":
|
@@ -3887,6 +3897,9 @@ const DisconnectReason = /* @__PURE__ */proto3.makeEnum("livekit.DisconnectReaso
|
|
3887
3897
|
}, {
|
3888
3898
|
no: 14,
|
3889
3899
|
name: "CONNECTION_TIMEOUT"
|
3900
|
+
}, {
|
3901
|
+
no: 15,
|
3902
|
+
name: "MEDIA_FAILURE"
|
3890
3903
|
}]);
|
3891
3904
|
const ReconnectReason = /* @__PURE__ */proto3.makeEnum("livekit.ReconnectReason", [{
|
3892
3905
|
no: 0,
|
@@ -4491,6 +4504,18 @@ const DataPacket = /* @__PURE__ */proto3.makeMessageType("livekit.DataPacket", (
|
|
4491
4504
|
kind: "message",
|
4492
4505
|
T: DataStream_Trailer,
|
4493
4506
|
oneof: "value"
|
4507
|
+
}, {
|
4508
|
+
no: 16,
|
4509
|
+
name: "sequence",
|
4510
|
+
kind: "scalar",
|
4511
|
+
T: 13
|
4512
|
+
/* ScalarType.UINT32 */
|
4513
|
+
}, {
|
4514
|
+
no: 17,
|
4515
|
+
name: "participant_sid",
|
4516
|
+
kind: "scalar",
|
4517
|
+
T: 9
|
4518
|
+
/* ScalarType.STRING */
|
4494
4519
|
}]);
|
4495
4520
|
const DataPacket_Kind = /* @__PURE__ */proto3.makeEnum("livekit.DataPacket.Kind", [{
|
4496
4521
|
no: 0,
|
@@ -5676,6 +5701,17 @@ const ReconnectResponse = /* @__PURE__ */proto3.makeMessageType("livekit.Reconne
|
|
5676
5701
|
name: "client_configuration",
|
5677
5702
|
kind: "message",
|
5678
5703
|
T: ClientConfiguration
|
5704
|
+
}, {
|
5705
|
+
no: 3,
|
5706
|
+
name: "server_info",
|
5707
|
+
kind: "message",
|
5708
|
+
T: ServerInfo
|
5709
|
+
}, {
|
5710
|
+
no: 4,
|
5711
|
+
name: "last_message_seq",
|
5712
|
+
kind: "scalar",
|
5713
|
+
T: 13
|
5714
|
+
/* ScalarType.UINT32 */
|
5679
5715
|
}]);
|
5680
5716
|
const TrackPublishedResponse = /* @__PURE__ */proto3.makeMessageType("livekit.TrackPublishedResponse", () => [{
|
5681
5717
|
no: 1,
|
@@ -5708,6 +5744,12 @@ const SessionDescription = /* @__PURE__ */proto3.makeMessageType("livekit.Sessio
|
|
5708
5744
|
kind: "scalar",
|
5709
5745
|
T: 9
|
5710
5746
|
/* ScalarType.STRING */
|
5747
|
+
}, {
|
5748
|
+
no: 3,
|
5749
|
+
name: "id",
|
5750
|
+
kind: "scalar",
|
5751
|
+
T: 13
|
5752
|
+
/* ScalarType.UINT32 */
|
5711
5753
|
}]);
|
5712
5754
|
const ParticipantUpdate = /* @__PURE__ */proto3.makeMessageType("livekit.ParticipantUpdate", () => [{
|
5713
5755
|
no: 1,
|
@@ -6122,6 +6164,25 @@ const SyncState = /* @__PURE__ */proto3.makeMessageType("livekit.SyncState", ()
|
|
6122
6164
|
kind: "scalar",
|
6123
6165
|
T: 9,
|
6124
6166
|
repeated: true
|
6167
|
+
}, {
|
6168
|
+
no: 7,
|
6169
|
+
name: "datachannel_receive_states",
|
6170
|
+
kind: "message",
|
6171
|
+
T: DataChannelReceiveState,
|
6172
|
+
repeated: true
|
6173
|
+
}]);
|
6174
|
+
const DataChannelReceiveState = /* @__PURE__ */proto3.makeMessageType("livekit.DataChannelReceiveState", () => [{
|
6175
|
+
no: 1,
|
6176
|
+
name: "publisher_sid",
|
6177
|
+
kind: "scalar",
|
6178
|
+
T: 9
|
6179
|
+
/* ScalarType.STRING */
|
6180
|
+
}, {
|
6181
|
+
no: 2,
|
6182
|
+
name: "last_seq",
|
6183
|
+
kind: "scalar",
|
6184
|
+
T: 13
|
6185
|
+
/* ScalarType.UINT32 */
|
6125
6186
|
}]);
|
6126
6187
|
const DataChannelInfo = /* @__PURE__ */proto3.makeMessageType("livekit.DataChannelInfo", () => [{
|
6127
6188
|
no: 1,
|
@@ -11270,7 +11331,7 @@ function getOSVersion(ua) {
|
|
11270
11331
|
return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
|
11271
11332
|
}
|
11272
11333
|
|
11273
|
-
var version$1 = "2.13.
|
11334
|
+
var version$1 = "2.13.6";
|
11274
11335
|
|
11275
11336
|
const version = version$1;
|
11276
11337
|
const protocolVersion = 16;
|
@@ -12890,7 +12951,8 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
12890
12951
|
writableStream: writable,
|
12891
12952
|
trackId: trackId,
|
12892
12953
|
codec,
|
12893
|
-
participantIdentity: participantIdentity
|
12954
|
+
participantIdentity: participantIdentity,
|
12955
|
+
isReuse: E2EE_FLAG in receiver
|
12894
12956
|
}
|
12895
12957
|
};
|
12896
12958
|
this.worker.postMessage(msg, [readable, writable]);
|
@@ -12933,7 +12995,8 @@ class E2EEManager extends eventsExports.EventEmitter {
|
|
12933
12995
|
writableStream: senderStreams.writable,
|
12934
12996
|
codec,
|
12935
12997
|
trackId,
|
12936
|
-
participantIdentity: this.room.localParticipant.identity
|
12998
|
+
participantIdentity: this.room.localParticipant.identity,
|
12999
|
+
isReuse: false
|
12937
13000
|
}
|
12938
13001
|
};
|
12939
13002
|
this.worker.postMessage(msg, [senderStreams.readable, senderStreams.writable]);
|
@@ -13367,23 +13430,23 @@ class SignalClient {
|
|
13367
13430
|
});
|
13368
13431
|
}
|
13369
13432
|
// initial offer after joining
|
13370
|
-
sendOffer(offer) {
|
13433
|
+
sendOffer(offer, offerId) {
|
13371
13434
|
this.log.debug('sending offer', Object.assign(Object.assign({}, this.logContext), {
|
13372
13435
|
offerSdp: offer.sdp
|
13373
13436
|
}));
|
13374
13437
|
this.sendRequest({
|
13375
13438
|
case: 'offer',
|
13376
|
-
value: toProtoSessionDescription(offer)
|
13439
|
+
value: toProtoSessionDescription(offer, offerId)
|
13377
13440
|
});
|
13378
13441
|
}
|
13379
13442
|
// answer a server-initiated offer
|
13380
|
-
sendAnswer(answer) {
|
13443
|
+
sendAnswer(answer, offerId) {
|
13381
13444
|
this.log.debug('sending answer', Object.assign(Object.assign({}, this.logContext), {
|
13382
13445
|
answerSdp: answer.sdp
|
13383
13446
|
}));
|
13384
13447
|
return this.sendRequest({
|
13385
13448
|
case: 'answer',
|
13386
|
-
value: toProtoSessionDescription(answer)
|
13449
|
+
value: toProtoSessionDescription(answer, offerId)
|
13387
13450
|
});
|
13388
13451
|
}
|
13389
13452
|
sendIceCandidate(candidate, target) {
|
@@ -13559,12 +13622,12 @@ class SignalClient {
|
|
13559
13622
|
if (msg.case === 'answer') {
|
13560
13623
|
const sd = fromProtoSessionDescription(msg.value);
|
13561
13624
|
if (this.onAnswer) {
|
13562
|
-
this.onAnswer(sd);
|
13625
|
+
this.onAnswer(sd, msg.value.id);
|
13563
13626
|
}
|
13564
13627
|
} else if (msg.case === 'offer') {
|
13565
13628
|
const sd = fromProtoSessionDescription(msg.value);
|
13566
13629
|
if (this.onOffer) {
|
13567
|
-
this.onOffer(sd);
|
13630
|
+
this.onOffer(sd, msg.value.id);
|
13568
13631
|
}
|
13569
13632
|
} else if (msg.case === 'trickle') {
|
13570
13633
|
const candidate = JSON.parse(msg.value.candidateInit);
|
@@ -13735,10 +13798,11 @@ function fromProtoSessionDescription(sd) {
|
|
13735
13798
|
}
|
13736
13799
|
return rsd;
|
13737
13800
|
}
|
13738
|
-
function toProtoSessionDescription(rsd) {
|
13801
|
+
function toProtoSessionDescription(rsd, id) {
|
13739
13802
|
const sd = new SessionDescription({
|
13740
13803
|
sdp: rsd.sdp,
|
13741
|
-
type: rsd.type
|
13804
|
+
type: rsd.type,
|
13805
|
+
id
|
13742
13806
|
});
|
13743
13807
|
return sd;
|
13744
13808
|
}
|
@@ -13787,6 +13851,135 @@ function createConnectionParams(token, info, opts) {
|
|
13787
13851
|
return params;
|
13788
13852
|
}
|
13789
13853
|
|
13854
|
+
class DataPacketBuffer {
|
13855
|
+
constructor() {
|
13856
|
+
this.buffer = [];
|
13857
|
+
this._totalSize = 0;
|
13858
|
+
}
|
13859
|
+
push(item) {
|
13860
|
+
this.buffer.push(item);
|
13861
|
+
this._totalSize += item.data.byteLength;
|
13862
|
+
}
|
13863
|
+
pop() {
|
13864
|
+
const item = this.buffer.shift();
|
13865
|
+
if (item) {
|
13866
|
+
this._totalSize -= item.data.byteLength;
|
13867
|
+
}
|
13868
|
+
return item;
|
13869
|
+
}
|
13870
|
+
getAll() {
|
13871
|
+
return this.buffer.slice();
|
13872
|
+
}
|
13873
|
+
popToSequence(sequence) {
|
13874
|
+
while (this.buffer.length > 0) {
|
13875
|
+
const first = this.buffer[0];
|
13876
|
+
if (first.sequence <= sequence) {
|
13877
|
+
this.pop();
|
13878
|
+
} else {
|
13879
|
+
break;
|
13880
|
+
}
|
13881
|
+
}
|
13882
|
+
}
|
13883
|
+
alignBufferedAmount(bufferedAmount) {
|
13884
|
+
while (this.buffer.length > 0) {
|
13885
|
+
const first = this.buffer[0];
|
13886
|
+
if (this._totalSize - first.data.byteLength <= bufferedAmount) {
|
13887
|
+
break;
|
13888
|
+
}
|
13889
|
+
this.pop();
|
13890
|
+
}
|
13891
|
+
}
|
13892
|
+
get length() {
|
13893
|
+
return this.buffer.length;
|
13894
|
+
}
|
13895
|
+
}
|
13896
|
+
|
13897
|
+
class TTLMap {
|
13898
|
+
/**
|
13899
|
+
* @param ttl ttl of the key (ms)
|
13900
|
+
*/
|
13901
|
+
constructor(ttl) {
|
13902
|
+
this._map = new Map();
|
13903
|
+
this._lastCleanup = 0;
|
13904
|
+
this.ttl = ttl;
|
13905
|
+
}
|
13906
|
+
set(key, value) {
|
13907
|
+
const now = Date.now();
|
13908
|
+
if (now - this._lastCleanup > this.ttl / 2) {
|
13909
|
+
this.cleanup();
|
13910
|
+
}
|
13911
|
+
const expiresAt = now + this.ttl;
|
13912
|
+
this._map.set(key, {
|
13913
|
+
value,
|
13914
|
+
expiresAt
|
13915
|
+
});
|
13916
|
+
return this;
|
13917
|
+
}
|
13918
|
+
get(key) {
|
13919
|
+
const entry = this._map.get(key);
|
13920
|
+
if (!entry) return undefined;
|
13921
|
+
if (entry.expiresAt < Date.now()) {
|
13922
|
+
this._map.delete(key);
|
13923
|
+
return undefined;
|
13924
|
+
}
|
13925
|
+
return entry.value;
|
13926
|
+
}
|
13927
|
+
has(key) {
|
13928
|
+
const entry = this._map.get(key);
|
13929
|
+
if (!entry) return false;
|
13930
|
+
if (entry.expiresAt < Date.now()) {
|
13931
|
+
this._map.delete(key);
|
13932
|
+
return false;
|
13933
|
+
}
|
13934
|
+
return true;
|
13935
|
+
}
|
13936
|
+
delete(key) {
|
13937
|
+
return this._map.delete(key);
|
13938
|
+
}
|
13939
|
+
clear() {
|
13940
|
+
this._map.clear();
|
13941
|
+
}
|
13942
|
+
cleanup() {
|
13943
|
+
const now = Date.now();
|
13944
|
+
for (const [key, entry] of this._map.entries()) {
|
13945
|
+
if (entry.expiresAt < now) {
|
13946
|
+
this._map.delete(key);
|
13947
|
+
}
|
13948
|
+
}
|
13949
|
+
this._lastCleanup = now;
|
13950
|
+
}
|
13951
|
+
get size() {
|
13952
|
+
this.cleanup();
|
13953
|
+
return this._map.size;
|
13954
|
+
}
|
13955
|
+
forEach(callback) {
|
13956
|
+
this.cleanup();
|
13957
|
+
for (const [key, entry] of this._map.entries()) {
|
13958
|
+
if (entry.expiresAt >= Date.now()) {
|
13959
|
+
callback(entry.value, key, this.asValueMap());
|
13960
|
+
}
|
13961
|
+
}
|
13962
|
+
}
|
13963
|
+
map(callback) {
|
13964
|
+
this.cleanup();
|
13965
|
+
const result = [];
|
13966
|
+
const valueMap = this.asValueMap();
|
13967
|
+
for (const [key, value] of valueMap.entries()) {
|
13968
|
+
result.push(callback(value, key, valueMap));
|
13969
|
+
}
|
13970
|
+
return result;
|
13971
|
+
}
|
13972
|
+
asValueMap() {
|
13973
|
+
const result = new Map();
|
13974
|
+
for (const [key, entry] of this._map.entries()) {
|
13975
|
+
if (entry.expiresAt >= Date.now()) {
|
13976
|
+
result.set(key, entry.value);
|
13977
|
+
}
|
13978
|
+
}
|
13979
|
+
return result;
|
13980
|
+
}
|
13981
|
+
}
|
13982
|
+
|
13790
13983
|
var lib = {};
|
13791
13984
|
|
13792
13985
|
var parser = {};
|
@@ -14554,6 +14747,7 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
14554
14747
|
super();
|
14555
14748
|
this.log = livekitLogger;
|
14556
14749
|
this.ddExtID = 0;
|
14750
|
+
this.latestOfferId = 0;
|
14557
14751
|
this.pendingCandidates = [];
|
14558
14752
|
this.restartingIce = false;
|
14559
14753
|
this.renegotiate = false;
|
@@ -14644,9 +14838,16 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
14644
14838
|
this.pendingCandidates.push(candidate);
|
14645
14839
|
});
|
14646
14840
|
}
|
14647
|
-
setRemoteDescription(sd) {
|
14841
|
+
setRemoteDescription(sd, offerId) {
|
14648
14842
|
return __awaiter(this, void 0, void 0, function* () {
|
14649
14843
|
var _a;
|
14844
|
+
if (sd.type === 'answer' && this.latestOfferId > 0 && offerId > 0 && offerId !== this.latestOfferId) {
|
14845
|
+
this.log.warn('ignoring answer for old offer', Object.assign(Object.assign({}, this.logContext), {
|
14846
|
+
offerId,
|
14847
|
+
latestOfferId: this.latestOfferId
|
14848
|
+
}));
|
14849
|
+
return false;
|
14850
|
+
}
|
14650
14851
|
let mungedSDP = undefined;
|
14651
14852
|
if (sd.type === 'offer') {
|
14652
14853
|
let {
|
@@ -14720,11 +14921,15 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
14720
14921
|
});
|
14721
14922
|
}
|
14722
14923
|
}
|
14924
|
+
return true;
|
14723
14925
|
});
|
14724
14926
|
}
|
14725
14927
|
createAndSendOffer(options) {
|
14726
14928
|
return __awaiter(this, void 0, void 0, function* () {
|
14727
14929
|
var _a;
|
14930
|
+
// increase the offer id at the start to ensure the offer is always > 0 so that we can use 0 as a default value for legacy behavior
|
14931
|
+
const offerId = this.latestOfferId + 1;
|
14932
|
+
this.latestOfferId = offerId;
|
14728
14933
|
if (this.onOffer === undefined) {
|
14729
14934
|
return;
|
14730
14935
|
}
|
@@ -14799,8 +15004,15 @@ class PCTransport extends eventsExports.EventEmitter {
|
|
14799
15004
|
});
|
14800
15005
|
}
|
14801
15006
|
});
|
15007
|
+
if (this.latestOfferId > offerId) {
|
15008
|
+
this.log.warn('latestOfferId mismatch', Object.assign(Object.assign({}, this.logContext), {
|
15009
|
+
latestOfferId: this.latestOfferId,
|
15010
|
+
offerId
|
15011
|
+
}));
|
15012
|
+
return;
|
15013
|
+
}
|
14802
15014
|
yield this.setMungedSDP(offer, libExports.write(sdpParsed));
|
14803
|
-
this.onOffer(offer);
|
15015
|
+
this.onOffer(offer, this.latestOfferId);
|
14804
15016
|
});
|
14805
15017
|
}
|
14806
15018
|
createAndSetAnswer() {
|
@@ -15195,9 +15407,9 @@ class PCTransportManager {
|
|
15195
15407
|
var _a;
|
15196
15408
|
(_a = this.onTrack) === null || _a === void 0 ? void 0 : _a.call(this, ev);
|
15197
15409
|
};
|
15198
|
-
this.publisher.onOffer = offer => {
|
15410
|
+
this.publisher.onOffer = (offer, offerId) => {
|
15199
15411
|
var _a;
|
15200
|
-
(_a = this.onPublisherOffer) === null || _a === void 0 ? void 0 : _a.call(this, offer);
|
15412
|
+
(_a = this.onPublisherOffer) === null || _a === void 0 ? void 0 : _a.call(this, offer, offerId);
|
15201
15413
|
};
|
15202
15414
|
this.state = PCTransportState.NEW;
|
15203
15415
|
this.connectionLock = new _();
|
@@ -15220,8 +15432,8 @@ class PCTransportManager {
|
|
15220
15432
|
createAndSendPublisherOffer(options) {
|
15221
15433
|
return this.publisher.createAndSendOffer(options);
|
15222
15434
|
}
|
15223
|
-
setPublisherAnswer(sd) {
|
15224
|
-
return this.publisher.setRemoteDescription(sd);
|
15435
|
+
setPublisherAnswer(sd, offerId) {
|
15436
|
+
return this.publisher.setRemoteDescription(sd, offerId);
|
15225
15437
|
}
|
15226
15438
|
removeTrack(sender) {
|
15227
15439
|
return this.publisher.removeTrack(sender);
|
@@ -15267,7 +15479,7 @@ class PCTransportManager {
|
|
15267
15479
|
}
|
15268
15480
|
});
|
15269
15481
|
}
|
15270
|
-
createSubscriberAnswerFromOffer(sd) {
|
15482
|
+
createSubscriberAnswerFromOffer(sd, offerId) {
|
15271
15483
|
return __awaiter(this, void 0, void 0, function* () {
|
15272
15484
|
this.log.debug('received server offer', Object.assign(Object.assign({}, this.logContext), {
|
15273
15485
|
RTCSdpType: sd.type,
|
@@ -15276,7 +15488,10 @@ class PCTransportManager {
|
|
15276
15488
|
}));
|
15277
15489
|
const unlock = yield this.remoteOfferLock.lock();
|
15278
15490
|
try {
|
15279
|
-
yield this.subscriber.setRemoteDescription(sd);
|
15491
|
+
const success = yield this.subscriber.setRemoteDescription(sd, offerId);
|
15492
|
+
if (!success) {
|
15493
|
+
return undefined;
|
15494
|
+
}
|
15280
15495
|
// answer the offer
|
15281
15496
|
const answer = yield this.subscriber.createAndSetAnswer();
|
15282
15497
|
return answer;
|
@@ -17216,44 +17431,13 @@ function setPublishingLayersForSender(sender, senderEncodings, qualities, sender
|
|
17216
17431
|
return;
|
17217
17432
|
}
|
17218
17433
|
let hasChanged = false;
|
17219
|
-
|
17220
|
-
|
17434
|
+
/* disable closable spatial layer as it has video blur / frozen issue with current server / client
|
17435
|
+
1. chrome 113: when switching to up layer with scalability Mode change, it will generate a
|
17436
|
+
low resolution frame and recover very quickly, but noticable
|
17437
|
+
2. livekit sfu: additional pli request cause video frozen for a few frames, also noticable */
|
17438
|
+
const closableSpatial = false;
|
17221
17439
|
/* @ts-ignore */
|
17222
|
-
if (closableSpatial && encodings[0].scalabilityMode) {
|
17223
|
-
// svc dynacast encodings
|
17224
|
-
const encoding = encodings[0];
|
17225
|
-
/* @ts-ignore */
|
17226
|
-
const mode = new ScalabilityMode(encoding.scalabilityMode);
|
17227
|
-
let maxQuality = VideoQuality$1.OFF;
|
17228
|
-
qualities.forEach(q => {
|
17229
|
-
if (q.enabled && (maxQuality === VideoQuality$1.OFF || q.quality > maxQuality)) {
|
17230
|
-
maxQuality = q.quality;
|
17231
|
-
}
|
17232
|
-
});
|
17233
|
-
if (maxQuality === VideoQuality$1.OFF) {
|
17234
|
-
if (encoding.active) {
|
17235
|
-
encoding.active = false;
|
17236
|
-
hasChanged = true;
|
17237
|
-
}
|
17238
|
-
} else if (!encoding.active || mode.spatial !== maxQuality + 1) {
|
17239
|
-
hasChanged = true;
|
17240
|
-
encoding.active = true;
|
17241
|
-
/* @ts-ignore */
|
17242
|
-
const originalMode = new ScalabilityMode(senderEncodings[0].scalabilityMode);
|
17243
|
-
mode.spatial = maxQuality + 1;
|
17244
|
-
mode.suffix = originalMode.suffix;
|
17245
|
-
if (mode.spatial === 1) {
|
17246
|
-
// no suffix for L1Tx
|
17247
|
-
mode.suffix = undefined;
|
17248
|
-
}
|
17249
|
-
/* @ts-ignore */
|
17250
|
-
encoding.scalabilityMode = mode.toString();
|
17251
|
-
encoding.scaleResolutionDownBy = Math.pow(2, 2 - maxQuality);
|
17252
|
-
if (senderEncodings[0].maxBitrate) {
|
17253
|
-
encoding.maxBitrate = senderEncodings[0].maxBitrate / (encoding.scaleResolutionDownBy * encoding.scaleResolutionDownBy);
|
17254
|
-
}
|
17255
|
-
}
|
17256
|
-
} else {
|
17440
|
+
if (closableSpatial && encodings[0].scalabilityMode) ; else {
|
17257
17441
|
if (isSVC) {
|
17258
17442
|
const hasEnabledEncoding = qualities.some(q => q.enabled);
|
17259
17443
|
if (hasEnabledEncoding) {
|
@@ -17366,6 +17550,7 @@ const lossyDataChannel = '_lossy';
|
|
17366
17550
|
const reliableDataChannel = '_reliable';
|
17367
17551
|
const minReconnectWait = 2 * 1000;
|
17368
17552
|
const leaveReconnect = 'leave-reconnect';
|
17553
|
+
const reliabeReceiveStateTTL = 30000;
|
17369
17554
|
var PCState;
|
17370
17555
|
(function (PCState) {
|
17371
17556
|
PCState[PCState["New"] = 0] = "New";
|
@@ -17389,6 +17574,10 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17389
17574
|
this.rtcConfig = {};
|
17390
17575
|
this.peerConnectionTimeout = roomConnectOptionDefaults.peerConnectionTimeout;
|
17391
17576
|
this.fullReconnectOnNext = false;
|
17577
|
+
/**
|
17578
|
+
* @internal
|
17579
|
+
*/
|
17580
|
+
this.latestRemoteOfferId = 0;
|
17392
17581
|
this.subscriberPrimary = false;
|
17393
17582
|
this.pcState = PCState.New;
|
17394
17583
|
this._isClosed = true;
|
@@ -17402,6 +17591,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17402
17591
|
this.maxJoinAttempts = 1;
|
17403
17592
|
this.shouldFailNext = false;
|
17404
17593
|
this.log = livekitLogger;
|
17594
|
+
this.reliableDataSequence = 1;
|
17595
|
+
this.reliableMessageBuffer = new DataPacketBuffer();
|
17596
|
+
this.reliableReceivedState = new TTLMap(reliabeReceiveStateTTL);
|
17405
17597
|
this.handleDataChannel = _a => __awaiter(this, [_a], void 0, function (_ref) {
|
17406
17598
|
var _this = this;
|
17407
17599
|
let {
|
@@ -17440,6 +17632,14 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17440
17632
|
return;
|
17441
17633
|
}
|
17442
17634
|
const dp = DataPacket.fromBinary(new Uint8Array(buffer));
|
17635
|
+
if (dp.sequence > 0 && dp.participantSid !== '') {
|
17636
|
+
const lastSeq = this.reliableReceivedState.get(dp.participantSid);
|
17637
|
+
if (lastSeq && dp.sequence <= lastSeq) {
|
17638
|
+
// ignore duplicate or out-of-order packets in reliable channel
|
17639
|
+
return;
|
17640
|
+
}
|
17641
|
+
this.reliableReceivedState.set(dp.participantSid, dp.sequence);
|
17642
|
+
}
|
17443
17643
|
if (((_a = dp.value) === null || _a === void 0 ? void 0 : _a.case) === 'speaker') {
|
17444
17644
|
// dispatch speaker updates
|
17445
17645
|
this.emit(EngineEvent.ActiveSpeakersUpdate, dp.value.value.speakers);
|
@@ -17540,6 +17740,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17540
17740
|
this.isBufferStatusLow = kind => {
|
17541
17741
|
const dc = this.dataChannelForKind(kind);
|
17542
17742
|
if (dc) {
|
17743
|
+
if (kind === DataPacket_Kind.RELIABLE) {
|
17744
|
+
this.reliableMessageBuffer.alignBufferedAmount(dc.bufferedAmount);
|
17745
|
+
}
|
17543
17746
|
return dc.bufferedAmount <= dc.bufferedAmountLowThreshold;
|
17544
17747
|
}
|
17545
17748
|
};
|
@@ -17661,6 +17864,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17661
17864
|
this.lossyDCSub = undefined;
|
17662
17865
|
this.reliableDC = undefined;
|
17663
17866
|
this.reliableDCSub = undefined;
|
17867
|
+
this.reliableMessageBuffer = new DataPacketBuffer();
|
17868
|
+
this.reliableDataSequence = 1;
|
17869
|
+
this.reliableReceivedState.clear();
|
17664
17870
|
});
|
17665
17871
|
}
|
17666
17872
|
cleanupClient() {
|
@@ -17748,8 +17954,8 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17748
17954
|
this.pcManager.onIceCandidate = (candidate, target) => {
|
17749
17955
|
this.client.sendIceCandidate(candidate, target);
|
17750
17956
|
};
|
17751
|
-
this.pcManager.onPublisherOffer = offer => {
|
17752
|
-
this.client.sendOffer(offer);
|
17957
|
+
this.pcManager.onPublisherOffer = (offer, offerId) => {
|
17958
|
+
this.client.sendOffer(offer, offerId);
|
17753
17959
|
};
|
17754
17960
|
this.pcManager.onDataChannel = this.handleDataChannel;
|
17755
17961
|
this.pcManager.onStateChange = (connectionState, publisherState, subscriberState) => __awaiter(this, void 0, void 0, function* () {
|
@@ -17788,14 +17994,14 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17788
17994
|
}
|
17789
17995
|
setupSignalClientCallbacks() {
|
17790
17996
|
// configure signaling client
|
17791
|
-
this.client.onAnswer = sd => __awaiter(this, void 0, void 0, function* () {
|
17997
|
+
this.client.onAnswer = (sd, offerId) => __awaiter(this, void 0, void 0, function* () {
|
17792
17998
|
if (!this.pcManager) {
|
17793
17999
|
return;
|
17794
18000
|
}
|
17795
18001
|
this.log.debug('received server answer', Object.assign(Object.assign({}, this.logContext), {
|
17796
18002
|
RTCSdpType: sd.type
|
17797
18003
|
}));
|
17798
|
-
yield this.pcManager.setPublisherAnswer(sd);
|
18004
|
+
yield this.pcManager.setPublisherAnswer(sd, offerId);
|
17799
18005
|
});
|
17800
18006
|
// add candidate on trickle
|
17801
18007
|
this.client.onTrickle = (candidate, target) => {
|
@@ -17809,12 +18015,15 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
17809
18015
|
this.pcManager.addIceCandidate(candidate, target);
|
17810
18016
|
};
|
17811
18017
|
// when server creates an offer for the client
|
17812
|
-
this.client.onOffer = sd => __awaiter(this, void 0, void 0, function* () {
|
18018
|
+
this.client.onOffer = (sd, offerId) => __awaiter(this, void 0, void 0, function* () {
|
18019
|
+
this.latestRemoteOfferId = offerId;
|
17813
18020
|
if (!this.pcManager) {
|
17814
18021
|
return;
|
17815
18022
|
}
|
17816
|
-
const answer = yield this.pcManager.createSubscriberAnswerFromOffer(sd);
|
17817
|
-
|
18023
|
+
const answer = yield this.pcManager.createSubscriberAnswerFromOffer(sd, offerId);
|
18024
|
+
if (answer) {
|
18025
|
+
this.client.sendAnswer(answer, offerId);
|
18026
|
+
}
|
17818
18027
|
});
|
17819
18028
|
this.client.onLocalTrackPublished = res => {
|
17820
18029
|
var _a;
|
@@ -18185,6 +18394,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
18185
18394
|
if (res) {
|
18186
18395
|
const rtcConfig = this.makeRTCConfiguration(res);
|
18187
18396
|
this.pcManager.updateConfiguration(rtcConfig);
|
18397
|
+
if (this.latestJoinResponse) {
|
18398
|
+
this.latestJoinResponse.serverInfo = res.serverInfo;
|
18399
|
+
}
|
18188
18400
|
} else {
|
18189
18401
|
this.log.warn('Did not receive reconnect response', this.logContext);
|
18190
18402
|
}
|
@@ -18204,6 +18416,9 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
18204
18416
|
if (((_a = this.reliableDC) === null || _a === void 0 ? void 0 : _a.readyState) === 'open' && this.reliableDC.id === null) {
|
18205
18417
|
this.createDataChannels();
|
18206
18418
|
}
|
18419
|
+
if (res === null || res === void 0 ? void 0 : res.lastMessageSeq) {
|
18420
|
+
this.resendReliableMessagesForResume(res.lastMessageSeq);
|
18421
|
+
}
|
18207
18422
|
// resume success
|
18208
18423
|
this.emit(EngineEvent.Resumed);
|
18209
18424
|
});
|
@@ -18276,16 +18491,42 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
18276
18491
|
/* @internal */
|
18277
18492
|
sendDataPacket(packet, kind) {
|
18278
18493
|
return __awaiter(this, void 0, void 0, function* () {
|
18279
|
-
const msg = packet.toBinary();
|
18280
18494
|
// make sure we do have a data connection
|
18281
18495
|
yield this.ensurePublisherConnected(kind);
|
18496
|
+
if (kind === DataPacket_Kind.RELIABLE) {
|
18497
|
+
packet.sequence = this.reliableDataSequence;
|
18498
|
+
this.reliableDataSequence += 1;
|
18499
|
+
}
|
18500
|
+
const msg = packet.toBinary();
|
18282
18501
|
const dc = this.dataChannelForKind(kind);
|
18283
18502
|
if (dc) {
|
18503
|
+
if (kind === DataPacket_Kind.RELIABLE) {
|
18504
|
+
this.reliableMessageBuffer.push({
|
18505
|
+
data: msg,
|
18506
|
+
sequence: packet.sequence
|
18507
|
+
});
|
18508
|
+
}
|
18509
|
+
if (this.attemptingReconnect) {
|
18510
|
+
return;
|
18511
|
+
}
|
18284
18512
|
dc.send(msg);
|
18285
18513
|
}
|
18286
18514
|
this.updateAndEmitDCBufferStatus(kind);
|
18287
18515
|
});
|
18288
18516
|
}
|
18517
|
+
resendReliableMessagesForResume(lastMessageSeq) {
|
18518
|
+
return __awaiter(this, void 0, void 0, function* () {
|
18519
|
+
yield this.ensurePublisherConnected(DataPacket_Kind.RELIABLE);
|
18520
|
+
const dc = this.dataChannelForKind(DataPacket_Kind.RELIABLE);
|
18521
|
+
if (dc) {
|
18522
|
+
this.reliableMessageBuffer.popToSequence(lastMessageSeq);
|
18523
|
+
this.reliableMessageBuffer.getAll().forEach(msg => {
|
18524
|
+
dc.send(msg.data);
|
18525
|
+
});
|
18526
|
+
}
|
18527
|
+
this.updateAndEmitDCBufferStatus(DataPacket_Kind.RELIABLE);
|
18528
|
+
});
|
18529
|
+
}
|
18289
18530
|
waitForBufferStatusLow(kind) {
|
18290
18531
|
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
18291
18532
|
if (this.isBufferStatusLow(kind)) {
|
@@ -18477,7 +18718,13 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
18477
18718
|
}),
|
18478
18719
|
publishTracks: getTrackPublicationInfo(localTracks),
|
18479
18720
|
dataChannels: this.dataChannelsInfo(),
|
18480
|
-
trackSidsDisabled
|
18721
|
+
trackSidsDisabled,
|
18722
|
+
datachannelReceiveStates: this.reliableReceivedState.map((seq, sid) => {
|
18723
|
+
return new DataChannelReceiveState({
|
18724
|
+
publisherSid: sid,
|
18725
|
+
lastSeq: seq
|
18726
|
+
});
|
18727
|
+
})
|
18481
18728
|
}));
|
18482
18729
|
}
|
18483
18730
|
/* @internal */
|
@@ -23588,7 +23835,7 @@ class Room extends eventsExports.EventEmitter {
|
|
23588
23835
|
this.remoteParticipants.forEach((participant, identity) => {
|
23589
23836
|
this.handleParticipantDisconnected(identity, participant);
|
23590
23837
|
});
|
23591
|
-
this.emit(RoomEvent.Moved, roomMoved.room.name
|
23838
|
+
this.emit(RoomEvent.Moved, roomMoved.room.name);
|
23592
23839
|
if (roomMoved.participant) {
|
23593
23840
|
this.handleParticipantUpdates([roomMoved.participant, ...roomMoved.otherParticipants]);
|
23594
23841
|
} else {
|
@@ -23818,15 +24065,15 @@ class Room extends eventsExports.EventEmitter {
|
|
23818
24065
|
var _this3 = this;
|
23819
24066
|
let exact = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
23820
24067
|
return function* () {
|
23821
|
-
var _a, _b, _c, _d, _e, _f
|
23822
|
-
var
|
24068
|
+
var _a, _b, _c, _d, _e, _f;
|
24069
|
+
var _g;
|
23823
24070
|
let success = true;
|
23824
|
-
let
|
24071
|
+
let shouldTriggerImmediateDeviceChange = false;
|
23825
24072
|
const deviceConstraint = exact ? {
|
23826
24073
|
exact: deviceId
|
23827
24074
|
} : deviceId;
|
23828
24075
|
if (kind === 'audioinput') {
|
23829
|
-
|
24076
|
+
shouldTriggerImmediateDeviceChange = _this3.localParticipant.audioTrackPublications.size === 0;
|
23830
24077
|
const prevDeviceId = (_a = _this3.getActiveDevice(kind)) !== null && _a !== void 0 ? _a : _this3.options.audioCaptureDefaults.deviceId;
|
23831
24078
|
_this3.options.audioCaptureDefaults.deviceId = deviceConstraint;
|
23832
24079
|
const tracks = Array.from(_this3.localParticipant.audioTrackPublications.values()).filter(track => track.source === Track.Source.Microphone);
|
@@ -23839,8 +24086,13 @@ class Room extends eventsExports.EventEmitter {
|
|
23839
24086
|
_this3.options.audioCaptureDefaults.deviceId = prevDeviceId;
|
23840
24087
|
throw e;
|
23841
24088
|
}
|
24089
|
+
const isMuted = tracks.some(t => {
|
24090
|
+
var _a, _b;
|
24091
|
+
return (_b = (_a = t.track) === null || _a === void 0 ? void 0 : _a.isMuted) !== null && _b !== void 0 ? _b : false;
|
24092
|
+
});
|
24093
|
+
if (success && isMuted) shouldTriggerImmediateDeviceChange = true;
|
23842
24094
|
} else if (kind === 'videoinput') {
|
23843
|
-
|
24095
|
+
shouldTriggerImmediateDeviceChange = _this3.localParticipant.videoTrackPublications.size === 0;
|
23844
24096
|
const prevDeviceId = (_b = _this3.getActiveDevice(kind)) !== null && _b !== void 0 ? _b : _this3.options.videoCaptureDefaults.deviceId;
|
23845
24097
|
_this3.options.videoCaptureDefaults.deviceId = deviceConstraint;
|
23846
24098
|
const tracks = Array.from(_this3.localParticipant.videoTrackPublications.values()).filter(track => track.source === Track.Source.Camera);
|
@@ -23854,6 +24106,7 @@ class Room extends eventsExports.EventEmitter {
|
|
23854
24106
|
throw e;
|
23855
24107
|
}
|
23856
24108
|
} else if (kind === 'audiooutput') {
|
24109
|
+
shouldTriggerImmediateDeviceChange = true;
|
23857
24110
|
if (!supportsSetSinkId() && !_this3.options.webAudioMix || _this3.options.webAudioMix && _this3.audioContext && !('setSinkId' in _this3.audioContext)) {
|
23858
24111
|
throw new Error('cannot switch audio output, setSinkId not supported');
|
23859
24112
|
}
|
@@ -23861,7 +24114,7 @@ class Room extends eventsExports.EventEmitter {
|
|
23861
24114
|
// setting `default` for web audio output doesn't work, so we need to normalize the id before
|
23862
24115
|
deviceId = (_c = yield DeviceManager.getInstance().normalizeDeviceId('audiooutput', deviceId)) !== null && _c !== void 0 ? _c : '';
|
23863
24116
|
}
|
23864
|
-
(_d = (
|
24117
|
+
(_d = (_g = _this3.options).audioOutput) !== null && _d !== void 0 ? _d : _g.audioOutput = {};
|
23865
24118
|
const prevDeviceId = (_e = _this3.getActiveDevice(kind)) !== null && _e !== void 0 ? _e : _this3.options.audioOutput.deviceId;
|
23866
24119
|
_this3.options.audioOutput.deviceId = deviceId;
|
23867
24120
|
try {
|
@@ -23879,9 +24132,8 @@ class Room extends eventsExports.EventEmitter {
|
|
23879
24132
|
throw e;
|
23880
24133
|
}
|
23881
24134
|
}
|
23882
|
-
if (
|
23883
|
-
|
23884
|
-
_this3.localParticipant.activeDeviceMap.set(kind, kind === 'audiooutput' && ((_g = _this3.options.audioOutput) === null || _g === void 0 ? void 0 : _g.deviceId) || deviceId);
|
24135
|
+
if (shouldTriggerImmediateDeviceChange) {
|
24136
|
+
_this3.localParticipant.activeDeviceMap.set(kind, deviceId);
|
23885
24137
|
_this3.emit(RoomEvent.ActiveDeviceChanged, kind, deviceId);
|
23886
24138
|
}
|
23887
24139
|
return success;
|
@@ -25006,6 +25258,7 @@ class PublishVideoCheck extends Checker {
|
|
25006
25258
|
};
|
25007
25259
|
video.play();
|
25008
25260
|
});
|
25261
|
+
stream.getTracks().forEach(t => t.stop());
|
25009
25262
|
video.remove();
|
25010
25263
|
});
|
25011
25264
|
}
|