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.
@@ -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.9";
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: 'Close method called on signal client'
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 = 10000
24326
+ responseTimeout = 15000
24250
24327
  } = _ref3;
24251
24328
  return function* () {
24252
- const maxRoundTripLatency = 2000;
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, responseTimeout - maxRoundTripLatency);
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