livekit-client 2.15.9 → 2.15.11
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 +125 -17
- 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 +7 -3
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/api/utils.d.ts +1 -0
- package/dist/src/api/utils.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts +1 -0
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +2 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/rpc.d.ts +6 -1
- package/dist/src/room/rpc.d.ts.map +1 -1
- package/dist/ts4.2/api/SignalClient.d.ts +7 -3
- package/dist/ts4.2/api/utils.d.ts +1 -0
- package/dist/ts4.2/room/PCTransportManager.d.ts +1 -0
- package/dist/ts4.2/room/RTCEngine.d.ts +2 -0
- package/dist/ts4.2/room/rpc.d.ts +6 -1
- package/package.json +2 -2
- package/src/api/SignalClient.test.ts +93 -12
- package/src/api/SignalClient.ts +36 -12
- package/src/api/utils.ts +18 -0
- package/src/room/PCTransportManager.ts +10 -0
- package/src/room/RTCEngine.ts +22 -3
- package/src/room/Room.ts +34 -0
- package/src/room/participant/LocalParticipant.ts +5 -9
- package/src/room/rpc.ts +6 -1
|
@@ -4262,6 +4262,9 @@ const ParticipantInfo_Kind = /* @__PURE__ */proto3.makeEnum("livekit.Participant
|
|
|
4262
4262
|
}, {
|
|
4263
4263
|
no: 4,
|
|
4264
4264
|
name: "AGENT"
|
|
4265
|
+
}, {
|
|
4266
|
+
no: 7,
|
|
4267
|
+
name: "CONNECTOR"
|
|
4265
4268
|
}]);
|
|
4266
4269
|
const ParticipantInfo_KindDetail = /* @__PURE__ */proto3.makeEnum("livekit.ParticipantInfo.KindDetail", [{
|
|
4267
4270
|
no: 0,
|
|
@@ -5348,6 +5351,19 @@ const DataStream_Trailer = /* @__PURE__ */proto3.makeMessageType("livekit.DataSt
|
|
|
5348
5351
|
}], {
|
|
5349
5352
|
localName: "DataStream_Trailer"
|
|
5350
5353
|
});
|
|
5354
|
+
const FilterParams = /* @__PURE__ */proto3.makeMessageType("livekit.FilterParams", () => [{
|
|
5355
|
+
no: 1,
|
|
5356
|
+
name: "include_events",
|
|
5357
|
+
kind: "scalar",
|
|
5358
|
+
T: 9,
|
|
5359
|
+
repeated: true
|
|
5360
|
+
}, {
|
|
5361
|
+
no: 2,
|
|
5362
|
+
name: "exclude_events",
|
|
5363
|
+
kind: "scalar",
|
|
5364
|
+
T: 9,
|
|
5365
|
+
repeated: true
|
|
5366
|
+
}]);
|
|
5351
5367
|
const WebhookConfig = /* @__PURE__ */proto3.makeMessageType("livekit.WebhookConfig", () => [{
|
|
5352
5368
|
no: 1,
|
|
5353
5369
|
name: "url",
|
|
@@ -5360,6 +5376,11 @@ const WebhookConfig = /* @__PURE__ */proto3.makeMessageType("livekit.WebhookConf
|
|
|
5360
5376
|
kind: "scalar",
|
|
5361
5377
|
T: 9
|
|
5362
5378
|
/* ScalarType.STRING */
|
|
5379
|
+
}, {
|
|
5380
|
+
no: 3,
|
|
5381
|
+
name: "filter_params",
|
|
5382
|
+
kind: "message",
|
|
5383
|
+
T: FilterParams
|
|
5363
5384
|
}]);
|
|
5364
5385
|
const SubscribedAudioCodec = /* @__PURE__ */proto3.makeMessageType("livekit.SubscribedAudioCodec", () => [{
|
|
5365
5386
|
no: 1,
|
|
@@ -6706,6 +6727,16 @@ const SessionDescription = /* @__PURE__ */proto3.makeMessageType("livekit.Sessio
|
|
|
6706
6727
|
kind: "scalar",
|
|
6707
6728
|
T: 13
|
|
6708
6729
|
/* ScalarType.UINT32 */
|
|
6730
|
+
}, {
|
|
6731
|
+
no: 4,
|
|
6732
|
+
name: "mid_to_track_id",
|
|
6733
|
+
kind: "map",
|
|
6734
|
+
K: 9,
|
|
6735
|
+
V: {
|
|
6736
|
+
kind: "scalar",
|
|
6737
|
+
T: 9
|
|
6738
|
+
/* ScalarType.STRING */
|
|
6739
|
+
}
|
|
6709
6740
|
}]);
|
|
6710
6741
|
const ParticipantUpdate = /* @__PURE__ */proto3.makeMessageType("livekit.ParticipantUpdate", () => [{
|
|
6711
6742
|
no: 1,
|
|
@@ -12570,7 +12601,7 @@ function getOSVersion(ua) {
|
|
|
12570
12601
|
return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
|
|
12571
12602
|
}
|
|
12572
12603
|
|
|
12573
|
-
var version$1 = "2.15.
|
|
12604
|
+
var version$1 = "2.15.11";
|
|
12574
12605
|
|
|
12575
12606
|
const version = version$1;
|
|
12576
12607
|
const protocolVersion = 16;
|
|
@@ -14641,6 +14672,21 @@ function parseSignalResponse(value) {
|
|
|
14641
14672
|
}
|
|
14642
14673
|
throw new Error("could not decode websocket message: ".concat(typeof value));
|
|
14643
14674
|
}
|
|
14675
|
+
function getAbortReasonAsString(signal) {
|
|
14676
|
+
let defaultMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Unknown reason';
|
|
14677
|
+
if (!(signal instanceof AbortSignal)) {
|
|
14678
|
+
return defaultMessage;
|
|
14679
|
+
}
|
|
14680
|
+
const reason = signal.reason;
|
|
14681
|
+
switch (typeof reason) {
|
|
14682
|
+
case 'string':
|
|
14683
|
+
return reason;
|
|
14684
|
+
case 'object':
|
|
14685
|
+
return reason instanceof Error ? reason.message : defaultMessage;
|
|
14686
|
+
default:
|
|
14687
|
+
return 'toString' in reason ? reason.toString() : defaultMessage;
|
|
14688
|
+
}
|
|
14689
|
+
}
|
|
14644
14690
|
|
|
14645
14691
|
const passThroughQueueSignals = ['syncState', 'trickle', 'offer', 'answer', 'simulate', 'leave'];
|
|
14646
14692
|
function canPassThroughQueue(req) {
|
|
@@ -14755,9 +14801,18 @@ class SignalClient {
|
|
|
14755
14801
|
const signals = abortSignal ? [timeoutAbortController.signal, abortSignal] : [timeoutAbortController.signal];
|
|
14756
14802
|
const combinedAbort = AbortSignal.any(signals);
|
|
14757
14803
|
const abortHandler = event => __awaiter(this, void 0, void 0, function* () {
|
|
14758
|
-
this.close();
|
|
14759
|
-
clearTimeout(wsTimeout);
|
|
14760
14804
|
const target = event.currentTarget;
|
|
14805
|
+
const reason = getAbortReasonAsString(target, 'Abort handler called');
|
|
14806
|
+
// send leave if we have an active stream writer (connection is open)
|
|
14807
|
+
if (this.streamWriter && !this.isDisconnected) {
|
|
14808
|
+
this.sendLeave().then(() => this.close(reason)).catch(e => {
|
|
14809
|
+
this.log.error(e);
|
|
14810
|
+
this.close();
|
|
14811
|
+
});
|
|
14812
|
+
} else {
|
|
14813
|
+
this.close();
|
|
14814
|
+
}
|
|
14815
|
+
clearTimeout(wsTimeout);
|
|
14761
14816
|
reject(target instanceof AbortSignal ? target.reason : target);
|
|
14762
14817
|
});
|
|
14763
14818
|
combinedAbort.addEventListener('abort', abortHandler);
|
|
@@ -14778,9 +14833,7 @@ class SignalClient {
|
|
|
14778
14833
|
if (this.ws) {
|
|
14779
14834
|
yield this.close(false);
|
|
14780
14835
|
}
|
|
14781
|
-
this.ws = new WebSocketStream(rtcUrl
|
|
14782
|
-
signal: combinedAbort
|
|
14783
|
-
});
|
|
14836
|
+
this.ws = new WebSocketStream(rtcUrl);
|
|
14784
14837
|
try {
|
|
14785
14838
|
this.ws.closed.then(closeInfo => {
|
|
14786
14839
|
if (this.isEstablishingConnection) {
|
|
@@ -14818,6 +14871,7 @@ class SignalClient {
|
|
|
14818
14871
|
return;
|
|
14819
14872
|
}
|
|
14820
14873
|
const signalReader = connection.readable.getReader();
|
|
14874
|
+
this.streamWriter = connection.writable.getWriter();
|
|
14821
14875
|
const firstMessage = yield signalReader.read();
|
|
14822
14876
|
signalReader.releaseLock();
|
|
14823
14877
|
if (!firstMessage.value) {
|
|
@@ -14880,6 +14934,7 @@ class SignalClient {
|
|
|
14880
14934
|
return __awaiter(this, arguments, void 0, function () {
|
|
14881
14935
|
var _this = this;
|
|
14882
14936
|
let updateState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
14937
|
+
let reason = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Close method called on signal client';
|
|
14883
14938
|
return function* () {
|
|
14884
14939
|
const unlock = yield _this.closingLock.lock();
|
|
14885
14940
|
try {
|
|
@@ -14890,7 +14945,7 @@ class SignalClient {
|
|
|
14890
14945
|
if (_this.ws) {
|
|
14891
14946
|
_this.ws.close({
|
|
14892
14947
|
closeCode: 1000,
|
|
14893
|
-
reason
|
|
14948
|
+
reason
|
|
14894
14949
|
});
|
|
14895
14950
|
// calling `ws.close()` only starts the closing handshake (CLOSING state), prefer to wait until state is actually CLOSED
|
|
14896
14951
|
const closePromise = _this.ws.closed;
|
|
@@ -15110,12 +15165,12 @@ class SignalClient {
|
|
|
15110
15165
|
if (msg.case === 'answer') {
|
|
15111
15166
|
const sd = fromProtoSessionDescription(msg.value);
|
|
15112
15167
|
if (this.onAnswer) {
|
|
15113
|
-
this.onAnswer(sd, msg.value.id);
|
|
15168
|
+
this.onAnswer(sd, msg.value.id, msg.value.midToTrackId);
|
|
15114
15169
|
}
|
|
15115
15170
|
} else if (msg.case === 'offer') {
|
|
15116
15171
|
const sd = fromProtoSessionDescription(msg.value);
|
|
15117
15172
|
if (this.onOffer) {
|
|
15118
|
-
this.onOffer(sd, msg.value.id);
|
|
15173
|
+
this.onOffer(sd, msg.value.id, msg.value.midToTrackId);
|
|
15119
15174
|
}
|
|
15120
15175
|
} else if (msg.case === 'trickle') {
|
|
15121
15176
|
const candidate = JSON.parse(msg.value.candidateInit);
|
|
@@ -15218,7 +15273,7 @@ class SignalClient {
|
|
|
15218
15273
|
return __awaiter(this, void 0, void 0, function* () {
|
|
15219
15274
|
if (this.state === SignalConnectionState.DISCONNECTED) return;
|
|
15220
15275
|
const onCloseCallback = this.onClose;
|
|
15221
|
-
yield this.close();
|
|
15276
|
+
yield this.close(undefined, reason);
|
|
15222
15277
|
this.log.debug("websocket connection closed: ".concat(reason), Object.assign(Object.assign({}, this.logContext), {
|
|
15223
15278
|
reason
|
|
15224
15279
|
}));
|
|
@@ -15286,7 +15341,6 @@ class SignalClient {
|
|
|
15286
15341
|
clearTimeout(timeoutHandle);
|
|
15287
15342
|
this.startPingInterval();
|
|
15288
15343
|
this.startReadingLoop(connection.readable.getReader(), firstMessage);
|
|
15289
|
-
this.streamWriter = connection.writable.getWriter();
|
|
15290
15344
|
}
|
|
15291
15345
|
/**
|
|
15292
15346
|
* Validates the first message received from the signal server
|
|
@@ -17176,6 +17230,11 @@ class PCTransportManager {
|
|
|
17176
17230
|
addPublisherTransceiverOfKind(kind, transceiverInit) {
|
|
17177
17231
|
return this.publisher.addTransceiverOfKind(kind, transceiverInit);
|
|
17178
17232
|
}
|
|
17233
|
+
getMidForReceiver(receiver) {
|
|
17234
|
+
const transceivers = this.subscriber ? this.subscriber.getTransceivers() : this.publisher.getTransceivers();
|
|
17235
|
+
const matchingTransceiver = transceivers.find(transceiver => transceiver.receiver === receiver);
|
|
17236
|
+
return matchingTransceiver === null || matchingTransceiver === void 0 ? void 0 : matchingTransceiver.mid;
|
|
17237
|
+
}
|
|
17179
17238
|
addPublisherTrack(track) {
|
|
17180
17239
|
return this.publisher.addTrack(track);
|
|
17181
17240
|
}
|
|
@@ -19336,6 +19395,7 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
19336
19395
|
this.reliableDataSequence = 1;
|
|
19337
19396
|
this.reliableMessageBuffer = new DataPacketBuffer();
|
|
19338
19397
|
this.reliableReceivedState = new TTLMap(reliabeReceiveStateTTL);
|
|
19398
|
+
this.midToTrackId = {};
|
|
19339
19399
|
this.handleDataChannel = _a => __awaiter(this, [_a], void 0, function (_ref) {
|
|
19340
19400
|
var _this = this;
|
|
19341
19401
|
let {
|
|
@@ -19758,13 +19818,16 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
19758
19818
|
}
|
|
19759
19819
|
setupSignalClientCallbacks() {
|
|
19760
19820
|
// configure signaling client
|
|
19761
|
-
this.client.onAnswer = (sd, offerId) => __awaiter(this, void 0, void 0, function* () {
|
|
19821
|
+
this.client.onAnswer = (sd, offerId, midToTrackId) => __awaiter(this, void 0, void 0, function* () {
|
|
19762
19822
|
if (!this.pcManager) {
|
|
19763
19823
|
return;
|
|
19764
19824
|
}
|
|
19765
19825
|
this.log.debug('received server answer', Object.assign(Object.assign({}, this.logContext), {
|
|
19766
|
-
RTCSdpType: sd.type
|
|
19826
|
+
RTCSdpType: sd.type,
|
|
19827
|
+
sdp: sd.sdp,
|
|
19828
|
+
midToTrackId
|
|
19767
19829
|
}));
|
|
19830
|
+
this.midToTrackId = midToTrackId;
|
|
19768
19831
|
yield this.pcManager.setPublisherAnswer(sd, offerId);
|
|
19769
19832
|
});
|
|
19770
19833
|
// add candidate on trickle
|
|
@@ -19779,11 +19842,12 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
19779
19842
|
this.pcManager.addIceCandidate(candidate, target);
|
|
19780
19843
|
};
|
|
19781
19844
|
// when server creates an offer for the client
|
|
19782
|
-
this.client.onOffer = (sd, offerId) => __awaiter(this, void 0, void 0, function* () {
|
|
19845
|
+
this.client.onOffer = (sd, offerId, midToTrackId) => __awaiter(this, void 0, void 0, function* () {
|
|
19783
19846
|
this.latestRemoteOfferId = offerId;
|
|
19784
19847
|
if (!this.pcManager) {
|
|
19785
19848
|
return;
|
|
19786
19849
|
}
|
|
19850
|
+
this.midToTrackId = midToTrackId;
|
|
19787
19851
|
const answer = yield this.pcManager.createSubscriberAnswerFromOffer(sd, offerId);
|
|
19788
19852
|
if (answer) {
|
|
19789
19853
|
this.client.sendAnswer(answer, offerId);
|
|
@@ -20569,6 +20633,19 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
20569
20633
|
window.removeEventListener('online', this.handleBrowserOnLine);
|
|
20570
20634
|
}
|
|
20571
20635
|
}
|
|
20636
|
+
getTrackIdForReceiver(receiver) {
|
|
20637
|
+
var _a;
|
|
20638
|
+
const mid = (_a = this.pcManager) === null || _a === void 0 ? void 0 : _a.getMidForReceiver(receiver);
|
|
20639
|
+
if (mid) {
|
|
20640
|
+
const match = Object.entries(this.midToTrackId).find(_ref2 => {
|
|
20641
|
+
let [key] = _ref2;
|
|
20642
|
+
return key === mid;
|
|
20643
|
+
});
|
|
20644
|
+
if (match) {
|
|
20645
|
+
return match[1];
|
|
20646
|
+
}
|
|
20647
|
+
}
|
|
20648
|
+
}
|
|
20572
20649
|
}
|
|
20573
20650
|
class SignalReconnectError extends Error {}
|
|
20574
20651
|
function supportOptionalDatachannel(protocol) {
|
|
@@ -24246,10 +24323,11 @@ class LocalParticipant extends Participant {
|
|
|
24246
24323
|
destinationIdentity,
|
|
24247
24324
|
method,
|
|
24248
24325
|
payload,
|
|
24249
|
-
responseTimeout =
|
|
24326
|
+
responseTimeout = 15000
|
|
24250
24327
|
} = _ref3;
|
|
24251
24328
|
return function* () {
|
|
24252
|
-
const maxRoundTripLatency =
|
|
24329
|
+
const maxRoundTripLatency = 7000;
|
|
24330
|
+
const minEffectiveTimeout = maxRoundTripLatency + 1000;
|
|
24253
24331
|
return new Promise((resolve, reject) => __awaiter(_this5, void 0, void 0, function* () {
|
|
24254
24332
|
var _a, _b, _c, _d;
|
|
24255
24333
|
if (byteLength(payload) > MAX_PAYLOAD_BYTES) {
|
|
@@ -24260,8 +24338,9 @@ class LocalParticipant extends Participant {
|
|
|
24260
24338
|
reject(RpcError.builtIn('UNSUPPORTED_SERVER'));
|
|
24261
24339
|
return;
|
|
24262
24340
|
}
|
|
24341
|
+
const effectiveTimeout = Math.max(responseTimeout, minEffectiveTimeout);
|
|
24263
24342
|
const id = crypto.randomUUID();
|
|
24264
|
-
yield this.publishRpcRequest(destinationIdentity, id, method, payload,
|
|
24343
|
+
yield this.publishRpcRequest(destinationIdentity, id, method, payload, effectiveTimeout);
|
|
24265
24344
|
const ackTimeoutId = setTimeout(() => {
|
|
24266
24345
|
this.pendingAcks.delete(id);
|
|
24267
24346
|
reject(RpcError.builtIn('CONNECTION_TIMEOUT'));
|
|
@@ -26352,6 +26431,11 @@ class Room extends eventsExports.EventEmitter {
|
|
|
26352
26431
|
// We'll defer these events until when the room is connected or eventually disconnected.
|
|
26353
26432
|
if (this.state === ConnectionState.Connecting || this.state === ConnectionState.Reconnecting) {
|
|
26354
26433
|
const reconnectedHandler = () => {
|
|
26434
|
+
this.log.debug('deferring on track for later', {
|
|
26435
|
+
mediaTrackId: mediaTrack.id,
|
|
26436
|
+
mediaStreamId: stream.id,
|
|
26437
|
+
tracksInStream: stream.getTracks().map(track => track.id)
|
|
26438
|
+
});
|
|
26355
26439
|
this.onTrackAdded(mediaTrack, stream, receiver);
|
|
26356
26440
|
cleanup();
|
|
26357
26441
|
};
|
|
@@ -26389,6 +26473,24 @@ class Room extends eventsExports.EventEmitter {
|
|
|
26389
26473
|
this.log.error("Tried to add a track for a participant, that's not present. Sid: ".concat(participantSid), this.logContext);
|
|
26390
26474
|
return;
|
|
26391
26475
|
}
|
|
26476
|
+
// in single peer connection case, the trackID is locally generated,
|
|
26477
|
+
// not the TR_ prefixed one generated by the server,
|
|
26478
|
+
// use `mid` to find the appropriate track.
|
|
26479
|
+
if (!trackId.startsWith('TR')) {
|
|
26480
|
+
const id = this.engine.getTrackIdForReceiver(receiver);
|
|
26481
|
+
if (!id) {
|
|
26482
|
+
this.log.error("Tried to add a track whose 'sid' could not be found for a participant, that's not present. Sid: ".concat(participantSid), this.logContext);
|
|
26483
|
+
return;
|
|
26484
|
+
}
|
|
26485
|
+
trackId = id;
|
|
26486
|
+
}
|
|
26487
|
+
if (!trackId.startsWith('TR')) {
|
|
26488
|
+
this.log.warn("Tried to add a track whose 'sid' could not be determined for a participant, that's not present. Sid: ".concat(participantSid, ", streamId: ").concat(streamId, ", trackId: ").concat(trackId), Object.assign(Object.assign({}, this.logContext), {
|
|
26489
|
+
rpID: participantSid,
|
|
26490
|
+
streamId,
|
|
26491
|
+
trackId
|
|
26492
|
+
}));
|
|
26493
|
+
}
|
|
26392
26494
|
let adaptiveStreamSettings;
|
|
26393
26495
|
if (this.options.adaptiveStream) {
|
|
26394
26496
|
if (typeof this.options.adaptiveStream === 'object') {
|
|
@@ -26892,6 +26994,12 @@ class Room extends eventsExports.EventEmitter {
|
|
|
26892
26994
|
if (event !== RoomEvent.ActiveSpeakersChanged && event !== RoomEvent.TranscriptionReceived) {
|
|
26893
26995
|
// only extract logContext from arguments in order to avoid logging the whole object tree
|
|
26894
26996
|
const minimizedArgs = mapArgs(args).filter(arg => arg !== undefined);
|
|
26997
|
+
if (event === RoomEvent.TrackSubscribed || event === RoomEvent.TrackUnsubscribed) {
|
|
26998
|
+
this.log.trace("subscribe trace: ".concat(event), Object.assign(Object.assign({}, this.logContext), {
|
|
26999
|
+
event,
|
|
27000
|
+
args: minimizedArgs
|
|
27001
|
+
}));
|
|
27002
|
+
}
|
|
26895
27003
|
this.log.debug("room event ".concat(event), Object.assign(Object.assign({}, this.logContext), {
|
|
26896
27004
|
event,
|
|
26897
27005
|
args: minimizedArgs
|