livekit-client 2.18.7 → 2.18.8

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.
Files changed (59) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +2 -2
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +391 -255
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/api/SignalClient.d.ts.map +1 -1
  10. package/dist/src/logger.d.ts +11 -1
  11. package/dist/src/logger.d.ts.map +1 -1
  12. package/dist/src/room/PCTransport.d.ts +13 -3
  13. package/dist/src/room/PCTransport.d.ts.map +1 -1
  14. package/dist/src/room/PCTransportManager.d.ts +3 -1
  15. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  16. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  17. package/dist/src/room/Room.d.ts.map +1 -1
  18. package/dist/src/room/data-track/LocalDataTrack.d.ts +31 -0
  19. package/dist/src/room/data-track/LocalDataTrack.d.ts.map +1 -1
  20. package/dist/src/room/data-track/RemoteDataTrack.d.ts.map +1 -1
  21. package/dist/src/room/data-track/handle.d.ts +1 -0
  22. package/dist/src/room/data-track/handle.d.ts.map +1 -1
  23. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts +4 -3
  24. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts.map +1 -1
  25. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +18 -3
  26. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts.map +1 -1
  27. package/dist/src/room/data-track/outgoing/types.d.ts +6 -0
  28. package/dist/src/room/data-track/outgoing/types.d.ts.map +1 -1
  29. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  30. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  31. package/dist/src/utils/subscribeToEvents.d.ts.map +1 -1
  32. package/dist/ts4.2/logger.d.ts +11 -1
  33. package/dist/ts4.2/room/PCTransport.d.ts +13 -3
  34. package/dist/ts4.2/room/PCTransportManager.d.ts +3 -1
  35. package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +31 -0
  36. package/dist/ts4.2/room/data-track/handle.d.ts +1 -0
  37. package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +4 -3
  38. package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +18 -3
  39. package/dist/ts4.2/room/data-track/outgoing/types.d.ts +6 -0
  40. package/package.json +1 -1
  41. package/src/api/SignalClient.ts +19 -31
  42. package/src/logger.test.ts +61 -0
  43. package/src/logger.ts +38 -4
  44. package/src/room/PCTransport.ts +26 -3
  45. package/src/room/PCTransportManager.test.ts +281 -0
  46. package/src/room/PCTransportManager.ts +45 -31
  47. package/src/room/RTCEngine.ts +34 -52
  48. package/src/room/Room.ts +37 -59
  49. package/src/room/data-track/LocalDataTrack.ts +51 -0
  50. package/src/room/data-track/RemoteDataTrack.ts +4 -1
  51. package/src/room/data-track/handle.ts +4 -0
  52. package/src/room/data-track/incoming/IncomingDataTrackManager.test.ts +72 -2
  53. package/src/room/data-track/incoming/IncomingDataTrackManager.ts +5 -3
  54. package/src/room/data-track/outgoing/OutgoingDataTrackManager.test.ts +235 -1
  55. package/src/room/data-track/outgoing/OutgoingDataTrackManager.ts +45 -3
  56. package/src/room/data-track/outgoing/types.ts +5 -0
  57. package/src/room/participant/LocalParticipant.ts +59 -144
  58. package/src/room/participant/Participant.ts +4 -1
  59. package/src/utils/subscribeToEvents.ts +11 -8
@@ -8152,16 +8152,45 @@ var LoggerNames;
8152
8152
  LoggerNames["E2EE"] = "lk-e2ee";
8153
8153
  LoggerNames["DataTracks"] = "livekit-data-tracks";
8154
8154
  })(LoggerNames || (LoggerNames = {}));
8155
- let livekitLogger = loglevelExports.getLogger('livekit');
8155
+ let livekitLogger = loglevelExports.getLogger(LoggerNames.Default);
8156
8156
  const livekitLoggers = Object.values(LoggerNames).map(name => loglevelExports.getLogger(name));
8157
8157
  livekitLogger.setDefaultLevel(LogLevel.info);
8158
8158
  /**
8159
8159
  * @internal
8160
+ *
8161
+ * Get a named logger. When `ctxFn` is supplied, every log call
8162
+ * automatically:
8163
+ * 1. prepends a `[key=value ...]` prefix derived from `ctxFn()` to the
8164
+ * message string, so identifiers are visible in browser devtools
8165
+ * without expanding the structured context object, and
8166
+ * 2. merges `ctxFn()` into the structured context passed to any
8167
+ * `setLogExtension` consumer, so ingestion pipelines continue to
8168
+ * receive the full metadata unchanged.
8160
8169
  */
8161
- function getLogger(name) {
8170
+ function getLogger(name, ctxFn) {
8162
8171
  const logger = loglevelExports.getLogger(name);
8163
8172
  logger.setDefaultLevel(livekitLogger.getLevel());
8164
- return logger;
8173
+ if (!ctxFn) {
8174
+ return logger;
8175
+ }
8176
+ return wrapWithContext(logger, ctxFn);
8177
+ }
8178
+ function wrapWithContext(base, ctxFn) {
8179
+ // Resolve the underlying method on every call so that later
8180
+ // setLogExtension installations (which replace the base logger's
8181
+ // methods via loglevel's methodFactory) are picked up.
8182
+ const wrap = method => (msg, extra) => {
8183
+ const ctx = ctxFn();
8184
+ const merged = ctx || extra ? Object.assign(Object.assign({}, ctx), extra) : undefined;
8185
+ base[method](msg, merged);
8186
+ };
8187
+ const proxy = Object.create(base);
8188
+ proxy.trace = wrap('trace');
8189
+ proxy.debug = wrap('debug');
8190
+ proxy.info = wrap('info');
8191
+ proxy.warn = wrap('warn');
8192
+ proxy.error = wrap('error');
8193
+ return proxy;
8165
8194
  }
8166
8195
  function setLogLevel(level, loggerName) {
8167
8196
  if (loggerName) {
@@ -8194,7 +8223,7 @@ function setLogExtension(extension, logger) {
8194
8223
  logR.setLevel(logR.getLevel());
8195
8224
  });
8196
8225
  }
8197
- const workerLogger = loglevelExports.getLogger('lk-e2ee');const maxRetryDelay = 7000;
8226
+ const workerLogger = loglevelExports.getLogger(LoggerNames.E2EE);const maxRetryDelay = 7000;
8198
8227
  const DEFAULT_RETRY_DELAYS_IN_MS = [0, 300, 2 * 2 * 300, 3 * 3 * 300, 4 * 4 * 300, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay, maxRetryDelay];
8199
8228
  class DefaultReconnectPolicy {
8200
8229
  constructor(retryDelays) {
@@ -11744,7 +11773,7 @@ function getMatch(exp, ua) {
11744
11773
  }
11745
11774
  function getOSVersion(ua) {
11746
11775
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
11747
- }var version$1 = "2.18.7";const version = version$1;
11776
+ }var version$1 = "2.18.8";const version = version$1;
11748
11777
  const protocolVersion = 16;/** Base error that all LiveKit specific custom errors inherit from. */
11749
11778
  class LivekitError extends Error {
11750
11779
  constructor(code, message, options) {
@@ -15115,6 +15144,9 @@ class DataTrackHandleAllocator {
15115
15144
  }
15116
15145
  return this.value;
15117
15146
  }
15147
+ reset() {
15148
+ this.value = 0;
15149
+ }
15118
15150
  }const DataTrackInfo = {
15119
15151
  from(protocolInfo) {
15120
15152
  return {
@@ -15328,8 +15360,8 @@ class SignalClient {
15328
15360
  this.onClose = undefined;
15329
15361
  this.onMediaSectionsRequirement = undefined;
15330
15362
  };
15331
- this.log = getLogger((_a = loggerOptions.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Signal);
15332
15363
  this.loggerContextCb = loggerOptions.loggerContextCb;
15364
+ this.log = getLogger((_a = loggerOptions.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Signal, () => this.logContext);
15333
15365
  this.useJSON = useJSON;
15334
15366
  this.requestQueue = new AsyncQueue();
15335
15367
  this.queuedRequests = [];
@@ -15359,7 +15391,7 @@ class SignalClient {
15359
15391
  reconnect(url, token, sid, reason) {
15360
15392
  return __awaiter(this, void 0, void 0, function* () {
15361
15393
  if (!this.options) {
15362
- this.log.warn('attempted to reconnect without signal options being set, ignoring', this.logContext);
15394
+ this.log.warn('attempted to reconnect without signal options being set, ignoring');
15363
15395
  return;
15364
15396
  }
15365
15397
  this.state = SignalConnectionState.RECONNECTING;
@@ -15424,10 +15456,10 @@ class SignalClient {
15424
15456
  if (redactedUrl.searchParams.has('access_token')) {
15425
15457
  redactedUrl.searchParams.set('access_token', '<redacted>');
15426
15458
  }
15427
- this.log.debug("connecting to ".concat(redactedUrl), Object.assign({
15459
+ this.log.info("signal connecting to ".concat(redactedUrl), {
15428
15460
  reconnect: opts.reconnect,
15429
15461
  reconnectReason: opts.reconnectReason
15430
- }, this.logContext));
15462
+ });
15431
15463
  if (this.ws) {
15432
15464
  yield this.close(false);
15433
15465
  }
@@ -15439,12 +15471,12 @@ class SignalClient {
15439
15471
  reject(ConnectionError.internal("Websocket got closed during a (re)connection attempt: ".concat(closeInfo.reason)));
15440
15472
  }
15441
15473
  if (closeInfo.closeCode !== 1000) {
15442
- this.log.warn("websocket closed", Object.assign(Object.assign({}, this.logContext), {
15474
+ this.log.warn("websocket closed", {
15443
15475
  reason: closeInfo.reason,
15444
15476
  code: closeInfo.closeCode,
15445
15477
  wasClean: closeInfo.closeCode === 1000,
15446
15478
  state: this.state
15447
- }));
15479
+ });
15448
15480
  if (this.state === SignalConnectionState.CONNECTED) {
15449
15481
  this.handleOnClose((_a = closeInfo.reason) !== null && _a !== void 0 ? _a : 'Unexpected WS error');
15450
15482
  }
@@ -15492,10 +15524,10 @@ class SignalClient {
15492
15524
  this.pingTimeoutDuration = firstSignalResponse.message.value.pingTimeout;
15493
15525
  this.pingIntervalDuration = firstSignalResponse.message.value.pingInterval;
15494
15526
  if (this.pingTimeoutDuration && this.pingTimeoutDuration > 0) {
15495
- this.log.debug('ping config', Object.assign(Object.assign({}, this.logContext), {
15527
+ this.log.debug('ping config', {
15496
15528
  timeout: this.pingTimeoutDuration,
15497
15529
  interval: this.pingIntervalDuration
15498
- }));
15530
+ });
15499
15531
  }
15500
15532
  if (this.onJoined) {
15501
15533
  this.onJoined(firstSignalResponse.message.value);
@@ -15566,9 +15598,9 @@ class SignalClient {
15566
15598
  yield Promise.race([closePromise, sleep(MAX_WS_CLOSE_TIME)]);
15567
15599
  }
15568
15600
  } catch (e) {
15569
- _this3.log.debug('websocket error while closing', Object.assign(Object.assign({}, _this3.logContext), {
15601
+ _this3.log.debug('websocket error while closing', {
15570
15602
  error: e
15571
- }));
15603
+ });
15572
15604
  } finally {
15573
15605
  if (updateState) {
15574
15606
  _this3.state = SignalConnectionState.DISCONNECTED;
@@ -15580,9 +15612,9 @@ class SignalClient {
15580
15612
  }
15581
15613
  // initial offer after joining
15582
15614
  sendOffer(offer, offerId) {
15583
- this.log.debug('sending offer', Object.assign(Object.assign({}, this.logContext), {
15615
+ this.log.debug('sending offer', {
15584
15616
  offerSdp: offer.sdp
15585
- }));
15617
+ });
15586
15618
  this.sendRequest({
15587
15619
  case: 'offer',
15588
15620
  value: toProtoSessionDescription(offer, offerId)
@@ -15590,18 +15622,18 @@ class SignalClient {
15590
15622
  }
15591
15623
  // answer a server-initiated offer
15592
15624
  sendAnswer(answer, offerId) {
15593
- this.log.debug('sending answer', Object.assign(Object.assign({}, this.logContext), {
15625
+ this.log.debug('sending answer', {
15594
15626
  answerSdp: answer.sdp
15595
- }));
15627
+ });
15596
15628
  return this.sendRequest({
15597
15629
  case: 'answer',
15598
15630
  value: toProtoSessionDescription(answer, offerId)
15599
15631
  });
15600
15632
  }
15601
15633
  sendIceCandidate(candidate, target) {
15602
- this.log.debug('sending ice candidate', Object.assign(Object.assign({}, this.logContext), {
15634
+ this.log.debug('sending ice candidate', {
15603
15635
  candidate
15604
- }));
15636
+ });
15605
15637
  return this.sendRequest({
15606
15638
  case: 'trickle',
15607
15639
  value: new TrickleRequest({
@@ -15776,7 +15808,7 @@ class SignalClient {
15776
15808
  return;
15777
15809
  }
15778
15810
  if (!_this5.streamWriter) {
15779
- _this5.log.error("cannot send signal request before connected, type: ".concat(message === null || message === void 0 ? void 0 : message.case), _this5.logContext);
15811
+ _this5.log.error("cannot send signal request before connected, type: ".concat(message === null || message === void 0 ? void 0 : message.case));
15780
15812
  return;
15781
15813
  }
15782
15814
  const req = new SignalRequest({
@@ -15789,9 +15821,9 @@ class SignalClient {
15789
15821
  yield _this5.streamWriter.write(req.toBinary());
15790
15822
  }
15791
15823
  } catch (e) {
15792
- _this5.log.error('error sending signal message', Object.assign(Object.assign({}, _this5.logContext), {
15824
+ _this5.log.error('error sending signal message', {
15793
15825
  error: e
15794
- }));
15826
+ });
15795
15827
  }
15796
15828
  }();
15797
15829
  });
@@ -15800,7 +15832,7 @@ class SignalClient {
15800
15832
  var _a, _b;
15801
15833
  const msg = res.message;
15802
15834
  if (msg == undefined) {
15803
- this.log.debug('received unsupported message', this.logContext);
15835
+ this.log.debug('received unsupported message');
15804
15836
  return;
15805
15837
  }
15806
15838
  let pingHandled = false;
@@ -15907,9 +15939,9 @@ class SignalClient {
15907
15939
  this.onDataTrackSubscriberHandles(msg.value);
15908
15940
  }
15909
15941
  } else {
15910
- this.log.debug('unsupported message', Object.assign(Object.assign({}, this.logContext), {
15942
+ this.log.debug('unsupported message', {
15911
15943
  msgCase: msg.case
15912
- }));
15944
+ });
15913
15945
  }
15914
15946
  if (!pingHandled) {
15915
15947
  this.resetPingTimeout();
@@ -15928,18 +15960,18 @@ class SignalClient {
15928
15960
  if (this.state === SignalConnectionState.DISCONNECTED) return;
15929
15961
  const onCloseCallback = this.onClose;
15930
15962
  yield this.close(undefined, reason);
15931
- this.log.debug("websocket connection closed: ".concat(reason), Object.assign(Object.assign({}, this.logContext), {
15963
+ this.log.info("websocket connection closed: ".concat(reason), {
15932
15964
  reason
15933
- }));
15965
+ });
15934
15966
  if (onCloseCallback) {
15935
15967
  onCloseCallback(reason);
15936
15968
  }
15937
15969
  });
15938
15970
  }
15939
15971
  handleWSError(error) {
15940
- this.log.error('websocket error', Object.assign(Object.assign({}, this.logContext), {
15972
+ this.log.error('websocket error', {
15941
15973
  error
15942
- }));
15974
+ });
15943
15975
  }
15944
15976
  /**
15945
15977
  * Resets the ping timeout and starts a new timeout.
@@ -15948,11 +15980,11 @@ class SignalClient {
15948
15980
  resetPingTimeout() {
15949
15981
  this.clearPingTimeout();
15950
15982
  if (!this.pingTimeoutDuration) {
15951
- this.log.warn('ping timeout duration not set', this.logContext);
15983
+ this.log.warn('ping timeout duration not set');
15952
15984
  return;
15953
15985
  }
15954
15986
  this.pingTimeout = CriticalTimers.setTimeout(() => {
15955
- this.log.warn("ping timeout triggered. last pong received at: ".concat(new Date(Date.now() - this.pingTimeoutDuration * 1000).toUTCString()), this.logContext);
15987
+ this.log.warn("ping timeout triggered. last pong received at: ".concat(new Date(Date.now() - this.pingTimeoutDuration * 1000).toUTCString()));
15956
15988
  this.handleOnClose('ping timeout');
15957
15989
  }, this.pingTimeoutDuration * 1000);
15958
15990
  }
@@ -15968,16 +16000,16 @@ class SignalClient {
15968
16000
  this.clearPingInterval();
15969
16001
  this.resetPingTimeout();
15970
16002
  if (!this.pingIntervalDuration) {
15971
- this.log.warn('ping interval duration not set', this.logContext);
16003
+ this.log.warn('ping interval duration not set');
15972
16004
  return;
15973
16005
  }
15974
- this.log.debug('start ping interval', this.logContext);
16006
+ this.log.debug('start ping interval');
15975
16007
  this.pingInterval = CriticalTimers.setInterval(() => {
15976
16008
  this.sendPing();
15977
16009
  }, this.pingIntervalDuration * 1000);
15978
16010
  }
15979
16011
  clearPingInterval() {
15980
- this.log.debug('clearing ping interval', this.logContext);
16012
+ this.log.debug('clearing ping interval');
15981
16013
  this.clearPingTimeout();
15982
16014
  if (this.pingInterval) {
15983
16015
  CriticalTimers.clearInterval(this.pingInterval);
@@ -15992,6 +16024,7 @@ class SignalClient {
15992
16024
  */
15993
16025
  handleSignalConnected(connection, timeoutHandle, firstMessage) {
15994
16026
  this.state = SignalConnectionState.CONNECTED;
16027
+ this.log.info('signal connected');
15995
16028
  clearTimeout(timeoutHandle);
15996
16029
  this.startPingInterval();
15997
16030
  this.startReadingLoop(connection.readable.getReader(), firstMessage);
@@ -16018,7 +16051,7 @@ class SignalClient {
16018
16051
  };
16019
16052
  } else {
16020
16053
  // in reconnecting, any message received means signal reconnected and we still need to process it
16021
- this.log.debug('declaring signal reconnected without reconnect response received', this.logContext);
16054
+ this.log.debug('declaring signal reconnected without reconnect response received');
16022
16055
  return {
16023
16056
  isValid: true,
16024
16057
  response: undefined,
@@ -17124,6 +17157,11 @@ const debounceInterval = 20;
17124
17157
  const PCEvents = {
17125
17158
  NegotiationStarted: 'negotiationStarted',
17126
17159
  NegotiationComplete: 'negotiationComplete',
17160
+ // Fired with the offerId for every successful publisher answer application,
17161
+ // including answers that immediately recurse into another offer via
17162
+ // `renegotiate`. Use this rather than NegotiationComplete to know that a
17163
+ // specific offer has been negotiated end-to-end.
17164
+ OfferAnswered: 'offerAnswered',
17127
17165
  RTPVideoPayloadTypes: 'rtpVideoPayloadTypes'
17128
17166
  };
17129
17167
  /** @internal */
@@ -17141,6 +17179,7 @@ class PCTransport extends eventsExports.EventEmitter {
17141
17179
  this.log = livekitLogger;
17142
17180
  this.ddExtID = 0;
17143
17181
  this.latestOfferId = 0;
17182
+ this.latestAcknowledgedOfferId = 0;
17144
17183
  this.pendingCandidates = [];
17145
17184
  this.restartingIce = false;
17146
17185
  this.renegotiate = false;
@@ -17313,6 +17352,13 @@ class PCTransport extends eventsExports.EventEmitter {
17313
17352
  });
17314
17353
  this.pendingCandidates = [];
17315
17354
  this.restartingIce = false;
17355
+ // Fire OfferAnswered for every successfully applied answer, including the
17356
+ // ones that recurse into another offer via `renegotiate`. Callers waiting
17357
+ // on a specific offerId can resolve as soon as their offer's answer is in.
17358
+ if (sd.type === 'answer') {
17359
+ this.latestAcknowledgedOfferId = offerId;
17360
+ this.emit(PCEvents.OfferAnswered, offerId);
17361
+ }
17316
17362
  if (this.renegotiate) {
17317
17363
  this.renegotiate = false;
17318
17364
  yield this.createAndSendOffer();
@@ -17984,41 +18030,47 @@ class PCTransportManager {
17984
18030
  }
17985
18031
  negotiate(abortController) {
17986
18032
  return __awaiter(this, void 0, void 0, function* () {
17987
- return new TypedPromise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
17988
- let negotiationTimeout = setTimeout(() => {
17989
- reject(new NegotiationError('negotiation timed out'));
17990
- }, this.peerConnectionTimeout);
18033
+ return new TypedPromise((resolve, reject) => {
18034
+ // Capture the publisher's latest offer id at request time. We are done
18035
+ // when an offer with a higher id has had its answer successfully
18036
+ // applied — that offer is the one that includes any transceiver/SDP
18037
+ // changes that motivated this negotiate call. Concurrent callers each
18038
+ // get their own checkpoint and resolve independently.
18039
+ const checkpoint = this.publisher.latestOfferId;
18040
+ // Race: an answer past our checkpoint already arrived before we had a
18041
+ // chance to subscribe.
18042
+ if (this.publisher.latestAcknowledgedOfferId > checkpoint) {
18043
+ this.log.debug("negotiation already handled in more recent acknowledged offer", this.logContext);
18044
+ resolve();
18045
+ return;
18046
+ }
18047
+ let cleanedUp = false;
17991
18048
  const cleanup = () => {
17992
- clearTimeout(negotiationTimeout);
17993
- this.publisher.off(PCEvents.NegotiationStarted, onNegotiationStarted);
17994
- abortController.signal.removeEventListener('abort', abortHandler);
18049
+ if (cleanedUp) return;
18050
+ cleanedUp = true;
18051
+ clearTimeout(deadlineTimer);
18052
+ this.publisher.off(PCEvents.OfferAnswered, onAnswered);
18053
+ abortController.signal.removeEventListener('abort', onAbort);
18054
+ };
18055
+ const onAnswered = offerId => {
18056
+ if (offerId > checkpoint) {
18057
+ cleanup();
18058
+ resolve();
18059
+ }
17995
18060
  };
17996
- const abortHandler = () => {
18061
+ const onAbort = () => {
17997
18062
  cleanup();
17998
18063
  reject(new NegotiationError('negotiation aborted'));
17999
18064
  };
18000
- // Reset the timeout each time a renegotiation cycle starts. This
18001
- // prevents premature timeouts when the negotiation machinery is
18002
- // actively renegotiating (offers going out, answers coming back) but
18003
- // NegotiationComplete hasn't fired yet because new requirements keep
18004
- // arriving between offer/answer round-trips.
18005
- const onNegotiationStarted = () => {
18006
- if (abortController.signal.aborted) {
18007
- return;
18008
- }
18009
- clearTimeout(negotiationTimeout);
18010
- negotiationTimeout = setTimeout(() => {
18011
- cleanup();
18012
- reject(new NegotiationError('negotiation timed out'));
18013
- }, this.peerConnectionTimeout);
18014
- };
18015
- abortController.signal.addEventListener('abort', abortHandler);
18016
- this.publisher.on(PCEvents.NegotiationStarted, onNegotiationStarted);
18017
- this.publisher.once(PCEvents.NegotiationComplete, () => {
18065
+ // Single hard deadline as a backstop. Not reset on cycle progress
18066
+ // progress is tracked via OfferAnswered, not NegotiationStarted.
18067
+ const deadlineTimer = setTimeout(() => {
18018
18068
  cleanup();
18019
- resolve();
18020
- });
18021
- yield this.publisher.negotiate(e => {
18069
+ reject(new NegotiationError('negotiation timed out'));
18070
+ }, this.peerConnectionTimeout);
18071
+ abortController.signal.addEventListener('abort', onAbort);
18072
+ this.publisher.on(PCEvents.OfferAnswered, onAnswered);
18073
+ this.publisher.negotiate(e => {
18022
18074
  cleanup();
18023
18075
  if (e instanceof Error) {
18024
18076
  reject(e);
@@ -18026,7 +18078,7 @@ class PCTransportManager {
18026
18078
  reject(new Error(String(e)));
18027
18079
  }
18028
18080
  });
18029
- }));
18081
+ });
18030
18082
  });
18031
18083
  }
18032
18084
  addPublisherTransceiver(track, transceiverInit) {
@@ -20347,7 +20399,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20347
20399
  } else {
20348
20400
  return;
20349
20401
  }
20350
- _this.log.debug("on data channel ".concat(channel.id, ", ").concat(channel.label), _this.logContext);
20402
+ _this.log.debug("on data channel ".concat(channel.id, ", ").concat(channel.label));
20351
20403
  channel.onmessage = handler;
20352
20404
  }();
20353
20405
  });
@@ -20363,9 +20415,9 @@ class RTCEngine extends eventsExports.EventEmitter {
20363
20415
  } else if (message.data instanceof Blob) {
20364
20416
  buffer = yield message.data.arrayBuffer();
20365
20417
  } else {
20366
- this.log.error('unsupported data type', Object.assign(Object.assign({}, this.logContext), {
20418
+ this.log.error('unsupported data type', {
20367
20419
  data: message.data
20368
- }));
20420
+ });
20369
20421
  return;
20370
20422
  }
20371
20423
  const dp = DataPacket.fromBinary(new Uint8Array(buffer));
@@ -20382,7 +20434,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20382
20434
  this.emit(EngineEvent.ActiveSpeakersUpdate, dp.value.value.speakers);
20383
20435
  } else if (((_b = dp.value) === null || _b === void 0 ? void 0 : _b.case) === 'encryptedPacket') {
20384
20436
  if (!this.e2eeManager) {
20385
- this.log.error('Received encrypted packet but E2EE not set up', this.logContext);
20437
+ this.log.error('Received encrypted packet but E2EE not set up');
20386
20438
  return;
20387
20439
  }
20388
20440
  const decryptedData = yield (_c = this.e2eeManager) === null || _c === void 0 ? void 0 : _c.handleEncryptedData(dp.value.value.encryptedValue, dp.value.value.iv, dp.participantIdentity, dp.value.value.keyIndex);
@@ -20416,9 +20468,9 @@ class RTCEngine extends eventsExports.EventEmitter {
20416
20468
  } else if (message.data instanceof Blob) {
20417
20469
  buffer = yield message.data.arrayBuffer();
20418
20470
  } else {
20419
- this.log.error('unsupported data type', Object.assign(Object.assign({}, this.logContext), {
20471
+ this.log.error('unsupported data type', {
20420
20472
  data: message.data
20421
- }));
20473
+ });
20422
20474
  return;
20423
20475
  }
20424
20476
  this.emit('dataTrackPacketReceived', new Uint8Array(buffer));
@@ -20430,13 +20482,13 @@ class RTCEngine extends eventsExports.EventEmitter {
20430
20482
  const {
20431
20483
  error
20432
20484
  } = event.error;
20433
- this.log.error("DataChannel error on ".concat(channelKind, ": ").concat(event.message), Object.assign(Object.assign({}, this.logContext), {
20485
+ this.log.error("DataChannel error on ".concat(channelKind, ": ").concat(event.message), {
20434
20486
  error
20435
- }));
20487
+ });
20436
20488
  } else {
20437
- this.log.error("Unknown DataChannel error on ".concat(channelKind), Object.assign(Object.assign({}, this.logContext), {
20489
+ this.log.error("Unknown DataChannel error on ".concat(channelKind), {
20438
20490
  event
20439
- }));
20491
+ });
20440
20492
  }
20441
20493
  };
20442
20494
  this.handleBufferedAmountLow = channelKind => {
@@ -20449,13 +20501,13 @@ class RTCEngine extends eventsExports.EventEmitter {
20449
20501
  if (this._isClosed) {
20450
20502
  return;
20451
20503
  }
20452
- this.log.warn("".concat(connection, " disconnected"), this.logContext);
20504
+ this.log.warn("".concat(connection, " disconnected"));
20453
20505
  if (this.reconnectAttempts === 0) {
20454
20506
  // only reset start time on the first try
20455
20507
  this.reconnectStart = Date.now();
20456
20508
  }
20457
20509
  const disconnect = duration => {
20458
- this.log.warn("could not recover connection after ".concat(this.reconnectAttempts, " attempts, ").concat(duration, "ms. giving up"), this.logContext);
20510
+ this.log.warn("could not recover connection after ".concat(this.reconnectAttempts, " attempts, ").concat(duration, "ms. giving up"));
20459
20511
  this.emit(EngineEvent.Disconnected);
20460
20512
  this.close();
20461
20513
  };
@@ -20471,7 +20523,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20471
20523
  if (connection === leaveReconnect) {
20472
20524
  delay = 0;
20473
20525
  }
20474
- this.log.debug("reconnecting in ".concat(delay, "ms"), this.logContext);
20526
+ this.log.debug("reconnecting in ".concat(delay, "ms"));
20475
20527
  this.clearReconnectTimeout();
20476
20528
  if (this.token) {
20477
20529
  // token may have been refreshed, we do not want to recreate the regionUrlProvider
@@ -20555,7 +20607,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20555
20607
  }
20556
20608
  }
20557
20609
  });
20558
- this.log = getLogger((_a = options.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Engine);
20610
+ this.log = getLogger((_a = options.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Engine, () => this.logContext);
20559
20611
  this.loggerOptions = {
20560
20612
  loggerName: options.loggerName,
20561
20613
  loggerContextCb: () => this.logContext
@@ -20599,7 +20651,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20599
20651
  var _this2 = this;
20600
20652
  let useV0Path = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
20601
20653
  return function* () {
20602
- var _a, _b, _c, _d, _e, _f;
20654
+ var _a, _b, _c;
20603
20655
  _this2._isNewlyCreated = false;
20604
20656
  _this2.url = url;
20605
20657
  _this2.token = token;
@@ -20641,7 +20693,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20641
20693
  // create offer
20642
20694
  if (!_this2.subscriberPrimary || joinResponse.fastPublish) {
20643
20695
  _this2.negotiate().catch(err => {
20644
- livekitLogger.error(err, _this2.logContext);
20696
+ _this2.log.error(err);
20645
20697
  });
20646
20698
  }
20647
20699
  }
@@ -20655,14 +20707,10 @@ class RTCEngine extends eventsExports.EventEmitter {
20655
20707
  region: joinResponse.serverRegion
20656
20708
  };
20657
20709
  }
20658
- _this2.log.debug("connected to Livekit Server ".concat(Object.entries(serverInfo).map(_ref2 => {
20710
+ _this2.log.info("connected to Livekit Server ".concat(Object.entries(serverInfo).map(_ref2 => {
20659
20711
  let [key, value] = _ref2;
20660
20712
  return "".concat(key, ": ").concat(value);
20661
- }).join(', ')), {
20662
- room: (_d = joinResponse.room) === null || _d === void 0 ? void 0 : _d.name,
20663
- roomSid: (_e = joinResponse.room) === null || _e === void 0 ? void 0 : _e.sid,
20664
- identity: (_f = joinResponse.participant) === null || _f === void 0 ? void 0 : _f.identity
20665
- });
20713
+ }).join(', ')));
20666
20714
  return {
20667
20715
  joinResponse,
20668
20716
  serverInfo
@@ -20670,7 +20718,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20670
20718
  } catch (e) {
20671
20719
  if (e instanceof ConnectionError) {
20672
20720
  if (e.reason === ConnectionErrorReason.ServerUnreachable) {
20673
- _this2.log.warn("Couldn't connect to server, attempt ".concat(_this2.joinAttempts, " of ").concat(_this2.maxJoinAttempts), _this2.logContext);
20721
+ _this2.log.warn("Couldn't connect to server, attempt ".concat(_this2.joinAttempts, " of ").concat(_this2.maxJoinAttempts));
20674
20722
  if (_this2.joinAttempts < _this2.maxJoinAttempts) {
20675
20723
  return _this2.join(url, token, opts, abortSignal, useV0Path);
20676
20724
  }
@@ -20807,9 +20855,9 @@ class RTCEngine extends eventsExports.EventEmitter {
20807
20855
  this.pcManager.removeTrack(sender);
20808
20856
  return true;
20809
20857
  } catch (e) {
20810
- this.log.warn('failed to remove track', Object.assign(Object.assign({}, this.logContext), {
20858
+ this.log.warn('failed to remove track', {
20811
20859
  error: e
20812
- }));
20860
+ });
20813
20861
  }
20814
20862
  return false;
20815
20863
  }
@@ -20854,7 +20902,7 @@ class RTCEngine extends eventsExports.EventEmitter {
20854
20902
  };
20855
20903
  this.pcManager.onDataChannel = this.handleDataChannel;
20856
20904
  this.pcManager.onStateChange = (connectionState, publisherState, subscriberState) => __awaiter(this, void 0, void 0, function* () {
20857
- this.log.debug("primary PC state changed ".concat(connectionState), this.logContext);
20905
+ this.log.debug("primary PC state changed ".concat(connectionState));
20858
20906
  if (['closed', 'disconnected', 'failed'].includes(publisherState)) {
20859
20907
  // reset publisher connection promise
20860
20908
  this.publisherConnectionPromise = undefined;
@@ -20893,11 +20941,11 @@ class RTCEngine extends eventsExports.EventEmitter {
20893
20941
  if (!this.pcManager) {
20894
20942
  return;
20895
20943
  }
20896
- this.log.debug('received server answer', Object.assign(Object.assign({}, this.logContext), {
20944
+ this.log.debug('received server answer', {
20897
20945
  RTCSdpType: sd.type,
20898
20946
  sdp: sd.sdp,
20899
20947
  midToTrackId
20900
- }));
20948
+ });
20901
20949
  this.midToTrackId = midToTrackId;
20902
20950
  yield this.pcManager.setPublisherAnswer(sd, offerId);
20903
20951
  });
@@ -20906,10 +20954,10 @@ class RTCEngine extends eventsExports.EventEmitter {
20906
20954
  if (!this.pcManager) {
20907
20955
  return;
20908
20956
  }
20909
- this.log.debug('got ICE candidate from peer', Object.assign(Object.assign({}, this.logContext), {
20957
+ this.log.debug('got ICE candidate from peer', {
20910
20958
  candidate,
20911
20959
  target
20912
- }));
20960
+ });
20913
20961
  this.pcManager.addIceCandidate(candidate, target);
20914
20962
  };
20915
20963
  // when server creates an offer for the client
@@ -20926,14 +20974,14 @@ class RTCEngine extends eventsExports.EventEmitter {
20926
20974
  });
20927
20975
  this.client.onLocalTrackPublished = res => {
20928
20976
  var _a;
20929
- this.log.debug('received trackPublishedResponse', Object.assign(Object.assign({}, this.logContext), {
20977
+ this.log.debug('received trackPublishedResponse', {
20930
20978
  cid: res.cid,
20931
20979
  track: (_a = res.track) === null || _a === void 0 ? void 0 : _a.sid
20932
- }));
20980
+ });
20933
20981
  if (!this.pendingTrackResolvers[res.cid]) {
20934
- this.log.error("missing track resolver for ".concat(res.cid), Object.assign(Object.assign({}, this.logContext), {
20982
+ this.log.error("missing track resolver for ".concat(res.cid), {
20935
20983
  cid: res.cid
20936
- }));
20984
+ });
20937
20985
  return;
20938
20986
  }
20939
20987
  const {
@@ -20983,11 +21031,11 @@ class RTCEngine extends eventsExports.EventEmitter {
20983
21031
  this.handleDisconnect('signal', ReconnectReason.RR_SIGNAL_DISCONNECTED);
20984
21032
  };
20985
21033
  this.client.onLeave = leave => {
20986
- this.log.debug('client leave request', Object.assign(Object.assign({}, this.logContext), {
21034
+ this.log.info("client leave request received (action=".concat(leave === null || leave === void 0 ? void 0 : leave.action, ")"), {
20987
21035
  reason: leave === null || leave === void 0 ? void 0 : leave.reason
20988
- }));
21036
+ });
20989
21037
  if (leave.regions) {
20990
- this.log.debug('updating regions', this.logContext);
21038
+ this.log.debug('updating regions');
20991
21039
  this.emit(EngineEvent.ServerRegionsReported, leave.regions);
20992
21040
  }
20993
21041
  switch (leave.action) {
@@ -21010,7 +21058,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21010
21058
  var _a;
21011
21059
  const rtcConfig = Object.assign({}, this.rtcConfig);
21012
21060
  if ((_a = this.signalOpts) === null || _a === void 0 ? void 0 : _a.e2eeEnabled) {
21013
- this.log.debug('E2EE - setting up transports with insertable streams', this.logContext);
21061
+ this.log.debug('E2EE - setting up transports with insertable streams');
21014
21062
  // this makes sure that no data is sent before the transforms are ready
21015
21063
  // @ts-ignore
21016
21064
  rtcConfig.encodedInsertableStreams = true;
@@ -21118,7 +21166,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21118
21166
  return sender;
21119
21167
  }
21120
21168
  if (supportsAddTrack()) {
21121
- this.log.warn('using add-track fallback', this.logContext);
21169
+ this.log.warn('using add-track fallback');
21122
21170
  const sender = yield this.createRTCRtpSender(track.mediaStreamTrack);
21123
21171
  return sender;
21124
21172
  }
@@ -21132,7 +21180,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21132
21180
  return this.createSimulcastTransceiverSender(track, simulcastTrack, opts, encodings);
21133
21181
  }
21134
21182
  if (supportsAddTrack()) {
21135
- this.log.debug('using add-track fallback', this.logContext);
21183
+ this.log.debug('using add-track fallback');
21136
21184
  return this.createRTCRtpSender(track.mediaStreamTrack);
21137
21185
  }
21138
21186
  throw new UnexpectedConnectionState('Cannot stream on this device');
@@ -21198,7 +21246,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21198
21246
  }
21199
21247
  // guard for attempting reconnection multiple times while one attempt is still not finished
21200
21248
  if (this.attemptingReconnect) {
21201
- livekitLogger.warn('already attempting reconnect, returning early', this.logContext);
21249
+ this.log.warn('already attempting reconnect, returning early');
21202
21250
  return;
21203
21251
  }
21204
21252
  if (((_a = this.clientConfiguration) === null || _a === void 0 ? void 0 : _a.resumeConnection) === ClientConfigSetting.DISABLED ||
@@ -21220,9 +21268,9 @@ class RTCEngine extends eventsExports.EventEmitter {
21220
21268
  this.reconnectAttempts += 1;
21221
21269
  let recoverable = true;
21222
21270
  if (e instanceof UnexpectedConnectionState) {
21223
- this.log.debug('received unrecoverable error', Object.assign(Object.assign({}, this.logContext), {
21271
+ this.log.debug('received unrecoverable error', {
21224
21272
  error: e
21225
- }));
21273
+ });
21226
21274
  // unrecoverable
21227
21275
  recoverable = false;
21228
21276
  } else if (!(e instanceof SignalReconnectError)) {
@@ -21232,7 +21280,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21232
21280
  if (recoverable) {
21233
21281
  this.handleDisconnect('reconnect', ReconnectReason.RR_UNKNOWN);
21234
21282
  } else {
21235
- this.log.info("could not recover connection after ".concat(this.reconnectAttempts, " attempts, ").concat(Date.now() - this.reconnectStart, "ms. giving up"), this.logContext);
21283
+ this.log.info("could not recover connection after ".concat(this.reconnectAttempts, " attempts, ").concat(Date.now() - this.reconnectStart, "ms. giving up"));
21236
21284
  this.emit(EngineEvent.Disconnected);
21237
21285
  yield this.close();
21238
21286
  }
@@ -21245,9 +21293,9 @@ class RTCEngine extends eventsExports.EventEmitter {
21245
21293
  try {
21246
21294
  return this.reconnectPolicy.nextRetryDelayInMs(context);
21247
21295
  } catch (e) {
21248
- this.log.warn('encountered error in reconnect policy', Object.assign(Object.assign({}, this.logContext), {
21296
+ this.log.warn('encountered error in reconnect policy', {
21249
21297
  error: e
21250
- }));
21298
+ });
21251
21299
  }
21252
21300
  // error in user code with provided reconnect policy, stop reconnecting
21253
21301
  return null;
@@ -21260,7 +21308,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21260
21308
  // permanent failure, don't attempt reconnection
21261
21309
  throw new UnexpectedConnectionState('could not reconnect, url or token not saved');
21262
21310
  }
21263
- this.log.info("reconnecting, attempt: ".concat(this.reconnectAttempts), this.logContext);
21311
+ this.log.info("reconnecting, attempt: ".concat(this.reconnectAttempts));
21264
21312
  this.emit(EngineEvent.Restarting);
21265
21313
  if (!this.client.isDisconnected) {
21266
21314
  yield this.client.sendLeave();
@@ -21270,7 +21318,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21270
21318
  let joinResponse;
21271
21319
  try {
21272
21320
  if (!this.signalOpts) {
21273
- this.log.warn('attempted connection restart, without signal options present', this.logContext);
21321
+ this.log.warn('attempted connection restart, without signal options present');
21274
21322
  throw new SignalReconnectError();
21275
21323
  }
21276
21324
  // in case a regionUrl is passed, the region URL takes precedence
@@ -21319,7 +21367,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21319
21367
  if (!this.pcManager) {
21320
21368
  throw new UnexpectedConnectionState('publisher and subscriber connections unset');
21321
21369
  }
21322
- this.log.info("resuming signal connection, attempt ".concat(this.reconnectAttempts), this.logContext);
21370
+ this.log.info("resuming signal connection, attempt ".concat(this.reconnectAttempts));
21323
21371
  this.emit(EngineEvent.Resuming);
21324
21372
  let res;
21325
21373
  try {
@@ -21329,9 +21377,9 @@ class RTCEngine extends eventsExports.EventEmitter {
21329
21377
  let message = '';
21330
21378
  if (error instanceof Error) {
21331
21379
  message = error.message;
21332
- this.log.error(error.message, Object.assign(Object.assign({}, this.logContext), {
21380
+ this.log.error(error.message, {
21333
21381
  error
21334
- }));
21382
+ });
21335
21383
  }
21336
21384
  if (error instanceof ConnectionError && error.reason === ConnectionErrorReason.NotAllowed) {
21337
21385
  throw new UnexpectedConnectionState('could not reconnect, token might be expired');
@@ -21349,7 +21397,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21349
21397
  this.latestJoinResponse.serverInfo = res.serverInfo;
21350
21398
  }
21351
21399
  } else {
21352
- this.log.warn('Did not receive reconnect response', this.logContext);
21400
+ this.log.warn('Did not receive reconnect response');
21353
21401
  }
21354
21402
  if (this.shouldFailNext) {
21355
21403
  this.shouldFailNext = false;
@@ -21385,7 +21433,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21385
21433
  waitForPCReconnected() {
21386
21434
  return __awaiter(this, void 0, void 0, function* () {
21387
21435
  this.pcState = PCState.Reconnecting;
21388
- this.log.debug('waiting for peer connection to reconnect', this.logContext);
21436
+ this.log.debug('waiting for peer connection to reconnect');
21389
21437
  try {
21390
21438
  yield sleep(minReconnectWait); // FIXME setTimeout again not ideal for a connection critical path
21391
21439
  if (!this.pcManager) {
@@ -21507,7 +21555,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21507
21555
  // Drop messages to reduce latency
21508
21556
  _this3.lossyDataDropCount += 1;
21509
21557
  if (_this3.lossyDataDropCount % 100 === 0) {
21510
- _this3.log.warn("dropping lossy data channel messages, total dropped: ".concat(_this3.lossyDataDropCount), _this3.logContext);
21558
+ _this3.log.warn("dropping lossy data channel messages, total dropped: ".concat(_this3.lossyDataDropCount));
21511
21559
  }
21512
21560
  return;
21513
21561
  }
@@ -21585,7 +21633,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21585
21633
  if (needNegotiation) {
21586
21634
  // start negotiation
21587
21635
  _this4.negotiate().catch(err => {
21588
- livekitLogger.error(err, _this4.logContext);
21636
+ _this4.log.error(err);
21589
21637
  });
21590
21638
  }
21591
21639
  const targetChannel = _this4.dataChannelForKind(kind, subscriber);
@@ -21644,7 +21692,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21644
21692
  const abortController = new AbortController();
21645
21693
  const handleClosed = () => {
21646
21694
  abortController.abort();
21647
- this.log.debug('engine disconnected while negotiation was ongoing', this.logContext);
21695
+ this.log.debug('engine disconnected while negotiation was ongoing');
21648
21696
  resolve();
21649
21697
  return;
21650
21698
  };
@@ -21715,7 +21763,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21715
21763
  sendSyncState(remoteTracks, localTracks, localDataTrackInfos) {
21716
21764
  var _a, _b, _c, _d;
21717
21765
  if (!this.pcManager) {
21718
- this.log.warn('sync state cannot be sent without peer connection setup', this.logContext);
21766
+ this.log.warn('sync state cannot be sent without peer connection setup');
21719
21767
  return;
21720
21768
  }
21721
21769
  const previousPublisherOffer = this.pcManager.publisher.getLocalDescription();
@@ -23163,7 +23211,10 @@ const DataTrackSymbol = Symbol.for('lk.data-track');class RemoteDataTrack {
23163
23211
  */
23164
23212
  subscribe(options) {
23165
23213
  try {
23166
- const [stream] = this.manager.openSubscriptionStream(this.info.sid, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.bufferSize);
23214
+ const [stream, sfuSubscriptionComplete] = this.manager.openSubscriptionStream(this.info.sid, options === null || options === void 0 ? void 0 : options.signal, options === null || options === void 0 ? void 0 : options.bufferSize);
23215
+ // Prevent uncaught promise rejections from bubbling up if rejections occur after the
23216
+ // readable stream is discarded.
23217
+ sfuSubscriptionComplete.catch(() => {});
23167
23218
  return stream;
23168
23219
  } catch (err) {
23169
23220
  // NOTE: Rethrow errors to break Throws<...> type boundary
@@ -23704,7 +23755,7 @@ class IncomingDataTrackManager extends eventsExports.EventEmitter {
23704
23755
  *
23705
23756
  * This is an index that allows track descriptors to be looked up
23706
23757
  * by subscriber handle in O(1) time, to make routing incoming packets
23707
- * a (hot code path) faster.
23758
+ * (a hot code path) faster.
23708
23759
  */
23709
23760
  this.subscriptionHandles = new Map();
23710
23761
  this.e2eeManager = (_a = options === null || options === void 0 ? void 0 : options.e2eeManager) !== null && _a !== void 0 ? _a : null;
@@ -24188,8 +24239,9 @@ class IncomingDataTrackManager extends eventsExports.EventEmitter {
24188
24239
  }
24189
24240
  }
24190
24241
  }
24191
- /** Shutdown the manager, ending any subscriptions. */
24192
- shutdown() {
24242
+ /** Resets the manager, ending any subscriptions, and getting it ready for the next room
24243
+ * connection. */
24244
+ reset() {
24193
24245
  var _a, _b;
24194
24246
  for (const descriptor of this.descriptors.values()) {
24195
24247
  this.emit('trackUnpublished', {
@@ -24204,6 +24256,7 @@ class IncomingDataTrackManager extends eventsExports.EventEmitter {
24204
24256
  }
24205
24257
  }
24206
24258
  this.descriptors.clear();
24259
+ this.subscriptionHandles.clear();
24207
24260
  }
24208
24261
  }class DataTrackPacketizerError extends LivekitReasonedError {
24209
24262
  constructor(message, reason, options) {
@@ -24402,9 +24455,26 @@ class DataTrackOutgoingPipelineError extends LivekitReasonedError {
24402
24455
  /** Represents the currently active {@link DataTrackHandle} for the publication. */
24403
24456
  this.handle = null;
24404
24457
  this.log = livekitLogger;
24458
+ /** Resolves once the data track has sent all pending packets the rtc data channel buffer. */
24459
+ this.flushedFuture = new Future();
24460
+ this.handleManagerReset = () => {
24461
+ // When the associated manager resets, mark any in flight flushes as complete
24462
+ // There's nothing actionable a user can do to get these to complete so no
24463
+ // error is being thrown.
24464
+ this.handleManagerPacketsFlushed();
24465
+ this.manager.off('packetsFlushed', this.handleManagerReset);
24466
+ this.manager.off('reset', this.handleManagerReset);
24467
+ };
24468
+ this.handleManagerPacketsFlushed = () => {
24469
+ var _a, _b;
24470
+ (_b = (_a = this.flushedFuture).resolve) === null || _b === void 0 ? void 0 : _b.call(_a);
24471
+ this.flushedFuture = new Future();
24472
+ };
24405
24473
  this.options = options;
24406
24474
  this.manager = manager;
24407
24475
  this.log = getLogger(LoggerNames.DataTracks);
24476
+ this.manager.on('packetsFlushed', this.handleManagerPacketsFlushed);
24477
+ this.manager.on('reset', this.handleManagerReset);
24408
24478
  }
24409
24479
  /** @internal */
24410
24480
  static withExplicitHandle(options, manager, handle) {
@@ -24465,6 +24535,36 @@ class DataTrackOutgoingPipelineError extends LivekitReasonedError {
24465
24535
  throw err;
24466
24536
  }
24467
24537
  }
24538
+ /**
24539
+ * When called, waits for all in flight packets to be sent before resolving.
24540
+ *
24541
+ * Use this to:
24542
+ *
24543
+ * 1. Send frames exactly in order:
24544
+ * ```ts
24545
+ * await track.tryPush(/* ... *\/);
24546
+ * await track.flush();
24547
+ * await track.tryPush(/* ... *\/);
24548
+ * await track.flush();
24549
+ * // ... etc ...
24550
+ * ```
24551
+ *
24552
+ * 2. Wait for frames to all be delivered before unpublishing a local data track:
24553
+ *
24554
+ * ```ts
24555
+ * await track.tryPush(/* ... *\/);
24556
+ * await track.tryPush(/* ... *\/);
24557
+ * await track.tryPush(/* ... *\/);
24558
+ * // ... etc ...
24559
+ * await track.flush();
24560
+ * await track.unpublish();
24561
+ * ```
24562
+ **/
24563
+ flush() {
24564
+ return __awaiter(this, void 0, void 0, function* () {
24565
+ return this.flushedFuture.promise;
24566
+ });
24567
+ }
24468
24568
  /**
24469
24569
  * Unpublish the track from the SFU. Once this is called, any further calls to {@link tryPush}
24470
24570
  * will fail.
@@ -24552,6 +24652,10 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24552
24652
  super();
24553
24653
  this.handleAllocator = new DataTrackHandleAllocator();
24554
24654
  this.descriptors = new Map();
24655
+ /** Number of packets for each data track which have been emitted via the `packetAvailable` event
24656
+ * and which have not yet been sent via the rtc data channel yet. Once this goes to 0, then
24657
+ * all in flight packets have been delivered, and the data tracks is "flushed". */
24658
+ this.inFlightPacketCounter = new Map();
24555
24659
  this.e2eeManager = (_a = options === null || options === void 0 ? void 0 : options.e2eeManager) !== null && _a !== void 0 ? _a : null;
24556
24660
  }
24557
24661
  static withDescriptors(descriptors) {
@@ -24584,6 +24688,7 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24584
24688
  tryProcessAndSend(handle, frame) {
24585
24689
  return __awaiter(this, void 0, void 0, function* () {
24586
24690
  var _a, e_1, _b, _c;
24691
+ var _d;
24587
24692
  const descriptor = this.getDescriptor(handle);
24588
24693
  if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.type) !== 'active') {
24589
24694
  throw DataTrackPushFrameError.trackUnpublished();
@@ -24596,11 +24701,14 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24596
24701
  }
24597
24702
  try {
24598
24703
  try {
24599
- for (var _d = true, _e = __asyncValues(descriptor.pipeline.processFrame(frame)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
24600
- _c = _f.value;
24601
- _d = false;
24704
+ for (var _e = true, _f = __asyncValues(descriptor.pipeline.processFrame(frame)), _g; _g = yield _f.next(), _a = _g.done, !_a; _e = true) {
24705
+ _c = _g.value;
24706
+ _e = false;
24602
24707
  const packet = _c;
24708
+ const prev = (_d = this.inFlightPacketCounter.get(handle)) !== null && _d !== void 0 ? _d : 0;
24709
+ this.inFlightPacketCounter.set(handle, prev + 1);
24603
24710
  this.emit('packetAvailable', {
24711
+ handle,
24604
24712
  bytes: packet.toBinary()
24605
24713
  });
24606
24714
  }
@@ -24610,7 +24718,7 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24610
24718
  };
24611
24719
  } finally {
24612
24720
  try {
24613
- if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
24721
+ if (!_e && !_a && (_b = _f.return)) yield _b.call(_f);
24614
24722
  } finally {
24615
24723
  if (e_1) throw e_1.error;
24616
24724
  }
@@ -24622,6 +24730,25 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24622
24730
  }
24623
24731
  });
24624
24732
  }
24733
+ /** The client has sent a packet over the rtc data channel. This signal is used for determining
24734
+ * once all packets are sent and a data track has been "flushed".
24735
+ *
24736
+ * @internal */
24737
+ handlePacketSendComplete(handle) {
24738
+ var _a;
24739
+ const prev = (_a = this.inFlightPacketCounter.get(handle)) !== null && _a !== void 0 ? _a : 0;
24740
+ let counter = prev - 1;
24741
+ if (counter < 0) {
24742
+ log.warn("OutgoingDataTrackManager.handlePacketSendComplete: inFlightPacketCounter was decremented below 0 (got ".concat(this.inFlightPacketCounter, " - resetting to 0. Were more packets send than were emitted?"));
24743
+ counter = 0;
24744
+ }
24745
+ this.inFlightPacketCounter.set(handle, counter);
24746
+ if (counter === 0) {
24747
+ this.emit('packetsFlushed', {
24748
+ handle
24749
+ });
24750
+ }
24751
+ }
24625
24752
  /**
24626
24753
  * Client requested to publish a track.
24627
24754
  *
@@ -24707,6 +24834,7 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24707
24834
  handle
24708
24835
  });
24709
24836
  yield descriptor.unpublishingFuture.promise;
24837
+ this.inFlightPacketCounter.delete(handle);
24710
24838
  this.emit('trackUnpublished', {
24711
24839
  sid: descriptor.info.sid
24712
24840
  });
@@ -24799,12 +24927,14 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24799
24927
  }
24800
24928
  }
24801
24929
  /**
24802
- * Shuts down the manager and all associated tracks.
24930
+ * Reset's the state of the manager and all associated tracks. Run on room disconnect to get
24931
+ * the manager ready for the next room connection.
24803
24932
  * @internal
24804
24933
  **/
24805
- shutdown() {
24934
+ reset() {
24806
24935
  return __awaiter(this, void 0, void 0, function* () {
24807
24936
  var _a, _b, _c, _d;
24937
+ this.handleAllocator.reset();
24808
24938
  for (const descriptor of this.descriptors.values()) {
24809
24939
  switch (descriptor.type) {
24810
24940
  case 'pending':
@@ -24819,6 +24949,8 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
24819
24949
  }
24820
24950
  }
24821
24951
  this.descriptors.clear();
24952
+ this.inFlightPacketCounter.clear();
24953
+ this.emit('reset');
24822
24954
  });
24823
24955
  }
24824
24956
  }class RemoteTrack extends Track {
@@ -25933,8 +26065,8 @@ class Participant extends eventsExports.EventEmitter {
25933
26065
  this.isSpeaking = false;
25934
26066
  this._connectionQuality = ConnectionQuality.Unknown;
25935
26067
  this.log = livekitLogger;
25936
- this.log = getLogger((_a = loggerOptions === null || loggerOptions === void 0 ? void 0 : loggerOptions.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Participant);
25937
26068
  this.loggerOptions = loggerOptions;
26069
+ this.log = getLogger((_a = loggerOptions === null || loggerOptions === void 0 ? void 0 : loggerOptions.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Participant, () => this.logContext);
25938
26070
  this.setMaxListeners(100);
25939
26071
  this.sid = sid;
25940
26072
  this.identity = identity;
@@ -26186,7 +26318,7 @@ class Participant extends eventsExports.EventEmitter {
26186
26318
  if (this.reconnectFuture) {
26187
26319
  // @throws-transformer ignore - introduced due to adding Throws into Future, investigate this
26188
26320
  // further
26189
- this.reconnectFuture.promise.catch(e => this.log.warn(e.message, this.logContext));
26321
+ this.reconnectFuture.promise.catch(e => this.log.warn(e.message));
26190
26322
  (_b = (_a = this.reconnectFuture) === null || _a === void 0 ? void 0 : _a.reject) === null || _b === void 0 ? void 0 : _b.call(_a, new Error('Got disconnected during reconnection attempt'));
26191
26323
  this.reconnectFuture = undefined;
26192
26324
  }
@@ -26270,10 +26402,10 @@ class Participant extends eventsExports.EventEmitter {
26270
26402
  }
26271
26403
  };
26272
26404
  this.updateTrackSubscriptionPermissions = () => {
26273
- this.log.debug('updating track subscription permissions', Object.assign(Object.assign({}, this.logContext), {
26405
+ this.log.debug('updating track subscription permissions', {
26274
26406
  allParticipantsAllowed: this.allParticipantsAllowedToSubscribe,
26275
26407
  participantTrackPermissions: this.participantTrackPermissions
26276
- }));
26408
+ });
26277
26409
  this.engine.client.sendUpdateSubscriptionPermissions(this.allParticipantsAllowedToSubscribe, this.participantTrackPermissions.map(p => trackPermissionToProto(p)));
26278
26410
  };
26279
26411
  /** @internal */
@@ -26287,29 +26419,29 @@ class Participant extends eventsExports.EventEmitter {
26287
26419
  muted = true;
26288
26420
  }
26289
26421
  if (!track.sid) {
26290
- this.log.error('could not update mute status for unpublished track', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
26422
+ this.log.error('could not update mute status for unpublished track', getLogContextFromTrack(track));
26291
26423
  return;
26292
26424
  }
26293
26425
  this.engine.updateMuteStatus(track.sid, muted);
26294
26426
  };
26295
26427
  this.onTrackUpstreamPaused = track => {
26296
- this.log.debug('upstream paused', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
26428
+ this.log.debug('upstream paused', getLogContextFromTrack(track));
26297
26429
  this.onTrackMuted(track, true);
26298
26430
  };
26299
26431
  this.onTrackUpstreamResumed = track => {
26300
- this.log.debug('upstream resumed', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
26432
+ this.log.debug('upstream resumed', getLogContextFromTrack(track));
26301
26433
  this.onTrackMuted(track, track.isMuted);
26302
26434
  };
26303
26435
  this.onTrackFeatureUpdate = track => {
26304
26436
  const pub = this.audioTrackPublications.get(track.sid);
26305
26437
  if (!pub) {
26306
- this.log.warn("Could not update local audio track settings, missing publication for track ".concat(track.sid), this.logContext);
26438
+ this.log.warn("Could not update local audio track settings, missing publication for track ".concat(track.sid));
26307
26439
  return;
26308
26440
  }
26309
26441
  this.engine.client.sendUpdateLocalAudioTrack(pub.trackSid, pub.getTrackFeatures());
26310
26442
  };
26311
26443
  this.onTrackCpuConstrained = (track, publication) => {
26312
- this.log.debug('track cpu constrained', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(publication)));
26444
+ this.log.debug('track cpu constrained', getLogContextFromTrack(publication));
26313
26445
  this.emit(ParticipantEvent.LocalTrackCpuConstrained, track, publication);
26314
26446
  };
26315
26447
  this.handleSubscribedQualityUpdate = update => __awaiter(this, void 0, void 0, function* () {
@@ -26320,9 +26452,9 @@ class Participant extends eventsExports.EventEmitter {
26320
26452
  }
26321
26453
  const pub = this.videoTrackPublications.get(update.trackSid);
26322
26454
  if (!pub) {
26323
- this.log.warn('received subscribed quality update for unknown track', Object.assign(Object.assign({}, this.logContext), {
26455
+ this.log.warn('received subscribed quality update for unknown track', {
26324
26456
  trackSid: update.trackSid
26325
- }));
26457
+ });
26326
26458
  return;
26327
26459
  }
26328
26460
  if (!pub.videoTrack) {
@@ -26335,7 +26467,7 @@ class Participant extends eventsExports.EventEmitter {
26335
26467
  _e = false;
26336
26468
  const codec = _c;
26337
26469
  if (isBackupCodec(codec)) {
26338
- this.log.debug("publish ".concat(codec, " for ").concat(pub.videoTrack.sid), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(pub)));
26470
+ this.log.debug("publish ".concat(codec, " for ").concat(pub.videoTrack.sid), getLogContextFromTrack(pub));
26339
26471
  yield this.publishAdditionalCodecForTrack(pub.videoTrack, codec, pub.options);
26340
26472
  }
26341
26473
  }
@@ -26354,16 +26486,16 @@ class Participant extends eventsExports.EventEmitter {
26354
26486
  this.handleLocalTrackUnpublished = unpublished => {
26355
26487
  const track = this.trackPublications.get(unpublished.trackSid);
26356
26488
  if (!track) {
26357
- this.log.warn('received unpublished event for unknown track', Object.assign(Object.assign({}, this.logContext), {
26489
+ this.log.warn('received unpublished event for unknown track', {
26358
26490
  trackSid: unpublished.trackSid
26359
- }));
26491
+ });
26360
26492
  return;
26361
26493
  }
26362
26494
  this.unpublishTrack(track.track);
26363
26495
  };
26364
26496
  this.handleTrackEnded = track => __awaiter(this, void 0, void 0, function* () {
26365
26497
  if (track.source === Track.Source.ScreenShare || track.source === Track.Source.ScreenShareAudio) {
26366
- this.log.debug('unpublishing local track due to TrackEnded', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
26498
+ this.log.debug('unpublishing local track due to TrackEnded', getLogContextFromTrack(track));
26367
26499
  this.unpublishTrack(track);
26368
26500
  } else if (track.isUserProvided) {
26369
26501
  yield track.mute();
@@ -26377,7 +26509,7 @@ class Participant extends eventsExports.EventEmitter {
26377
26509
  name: track.source === Track.Source.Camera ? 'camera' : 'microphone'
26378
26510
  });
26379
26511
  if (currentPermissions && currentPermissions.state === 'denied') {
26380
- this.log.warn("user has revoked access to ".concat(track.source), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
26512
+ this.log.warn("user has revoked access to ".concat(track.source), getLogContextFromTrack(track));
26381
26513
  // detect granted change after permissions were denied to try and resume then
26382
26514
  currentPermissions.onchange = () => {
26383
26515
  if (currentPermissions.state !== 'denied') {
@@ -26394,7 +26526,7 @@ class Participant extends eventsExports.EventEmitter {
26394
26526
  }
26395
26527
  }
26396
26528
  if (!track.isMuted) {
26397
- this.log.debug('track ended, attempting to use a different device', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
26529
+ this.log.debug('track ended, attempting to use a different device', getLogContextFromTrack(track));
26398
26530
  if (isLocalAudioTrack(track)) {
26399
26531
  // fall back to default device if available
26400
26532
  yield track.restartTrack({
@@ -26405,7 +26537,7 @@ class Participant extends eventsExports.EventEmitter {
26405
26537
  }
26406
26538
  }
26407
26539
  } catch (e) {
26408
- this.log.warn("could not restart track, muting instead", Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
26540
+ this.log.warn("could not restart track, muting instead", getLogContextFromTrack(track));
26409
26541
  yield track.mute();
26410
26542
  }
26411
26543
  }
@@ -26598,10 +26730,10 @@ class Participant extends eventsExports.EventEmitter {
26598
26730
  setTrackEnabled(source, enabled, options, publishOptions) {
26599
26731
  return __awaiter(this, void 0, void 0, function* () {
26600
26732
  var _a, _b;
26601
- this.log.debug('setTrackEnabled', Object.assign(Object.assign({}, this.logContext), {
26733
+ this.log.debug('setTrackEnabled', {
26602
26734
  source,
26603
26735
  enabled
26604
- }));
26736
+ });
26605
26737
  if (this.republishPromise) {
26606
26738
  yield this.republishPromise;
26607
26739
  }
@@ -26614,9 +26746,9 @@ class Participant extends eventsExports.EventEmitter {
26614
26746
  if (this.pendingPublishing.has(source)) {
26615
26747
  const pendingTrack = yield this.waitForPendingPublicationOfSource(source);
26616
26748
  if (!pendingTrack) {
26617
- this.log.info('waiting for pending publication promise timed out', Object.assign(Object.assign({}, this.logContext), {
26749
+ this.log.info('waiting for pending publication promise timed out', {
26618
26750
  source
26619
- }));
26751
+ });
26620
26752
  }
26621
26753
  yield pendingTrack === null || pendingTrack === void 0 ? void 0 : pendingTrack.unmute();
26622
26754
  return pendingTrack;
@@ -26653,14 +26785,14 @@ class Participant extends eventsExports.EventEmitter {
26653
26785
  for (const localTrack of localTracks) {
26654
26786
  const opts = Object.assign(Object.assign({}, this.roomOptions.publishDefaults), options);
26655
26787
  if (source === Track.Source.Microphone && isAudioTrack(localTrack) && opts.preConnectBuffer) {
26656
- this.log.info('starting preconnect buffer for microphone', Object.assign({}, this.logContext));
26788
+ this.log.info('starting preconnect buffer for microphone');
26657
26789
  localTrack.startPreConnectBuffer();
26658
26790
  }
26659
26791
  }
26660
26792
  try {
26661
26793
  const publishPromises = [];
26662
26794
  for (const localTrack of localTracks) {
26663
- this.log.info('publishing track', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(localTrack)));
26795
+ this.log.info('publishing track', getLogContextFromTrack(localTrack));
26664
26796
  publishPromises.push(this.publishTrack(localTrack, publishOptions));
26665
26797
  }
26666
26798
  const publishedTracks = yield Promise.all(publishPromises);
@@ -26681,9 +26813,9 @@ class Participant extends eventsExports.EventEmitter {
26681
26813
  // if there's no track available yet first wait for pending publishing promises of that source to see if it becomes available
26682
26814
  track = yield this.waitForPendingPublicationOfSource(source);
26683
26815
  if (!track) {
26684
- this.log.info('waiting for pending publication promise timed out', Object.assign(Object.assign({}, this.logContext), {
26816
+ this.log.info('waiting for pending publication promise timed out', {
26685
26817
  source
26686
- }));
26818
+ });
26687
26819
  }
26688
26820
  }
26689
26821
  if (track && track.track) {
@@ -26929,7 +27061,7 @@ class Participant extends eventsExports.EventEmitter {
26929
27061
  }
26930
27062
  });
26931
27063
  if (existingPublication) {
26932
- _this2.log.warn('track has already been published, skipping', Object.assign(Object.assign({}, _this2.logContext), getLogContextFromTrack(existingPublication)));
27064
+ _this2.log.warn('track has already been published, skipping', getLogContextFromTrack(existingPublication));
26933
27065
  return existingPublication;
26934
27066
  }
26935
27067
  const opts = Object.assign(Object.assign({}, _this2.roomOptions.publishDefaults), options);
@@ -26940,16 +27072,16 @@ class Participant extends eventsExports.EventEmitter {
26940
27072
  // disable dtx for stereo track if not enabled explicitly
26941
27073
  if (isStereo) {
26942
27074
  if (opts.dtx === undefined) {
26943
- _this2.log.info("Opus DTX will be disabled for stereo tracks by default. Enable them explicitly to make it work.", Object.assign(Object.assign({}, _this2.logContext), getLogContextFromTrack(track)));
27075
+ _this2.log.debug("Opus DTX will be disabled for stereo tracks by default. Enable them explicitly to make it work.", getLogContextFromTrack(track));
26944
27076
  }
26945
27077
  if (opts.red === undefined) {
26946
- _this2.log.info("Opus RED will be disabled for stereo tracks by default. Enable them explicitly to make it work.");
27078
+ _this2.log.debug("Opus RED will be disabled for stereo tracks by default. Enable them explicitly to make it work.");
26947
27079
  }
26948
27080
  (_c = opts.dtx) !== null && _c !== void 0 ? _c : opts.dtx = false;
26949
27081
  (_d = opts.red) !== null && _d !== void 0 ? _d : opts.red = false;
26950
27082
  }
26951
27083
  if (!isE2EESimulcastSupported() && _this2.roomOptions.e2ee) {
26952
- _this2.log.info("End-to-end encryption is set up, simulcast publishing will be disabled on Safari versions and iOS browsers running iOS < v17.2", Object.assign({}, _this2.logContext));
27084
+ _this2.log.info("End-to-end encryption is set up, simulcast publishing will be disabled on Safari versions and iOS browsers running iOS < v17.2");
26953
27085
  opts.simulcast = false;
26954
27086
  }
26955
27087
  if (opts.source) {
@@ -26958,9 +27090,9 @@ class Participant extends eventsExports.EventEmitter {
26958
27090
  const publishPromise = new Promise((resolve, reject) => __awaiter(_this2, void 0, void 0, function* () {
26959
27091
  try {
26960
27092
  if (this.engine.client.currentState !== SignalConnectionState.CONNECTED) {
26961
- this.log.debug('deferring track publication until signal is connected', Object.assign(Object.assign({}, this.logContext), {
27093
+ this.log.debug('deferring track publication until signal is connected', {
26962
27094
  track: getLogContextFromTrack(track)
26963
- }));
27095
+ });
26964
27096
  let publicationTimedOut = false;
26965
27097
  const timeout = setTimeout(() => {
26966
27098
  publicationTimedOut = true;
@@ -26992,9 +27124,9 @@ class Participant extends eventsExports.EventEmitter {
26992
27124
  return publication;
26993
27125
  } catch (e) {
26994
27126
  if (!hasRetriedAfterNegotiationError && e instanceof NegotiationError) {
26995
- _this2.log.warn('negotiation due to track publish failed, retrying after reconnect', Object.assign(Object.assign({}, _this2.logContext), {
27127
+ _this2.log.warn('negotiation due to track publish failed, retrying after reconnect', {
26996
27128
  error: e
26997
- }));
27129
+ });
26998
27130
  _this2.pendingPublishPromises.delete(track);
26999
27131
  yield _this2.waitForNextEngineRestart();
27000
27132
  return yield _this2.publishOrRepublishTrack(track, options, isRepublish, true);
@@ -27014,7 +27146,7 @@ class Participant extends eventsExports.EventEmitter {
27014
27146
  }
27015
27147
  hasPermissionsToPublish(track) {
27016
27148
  if (!this.permissions) {
27017
- this.log.warn('no permissions present for publishing track', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27149
+ this.log.warn('no permissions present for publishing track', getLogContextFromTrack(track));
27018
27150
  return false;
27019
27151
  }
27020
27152
  const {
@@ -27024,7 +27156,7 @@ class Participant extends eventsExports.EventEmitter {
27024
27156
  if (canPublish && (canPublishSources.length === 0 || canPublishSources.map(source => getTrackSourceFromProto(source)).includes(track.source))) {
27025
27157
  return true;
27026
27158
  }
27027
- this.log.warn('insufficient permissions to publish', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27159
+ this.log.warn('insufficient permissions to publish', getLogContextFromTrack(track));
27028
27160
  return false;
27029
27161
  }
27030
27162
  publish(track, opts, isStereo) {
@@ -27035,7 +27167,7 @@ class Participant extends eventsExports.EventEmitter {
27035
27167
  }
27036
27168
  const existingTrackOfSource = Array.from(this.trackPublications.values()).find(publishedTrack => isLocalTrack(track) && publishedTrack.source === track.source);
27037
27169
  if (existingTrackOfSource && track.source !== Track.Source.Unknown) {
27038
- this.log.info("publishing a second track with the same source: ".concat(track.source), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27170
+ this.log.info("publishing a second track with the same source: ".concat(track.source), getLogContextFromTrack(track));
27039
27171
  }
27040
27172
  if (opts.stopMicTrackOnMute && isAudioTrack(track)) {
27041
27173
  track.stopOnMute = true;
@@ -27124,7 +27256,7 @@ class Participant extends eventsExports.EventEmitter {
27124
27256
  height: defaultRes.height
27125
27257
  };
27126
27258
  // log failure
27127
- this.log.error('could not determine track dimensions, using defaults', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
27259
+ this.log.error('could not determine track dimensions, using defaults', Object.assign(Object.assign({}, getLogContextFromTrack(track)), {
27128
27260
  dims
27129
27261
  }));
27130
27262
  }
@@ -27145,7 +27277,7 @@ class Participant extends eventsExports.EventEmitter {
27145
27277
  // that we need
27146
27278
  if ('contentHint' in track.mediaStreamTrack) {
27147
27279
  track.mediaStreamTrack.contentHint = 'motion';
27148
- this.log.info('forcing contentHint to motion for screenshare with SVC codecs', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27280
+ this.log.debug('forcing contentHint to motion for screenshare with SVC codecs', getLogContextFromTrack(track));
27149
27281
  }
27150
27282
  }
27151
27283
  // set scalabilityMode to 'L3T3_KEY' by default
@@ -27241,10 +27373,10 @@ class Participant extends eventsExports.EventEmitter {
27241
27373
  try {
27242
27374
  this.engine.pcManager.publisher.removeTrack(track.sender);
27243
27375
  } catch (e) {
27244
- this.log.error(e, this.logContext);
27376
+ this.log.error(e);
27245
27377
  }
27246
27378
  yield this.engine.negotiate().catch(negotiateErr => {
27247
- this.log.error('failed to negotiate after removing track due to failed add track request', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
27379
+ this.log.error('failed to negotiate after removing track due to failed add track request', Object.assign(Object.assign({}, getLogContextFromTrack(track)), {
27248
27380
  error: negotiateErr
27249
27381
  }));
27250
27382
  });
@@ -27268,7 +27400,7 @@ class Participant extends eventsExports.EventEmitter {
27268
27400
  if (primaryCodecMime && track.kind === Track.Kind.Video) {
27269
27401
  const updatedCodec = mimeTypeToVideoCodecString(primaryCodecMime);
27270
27402
  if (updatedCodec !== videoCodec) {
27271
- this.log.debug('falling back to server selected codec', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
27403
+ this.log.debug('falling back to server selected codec', Object.assign(Object.assign({}, getLogContextFromTrack(track)), {
27272
27404
  codec: updatedCodec
27273
27405
  }));
27274
27406
  opts.videoCodec = updatedCodec;
@@ -27299,10 +27431,10 @@ class Participant extends eventsExports.EventEmitter {
27299
27431
  };
27300
27432
  }
27301
27433
  }
27302
- this.log.debug("publishing ".concat(track.kind, " with encodings"), Object.assign(Object.assign({}, this.logContext), {
27434
+ this.log.debug("publishing ".concat(track.kind, " with encodings"), {
27303
27435
  encodings,
27304
27436
  trackInfo: ti
27305
- }));
27437
+ });
27306
27438
  if (isLocalVideoTrack(track)) {
27307
27439
  track.startMonitor(this.engine.client);
27308
27440
  } else if (isLocalAudioTrack(track)) {
@@ -27318,10 +27450,10 @@ class Participant extends eventsExports.EventEmitter {
27318
27450
  this.on(ParticipantEvent.LocalTrackSubscribed, pub => {
27319
27451
  if (pub.trackSid === ti.sid) {
27320
27452
  if (!track.hasPreConnectBuffer) {
27321
- this.log.warn('subscribe event came to late, buffer already closed', this.logContext);
27453
+ this.log.warn('subscribe event came to late, buffer already closed');
27322
27454
  return;
27323
27455
  }
27324
- this.log.debug('finished recording preconnect buffer', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27456
+ this.log.debug('finished recording preconnect buffer', getLogContextFromTrack(track));
27325
27457
  track.stopPreConnectBuffer();
27326
27458
  }
27327
27459
  });
@@ -27330,13 +27462,13 @@ class Participant extends eventsExports.EventEmitter {
27330
27462
  var _a, e_2, _b, _c;
27331
27463
  var _d, _e;
27332
27464
  try {
27333
- this.log.debug('waiting for agent', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27465
+ this.log.debug('waiting for agent', getLogContextFromTrack(track));
27334
27466
  const agentActiveTimeout = setTimeout(() => {
27335
27467
  reject(new Error('agent not active within 10 seconds'));
27336
27468
  }, 10000);
27337
27469
  const agent = yield this.waitUntilActiveAgentPresent();
27338
27470
  clearTimeout(agentActiveTimeout);
27339
- this.log.debug('sending preconnect buffer', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27471
+ this.log.debug('sending preconnect buffer', getLogContextFromTrack(track));
27340
27472
  const writer = yield this.streamBytes({
27341
27473
  name: 'preconnect-buffer',
27342
27474
  mimeType,
@@ -27373,9 +27505,9 @@ class Participant extends eventsExports.EventEmitter {
27373
27505
  }
27374
27506
  }));
27375
27507
  bufferStreamPromise.then(() => {
27376
- this.log.debug('preconnect buffer sent successfully', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27508
+ this.log.debug('preconnect buffer sent successfully', getLogContextFromTrack(track));
27377
27509
  }).catch(e => {
27378
- this.log.error('error sending preconnect buffer', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
27510
+ this.log.error('error sending preconnect buffer', Object.assign(Object.assign({}, getLogContextFromTrack(track)), {
27379
27511
  error: e
27380
27512
  }));
27381
27513
  });
@@ -27416,7 +27548,7 @@ class Participant extends eventsExports.EventEmitter {
27416
27548
  const opts = Object.assign(Object.assign({}, (_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.publishDefaults), options);
27417
27549
  const encodings = computeTrackBackupEncodings(track, videoCodec, opts);
27418
27550
  if (!encodings) {
27419
- this.log.info("backup codec has been disabled, ignoring request to add additional codec for track", Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27551
+ this.log.info("backup codec has been disabled, ignoring request to add additional codec for track", getLogContextFromTrack(track));
27420
27552
  return;
27421
27553
  }
27422
27554
  const simulcastTrack = track.addSimulcastTrack(videoCodec, encodings);
@@ -27444,10 +27576,10 @@ class Participant extends eventsExports.EventEmitter {
27444
27576
  });
27445
27577
  const rets = yield Promise.all([this.engine.addTrack(req), negotiate()]);
27446
27578
  const ti = rets[0];
27447
- this.log.debug("published ".concat(videoCodec, " for track ").concat(track.sid), Object.assign(Object.assign({}, this.logContext), {
27579
+ this.log.debug("published ".concat(videoCodec, " for track ").concat(track.sid), {
27448
27580
  encodings,
27449
27581
  trackInfo: ti
27450
- }));
27582
+ });
27451
27583
  });
27452
27584
  }
27453
27585
  unpublishTrack(track, stopOnUnpublish) {
@@ -27456,16 +27588,16 @@ class Participant extends eventsExports.EventEmitter {
27456
27588
  if (isLocalTrack(track)) {
27457
27589
  const publishPromise = this.pendingPublishPromises.get(track);
27458
27590
  if (publishPromise) {
27459
- this.log.info('awaiting publish promise before attempting to unpublish', Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
27591
+ this.log.debug('awaiting publish promise before attempting to unpublish', getLogContextFromTrack(track));
27460
27592
  yield publishPromise;
27461
27593
  }
27462
27594
  }
27463
27595
  // look through all published tracks to find the right ones
27464
27596
  const publication = this.getPublicationForTrack(track);
27465
27597
  const pubLogContext = publication ? getLogContextFromTrack(publication) : undefined;
27466
- this.log.debug('unpublishing track', Object.assign(Object.assign({}, this.logContext), pubLogContext));
27598
+ this.log.info('unpublishing track', pubLogContext);
27467
27599
  if (!publication || !publication.track) {
27468
- this.log.warn('track was not unpublished because no publication was found', Object.assign(Object.assign({}, this.logContext), pubLogContext));
27600
+ this.log.warn('track was not unpublished because no publication was found', pubLogContext);
27469
27601
  return undefined;
27470
27602
  }
27471
27603
  track = publication.track;
@@ -27501,7 +27633,7 @@ class Participant extends eventsExports.EventEmitter {
27501
27633
  try {
27502
27634
  negotiationNeeded = this.engine.removeTrack(trackSender);
27503
27635
  } catch (e) {
27504
- this.log.warn(e, this.logContext);
27636
+ this.log.warn(e);
27505
27637
  negotiationNeeded = true;
27506
27638
  }
27507
27639
  if (isLocalVideoTrack(track)) {
@@ -27510,7 +27642,7 @@ class Participant extends eventsExports.EventEmitter {
27510
27642
  try {
27511
27643
  negotiationNeeded = this.engine.removeTrack(trackInfo.sender);
27512
27644
  } catch (e) {
27513
- this.log.warn(e, this.logContext);
27645
+ this.log.warn(e);
27514
27646
  negotiationNeeded = true;
27515
27647
  }
27516
27648
  trackInfo.sender = undefined;
@@ -27519,7 +27651,7 @@ class Participant extends eventsExports.EventEmitter {
27519
27651
  track.simulcastCodecs.clear();
27520
27652
  }
27521
27653
  } catch (e) {
27522
- this.log.warn('failed to unpublish track', Object.assign(Object.assign(Object.assign({}, this.logContext), pubLogContext), {
27654
+ this.log.warn('failed to unpublish track', Object.assign(Object.assign({}, pubLogContext), {
27523
27655
  error: e
27524
27656
  }));
27525
27657
  }
@@ -27573,9 +27705,9 @@ class Participant extends eventsExports.EventEmitter {
27573
27705
  if (restartTracks && !track.isMuted && track.source !== Track.Source.ScreenShare && track.source !== Track.Source.ScreenShareAudio && (isLocalAudioTrack(track) || isLocalVideoTrack(track)) && !track.isUserProvided) {
27574
27706
  // generally we need to restart the track before publishing, often a full reconnect
27575
27707
  // is necessary because computer had gone to sleep.
27576
- this.log.debug('restarting existing track', Object.assign(Object.assign({}, this.logContext), {
27708
+ this.log.debug('restarting existing track', {
27577
27709
  track: pub.trackSid
27578
- }));
27710
+ });
27579
27711
  yield track.restartTrack();
27580
27712
  }
27581
27713
  yield this.publishOrRepublishTrack(track, pub.options, true);
@@ -27916,7 +28048,7 @@ class Participant extends eventsExports.EventEmitter {
27916
28048
  if (pub) {
27917
28049
  const mutedOnServer = pub.isMuted || ((_b = (_a = pub.track) === null || _a === void 0 ? void 0 : _a.isUpstreamPaused) !== null && _b !== void 0 ? _b : false);
27918
28050
  if (mutedOnServer !== ti.muted) {
27919
- this.log.debug('updating server mute state after reconcile', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(pub)), {
28051
+ this.log.debug('updating server mute state after reconcile', Object.assign(Object.assign({}, getLogContextFromTrack(pub)), {
27920
28052
  mutedOnServer
27921
28053
  }));
27922
28054
  this.engine.client.sendMuteTrack(ti.sid, mutedOnServer);
@@ -28700,7 +28832,7 @@ class Room extends eventsExports.EventEmitter {
28700
28832
  const unlockDisconnect = yield this.disconnectLock.lock();
28701
28833
  if (this.state === ConnectionState.Connected) {
28702
28834
  // when the state is reconnecting or connected, this function returns immediately
28703
- this.log.info("already connected to room ".concat(this.name), this.logContext);
28835
+ this.log.info("already connected to room ".concat(this.name));
28704
28836
  unlockDisconnect();
28705
28837
  return Promise.resolve();
28706
28838
  }
@@ -28726,9 +28858,9 @@ class Room extends eventsExports.EventEmitter {
28726
28858
  var _a;
28727
28859
  (_a = this.regionUrlProvider) === null || _a === void 0 ? void 0 : _a.setServerReportedRegions(settings);
28728
28860
  }).catch(e => {
28729
- this.log.warn('could not fetch region settings', Object.assign(Object.assign({}, this.logContext), {
28861
+ this.log.warn('could not fetch region settings', {
28730
28862
  error: e
28731
- }));
28863
+ });
28732
28864
  });
28733
28865
  }
28734
28866
  const connectFn = (resolve, reject, regionUrl) => __awaiter(this, void 0, void 0, function* () {
@@ -28769,7 +28901,7 @@ class Room extends eventsExports.EventEmitter {
28769
28901
  BackOffStrategy.getInstance().addFailedConnectionAttempt(url);
28770
28902
  }
28771
28903
  if (nextUrl && !((_b = this.abortController) === null || _b === void 0 ? void 0 : _b.signal.aborted)) {
28772
- this.log.info("Initial connection failed with ConnectionError: ".concat(error.message, ". Retrying with another region: ").concat(nextUrl), this.logContext);
28904
+ this.log.info("Initial connection failed with ConnectionError: ".concat(error.message, ". Retrying with another region: ").concat(nextUrl));
28773
28905
  this.recreateEngine(true);
28774
28906
  yield connectFn(resolve, reject, nextUrl);
28775
28907
  } else {
@@ -28811,7 +28943,7 @@ class Room extends eventsExports.EventEmitter {
28811
28943
  throw new UnsupportedServer('unknown server version');
28812
28944
  }
28813
28945
  if (serverInfo.version === '0.15.1' && this.options.dynacast) {
28814
- this.log.debug('disabling dynacast due to server version', this.logContext);
28946
+ this.log.debug('disabling dynacast due to server version');
28815
28947
  // dynacast has a bug in 0.15.1, so we cannot use it then
28816
28948
  roomOptions.dynacast = false;
28817
28949
  }
@@ -28826,9 +28958,9 @@ class Room extends eventsExports.EventEmitter {
28826
28958
  try {
28827
28959
  this.e2eeManager.setSifTrailer(joinResponse.sifTrailer);
28828
28960
  } catch (e) {
28829
- this.log.error(e instanceof Error ? e.message : 'Could not set SifTrailer', Object.assign(Object.assign({}, this.logContext), {
28961
+ this.log.error(e instanceof Error ? e.message : 'Could not set SifTrailer', {
28830
28962
  error: e
28831
- }));
28963
+ });
28832
28964
  }
28833
28965
  }
28834
28966
  // populate remote participants, these should not trigger new events
@@ -28840,7 +28972,7 @@ class Room extends eventsExports.EventEmitter {
28840
28972
  this.attemptConnection = (url, token, opts, abortController) => __awaiter(this, void 0, void 0, function* () {
28841
28973
  var _a, _b;
28842
28974
  if (this.state === ConnectionState.Reconnecting || this.isResuming || ((_a = this.engine) === null || _a === void 0 ? void 0 : _a.pendingReconnect)) {
28843
- this.log.info('Reconnection attempt replaced by new connection attempt', this.logContext);
28975
+ this.log.info('Reconnection attempt replaced by new connection attempt');
28844
28976
  // make sure we close and recreate the existing engine in order to get rid of any potentially ongoing reconnection attempts
28845
28977
  this.recreateEngine(true);
28846
28978
  } else {
@@ -28875,9 +29007,9 @@ class Room extends eventsExports.EventEmitter {
28875
29007
  resultingError.reason = err.reason;
28876
29008
  resultingError.status = err.status;
28877
29009
  }
28878
- this.log.debug("error trying to establish signal connection", Object.assign(Object.assign({}, this.logContext), {
29010
+ this.log.debug("error trying to establish signal connection", {
28879
29011
  error: err
28880
- }));
29012
+ });
28881
29013
  throw resultingError;
28882
29014
  }
28883
29015
  if (abortController.signal.aborted) {
@@ -28925,14 +29057,14 @@ class Room extends eventsExports.EventEmitter {
28925
29057
  const unlock = yield _this2.disconnectLock.lock();
28926
29058
  try {
28927
29059
  if (_this2.state === ConnectionState.Disconnected) {
28928
- _this2.log.debug('already disconnected', _this2.logContext);
29060
+ _this2.log.debug('already disconnected');
28929
29061
  return;
28930
29062
  }
28931
- _this2.log.info('disconnect from room', Object.assign({}, _this2.logContext));
29063
+ _this2.log.info('disconnect from room');
28932
29064
  if (_this2.state === ConnectionState.Connecting || _this2.state === ConnectionState.Reconnecting || _this2.isResuming) {
28933
29065
  // try aborting pending connection attempt
28934
29066
  const msg = 'Abort connection attempt due to user initiated disconnect';
28935
- _this2.log.warn(msg, _this2.logContext);
29067
+ _this2.log.warn(msg);
28936
29068
  (_a = _this2.abortController) === null || _a === void 0 ? void 0 : _a.abort(msg);
28937
29069
  // in case the abort controller didn't manage to cancel the connection attempt, reject the connect promise explicitly
28938
29070
  (_c = (_b = _this2.connectFuture) === null || _b === void 0 ? void 0 : _b.reject) === null || _c === void 0 ? void 0 : _c.call(_b, ConnectionError.cancelled('Client initiated disconnect'));
@@ -28956,7 +29088,7 @@ class Room extends eventsExports.EventEmitter {
28956
29088
  });
28957
29089
  };
28958
29090
  this.onPageLeave = () => __awaiter(this, void 0, void 0, function* () {
28959
- this.log.info('Page leave detected, disconnecting', this.logContext);
29091
+ this.log.info('Page leave detected, disconnecting');
28960
29092
  yield this.disconnect();
28961
29093
  });
28962
29094
  /**
@@ -28996,7 +29128,7 @@ class Room extends eventsExports.EventEmitter {
28996
29128
  // set the srcObject to null on page hide in order to prevent lock screen controls to show up for it
28997
29129
  dummyAudioEl.srcObject = document.hidden ? null : stream;
28998
29130
  if (!document.hidden) {
28999
- this.log.debug('page visible again, triggering startAudio to resume playback and update playback status', this.logContext);
29131
+ this.log.debug('page visible again, triggering startAudio to resume playback and update playback status');
29000
29132
  this.startAudio();
29001
29133
  }
29002
29134
  });
@@ -29046,7 +29178,7 @@ class Room extends eventsExports.EventEmitter {
29046
29178
  if (e.name === 'NotAllowedError') {
29047
29179
  this.handleVideoPlaybackFailed();
29048
29180
  } else {
29049
- this.log.warn('Resuming video playback failed, make sure you call `startVideo` directly in a user gesture handler', this.logContext);
29181
+ this.log.warn('Resuming video playback failed, make sure you call `startVideo` directly in a user gesture handler');
29050
29182
  }
29051
29183
  });
29052
29184
  });
@@ -29067,24 +29199,24 @@ class Room extends eventsExports.EventEmitter {
29067
29199
  this.incomingDataTrackManager.resendSubscriptionUpdates();
29068
29200
  };
29069
29201
  this.handleSignalRestarted = joinResponse => __awaiter(this, void 0, void 0, function* () {
29070
- this.log.debug("signal reconnected to server, region ".concat(joinResponse.serverRegion), Object.assign(Object.assign({}, this.logContext), {
29202
+ this.log.debug("signal reconnected to server, region ".concat(joinResponse.serverRegion), {
29071
29203
  region: joinResponse.serverRegion
29072
- }));
29204
+ });
29073
29205
  this.bufferedEvents = [];
29074
29206
  this.applyJoinResponse(joinResponse);
29075
29207
  try {
29076
29208
  // unpublish & republish tracks
29077
29209
  yield this.localParticipant.republishAllTracks(undefined, true);
29078
29210
  } catch (error) {
29079
- this.log.error('error trying to re-publish tracks after reconnection', Object.assign(Object.assign({}, this.logContext), {
29211
+ this.log.error('error trying to re-publish tracks after reconnection', {
29080
29212
  error
29081
- }));
29213
+ });
29082
29214
  }
29083
29215
  try {
29084
29216
  yield this.engine.waitForRestarted();
29085
- this.log.debug("fully reconnected to server", Object.assign(Object.assign({}, this.logContext), {
29217
+ this.log.debug("fully reconnected to server", {
29086
29218
  region: joinResponse.serverRegion
29087
- }));
29219
+ });
29088
29220
  } catch (_a) {
29089
29221
  // reconnection failed, handleDisconnect is being invoked already, just return here
29090
29222
  return;
@@ -29283,9 +29415,9 @@ class Room extends eventsExports.EventEmitter {
29283
29415
  this.emit(RoomEvent.AudioPlaybackStatusChanged, true);
29284
29416
  };
29285
29417
  this.handleAudioPlaybackFailed = e => {
29286
- this.log.warn('could not playback audio', Object.assign(Object.assign({}, this.logContext), {
29418
+ this.log.warn('could not playback audio', {
29287
29419
  error: e
29288
- }));
29420
+ });
29289
29421
  if (!this.canPlaybackAudio) {
29290
29422
  return;
29291
29423
  }
@@ -29382,7 +29514,7 @@ class Room extends eventsExports.EventEmitter {
29382
29514
  const deviceId = yield track.getDeviceId(false);
29383
29515
  const deviceKind = sourceToKind(track.source);
29384
29516
  if (deviceKind && deviceId && deviceId !== this.localParticipant.activeDeviceMap.get(deviceKind)) {
29385
- this.log.debug("local track restarted, setting ".concat(deviceKind, " ").concat(deviceId, " active"), this.logContext);
29517
+ this.log.debug("local track restarted, setting ".concat(deviceKind, " ").concat(deviceId, " active"));
29386
29518
  this.localParticipant.activeDeviceMap.set(deviceKind, deviceId);
29387
29519
  this.emit(RoomEvent.ActiveDeviceChanged, deviceKind, deviceId);
29388
29520
  }
@@ -29403,7 +29535,7 @@ class Room extends eventsExports.EventEmitter {
29403
29535
  this.remoteParticipants = new Map();
29404
29536
  this.sidToIdentity = new Map();
29405
29537
  this.options = Object.assign(Object.assign({}, roomOptionDefaults), options);
29406
- this.log = getLogger((_a = this.options.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Room);
29538
+ this.log = getLogger((_a = this.options.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Room, () => this.logContext);
29407
29539
  this.transcriptionReceivedTimes = new Map();
29408
29540
  this.options.audioCaptureDefaults = Object.assign(Object.assign({}, audioDefaults), options === null || options === void 0 ? void 0 : options.audioCaptureDefaults);
29409
29541
  this.options.videoCaptureDefaults = Object.assign(Object.assign({}, videoDefaults), options === null || options === void 0 ? void 0 : options.videoCaptureDefaults);
@@ -29446,9 +29578,10 @@ class Room extends eventsExports.EventEmitter {
29446
29578
  this.emit(RoomEvent.LocalDataTrackUnpublished, event.sid);
29447
29579
  }).on('packetAvailable', _ref => {
29448
29580
  let {
29581
+ handle,
29449
29582
  bytes
29450
29583
  } = _ref;
29451
- this.engine.sendLossyBytes(bytes, DataChannelKind.DATA_TRACK_LOSSY, 'wait');
29584
+ this.engine.sendLossyBytes(bytes, DataChannelKind.DATA_TRACK_LOSSY, 'wait').finally(() => this.outgoingDataTrackManager.handlePacketSendComplete(handle));
29452
29585
  });
29453
29586
  this.disconnectLock = new _();
29454
29587
  this.localParticipant = new LocalParticipant('', '', this.engine, this.options, this.rpcHandlers, this.outgoingDataStreamManager, this.outgoingDataTrackManager);
@@ -29465,7 +29598,7 @@ class Room extends eventsExports.EventEmitter {
29465
29598
  this.localParticipant.activeDeviceMap.set('audioinput', unwrapConstraint(this.options.audioCaptureDefaults.deviceId));
29466
29599
  }
29467
29600
  if ((_d = this.options.audioOutput) === null || _d === void 0 ? void 0 : _d.deviceId) {
29468
- this.switchActiveDevice('audiooutput', unwrapConstraint(this.options.audioOutput.deviceId)).catch(e => this.log.warn("Could not set audio output: ".concat(e.message), this.logContext));
29601
+ this.switchActiveDevice('audiooutput', unwrapConstraint(this.options.audioOutput.deviceId)).catch(e => this.log.warn("Could not set audio output: ".concat(e.message)));
29469
29602
  }
29470
29603
  if (isWeb()) {
29471
29604
  const abortController = new AbortController();
@@ -29581,12 +29714,12 @@ class Room extends eventsExports.EventEmitter {
29581
29714
  }
29582
29715
  }
29583
29716
  get logContext() {
29584
- var _a;
29717
+ var _a, _b, _c;
29585
29718
  return {
29586
29719
  room: this.name,
29587
29720
  roomID: (_a = this.roomInfo) === null || _a === void 0 ? void 0 : _a.sid,
29588
- participant: this.localParticipant.identity,
29589
- participantID: this.localParticipant.sid
29721
+ participant: (_b = this.localParticipant) === null || _b === void 0 ? void 0 : _b.identity,
29722
+ participantID: (_c = this.localParticipant) === null || _c === void 0 ? void 0 : _c.sid
29590
29723
  };
29591
29724
  }
29592
29725
  /**
@@ -29652,14 +29785,14 @@ class Room extends eventsExports.EventEmitter {
29652
29785
  }).on(EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate).on(EngineEvent.DataPacketReceived, this.handleDataPacket).on(EngineEvent.Resuming, () => {
29653
29786
  this.clearConnectionReconcile();
29654
29787
  this.isResuming = true;
29655
- this.log.info('Resuming signal connection', this.logContext);
29788
+ this.log.debug('Resuming signal connection');
29656
29789
  if (this.setAndEmitConnectionState(ConnectionState.SignalReconnecting)) {
29657
29790
  this.emit(RoomEvent.SignalReconnecting);
29658
29791
  }
29659
29792
  }).on(EngineEvent.Resumed, () => {
29660
29793
  this.registerConnectionReconcile();
29661
29794
  this.isResuming = false;
29662
- this.log.info('Resumed signal connection', this.logContext);
29795
+ this.log.debug('Resumed signal connection');
29663
29796
  this.updateSubscriptions();
29664
29797
  this.emitBufferedEvents();
29665
29798
  if (this.setAndEmitConnectionState(ConnectionState.Connected)) {
@@ -29694,7 +29827,7 @@ class Room extends eventsExports.EventEmitter {
29694
29827
  }
29695
29828
  }).on(EngineEvent.PublishDataTrackResponse, event => {
29696
29829
  if (!event.info) {
29697
- this.log.warn("received PublishDataTrackResponse, but event.info was ".concat(event.info, ", so skipping."), this.logContext);
29830
+ this.log.warn("received PublishDataTrackResponse, but event.info was ".concat(event.info, ", so skipping."));
29698
29831
  return;
29699
29832
  }
29700
29833
  this.outgoingDataTrackManager.receivedSfuPublishResponse(event.info.pubHandle, {
@@ -29708,7 +29841,7 @@ class Room extends eventsExports.EventEmitter {
29708
29841
  });
29709
29842
  }).on(EngineEvent.UnPublishDataTrackResponse, event => {
29710
29843
  if (!event.info) {
29711
- this.log.warn("received UnPublishDataTrackResponse, but event.info was ".concat(event.info, ", so skipping."), this.logContext);
29844
+ this.log.warn("received UnPublishDataTrackResponse, but event.info was ".concat(event.info, ", so skipping."));
29712
29845
  return;
29713
29846
  }
29714
29847
  this.outgoingDataTrackManager.receivedSfuUnpublishResponse(event.info.pubHandle);
@@ -29789,7 +29922,7 @@ class Room extends eventsExports.EventEmitter {
29789
29922
  if (this.state !== ConnectionState.Disconnected) {
29790
29923
  return;
29791
29924
  }
29792
- this.log.debug("prepareConnection to ".concat(url), this.logContext);
29925
+ this.log.debug("prepareConnection to ".concat(url));
29793
29926
  try {
29794
29927
  if (isCloud(new URL(url)) && token) {
29795
29928
  this.regionUrlProvider = new RegionUrlProvider(url, token);
@@ -29801,7 +29934,7 @@ class Room extends eventsExports.EventEmitter {
29801
29934
  yield fetch(toHttpUrl(regionUrl), {
29802
29935
  method: 'HEAD'
29803
29936
  });
29804
- this.log.debug("prepared connection to ".concat(regionUrl), this.logContext);
29937
+ this.log.debug("prepared connection to ".concat(regionUrl));
29805
29938
  }
29806
29939
  } else {
29807
29940
  yield fetch(toHttpUrl(url), {
@@ -29809,9 +29942,9 @@ class Room extends eventsExports.EventEmitter {
29809
29942
  });
29810
29943
  }
29811
29944
  } catch (e) {
29812
- this.log.warn('could not prepare connection', Object.assign(Object.assign({}, this.logContext), {
29945
+ this.log.warn('could not prepare connection', {
29813
29946
  error: e
29814
- }));
29947
+ });
29815
29948
  }
29816
29949
  });
29817
29950
  }
@@ -30110,11 +30243,11 @@ class Room extends eventsExports.EventEmitter {
30110
30243
  return;
30111
30244
  }
30112
30245
  if (this.state === ConnectionState.Disconnected) {
30113
- this.log.warn('skipping incoming track after Room disconnected', this.logContext);
30246
+ this.log.warn('skipping incoming track after Room disconnected');
30114
30247
  return;
30115
30248
  }
30116
30249
  if (mediaTrack.readyState === 'ended') {
30117
- this.log.info('skipping incoming track as it already ended', this.logContext);
30250
+ this.log.debug('skipping incoming track as it already ended');
30118
30251
  return;
30119
30252
  }
30120
30253
  const parts = unpackStreamId(stream.id);
@@ -30125,14 +30258,14 @@ class Room extends eventsExports.EventEmitter {
30125
30258
  // and generates its own track id instead of infer from sdp track id.
30126
30259
  if (streamId && streamId.startsWith('TR')) trackId = streamId;
30127
30260
  if (participantSid === this.localParticipant.sid) {
30128
- this.log.warn('tried to create RemoteParticipant for local participant', this.logContext);
30261
+ this.log.warn('tried to create RemoteParticipant for local participant');
30129
30262
  return;
30130
30263
  }
30131
30264
  const participant = Array.from(this.remoteParticipants.values()).find(p => p.sid === participantSid);
30132
30265
  if (!participant) {
30133
30266
  // server could require extra media sections to accelerate subscription.
30134
30267
  if (participantSid.startsWith('PA')) {
30135
- this.log.error("Tried to add a track for a participant, that's not present. Sid: ".concat(participantSid), this.logContext);
30268
+ this.log.error("Tried to add a track for a participant, that's not present. Sid: ".concat(participantSid));
30136
30269
  }
30137
30270
  return;
30138
30271
  }
@@ -30142,17 +30275,17 @@ class Room extends eventsExports.EventEmitter {
30142
30275
  if (!trackId.startsWith('TR')) {
30143
30276
  const id = this.engine.getTrackIdForReceiver(receiver);
30144
30277
  if (!id) {
30145
- 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);
30278
+ this.log.error("Tried to add a track whose 'sid' could not be found for a participant, that's not present. Sid: ".concat(participantSid));
30146
30279
  return;
30147
30280
  }
30148
30281
  trackId = id;
30149
30282
  }
30150
30283
  if (!trackId.startsWith('TR')) {
30151
- 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), {
30284
+ 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), {
30152
30285
  remoteParticipantID: participantSid,
30153
30286
  streamId,
30154
30287
  trackId
30155
- }));
30288
+ });
30156
30289
  }
30157
30290
  let adaptiveStreamSettings;
30158
30291
  if (this.options.adaptiveStream) {
@@ -30182,9 +30315,9 @@ class Room extends eventsExports.EventEmitter {
30182
30315
  // the track publication may not be registered yet if the server signals
30183
30316
  // the subscription before publishTrack has finished adding the publication.
30184
30317
  // defer with a timeout until LocalTrackPublished fires for the matching trackSid
30185
- this.log.debug('deferring LocalTrackSubscribed, publication not yet available', Object.assign(Object.assign({}, this.logContext), {
30318
+ this.log.debug('deferring LocalTrackSubscribed, publication not yet available', {
30186
30319
  subscribedSid
30187
- }));
30320
+ });
30188
30321
  const TIMEOUT_MS = 10000;
30189
30322
  let timer;
30190
30323
  const onPublished = pub => {
@@ -30207,9 +30340,9 @@ class Room extends eventsExports.EventEmitter {
30207
30340
  if (pub) {
30208
30341
  this.emitLocalTrackSubscribed(pub);
30209
30342
  } else {
30210
- this.log.warn('could not find local track publication for LocalTrackSubscribed event after timeout', Object.assign(Object.assign({}, this.logContext), {
30343
+ this.log.warn('could not find local track publication for LocalTrackSubscribed event after timeout', {
30211
30344
  subscribedSid
30212
- }));
30345
+ });
30213
30346
  }
30214
30347
  }, TIMEOUT_MS);
30215
30348
  }
@@ -30226,6 +30359,8 @@ class Room extends eventsExports.EventEmitter {
30226
30359
  this.bufferedEvents = [];
30227
30360
  this.transcriptionReceivedTimes.clear();
30228
30361
  this.incomingDataStreamManager.clearControllers();
30362
+ this.incomingDataTrackManager.reset();
30363
+ this.outgoingDataTrackManager.reset();
30229
30364
  if (this.state === ConnectionState.Disconnected) {
30230
30365
  return;
30231
30366
  }
@@ -30402,9 +30537,9 @@ class Room extends eventsExports.EventEmitter {
30402
30537
  try {
30403
30538
  yield Promise.race([this.audioContext.resume(), sleep(200)]);
30404
30539
  } catch (e) {
30405
- this.log.warn('Could not resume audio context', Object.assign(Object.assign({}, this.logContext), {
30540
+ this.log.warn('Could not resume audio context', {
30406
30541
  error: e
30407
- }));
30542
+ });
30408
30543
  }
30409
30544
  }
30410
30545
  const newContextIsRunning = ((_b = this.audioContext) === null || _b === void 0 ? void 0 : _b.state) === 'running';
@@ -30432,7 +30567,7 @@ class Room extends eventsExports.EventEmitter {
30432
30567
  participant.setAudioContext(this.audioContext);
30433
30568
  }
30434
30569
  if ((_a = this.options.audioOutput) === null || _a === void 0 ? void 0 : _a.deviceId) {
30435
- participant.setAudioOutput(this.options.audioOutput).catch(e => this.log.warn("Could not set audio output: ".concat(e.message), this.logContext));
30570
+ participant.setAudioOutput(this.options.audioOutput).catch(e => this.log.warn("Could not set audio output: ".concat(e.message)));
30436
30571
  }
30437
30572
  return participant;
30438
30573
  }
@@ -30544,13 +30679,13 @@ class Room extends eventsExports.EventEmitter {
30544
30679
  // transports failed without notifying engine
30545
30680
  !this.engine.verifyTransport()) {
30546
30681
  consecutiveFailures++;
30547
- this.log.warn('detected connection state mismatch', Object.assign(Object.assign({}, this.logContext), {
30682
+ this.log.warn('detected connection state mismatch', {
30548
30683
  numFailures: consecutiveFailures,
30549
30684
  engine: this.engine ? {
30550
30685
  closed: this.engine.isClosed,
30551
30686
  transportsConnectedOrConnecting: this.engine.verifyTransport()
30552
30687
  } : undefined
30553
- }));
30688
+ });
30554
30689
  if (consecutiveFailures >= 3) {
30555
30690
  this.recreateEngine();
30556
30691
  this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, DisconnectReason.STATE_MISMATCH);
@@ -30570,6 +30705,7 @@ class Room extends eventsExports.EventEmitter {
30570
30705
  // unchanged
30571
30706
  return false;
30572
30707
  }
30708
+ this.log.info("connection state changed: ".concat(this.state, " -> ").concat(state));
30573
30709
  this.state = state;
30574
30710
  this.incomingDataStreamManager.setConnected(state === ConnectionState.Connected);
30575
30711
  this.emit(RoomEvent.ConnectionStateChanged, this.state);
@@ -30715,15 +30851,15 @@ class Room extends eventsExports.EventEmitter {
30715
30851
  // only extract logContext from arguments in order to avoid logging the whole object tree
30716
30852
  const minimizedArgs = mapArgs(args).filter(arg => arg !== undefined);
30717
30853
  if (event === RoomEvent.TrackSubscribed || event === RoomEvent.TrackUnsubscribed) {
30718
- this.log.trace("subscribe trace: ".concat(event), Object.assign(Object.assign({}, this.logContext), {
30854
+ this.log.trace("subscribe trace: ".concat(event), {
30719
30855
  event,
30720
30856
  args: minimizedArgs
30721
- }));
30857
+ });
30722
30858
  }
30723
- this.log.debug("room event ".concat(event), Object.assign(Object.assign({}, this.logContext), {
30859
+ this.log.debug("room event ".concat(event), {
30724
30860
  event,
30725
30861
  args: minimizedArgs
30726
- }));
30862
+ });
30727
30863
  }
30728
30864
  return super.emit(event, ...args);
30729
30865
  }