livekit-client 2.4.2 → 2.5.1

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 (80) hide show
  1. package/README.md +8 -4
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  4. package/dist/livekit-client.esm.mjs +374 -102
  5. package/dist/livekit-client.esm.mjs.map +1 -1
  6. package/dist/livekit-client.umd.js +1 -1
  7. package/dist/livekit-client.umd.js.map +1 -1
  8. package/dist/src/api/SignalClient.d.ts +3 -2
  9. package/dist/src/api/SignalClient.d.ts.map +1 -1
  10. package/dist/src/connectionHelper/checks/publishAudio.d.ts.map +1 -1
  11. package/dist/src/connectionHelper/checks/publishVideo.d.ts.map +1 -1
  12. package/dist/src/room/PCTransport.d.ts +1 -1
  13. package/dist/src/room/PCTransport.d.ts.map +1 -1
  14. package/dist/src/room/RTCEngine.d.ts +4 -3
  15. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  16. package/dist/src/room/Room.d.ts +5 -0
  17. package/dist/src/room/Room.d.ts.map +1 -1
  18. package/dist/src/room/errors.d.ts +4 -3
  19. package/dist/src/room/errors.d.ts.map +1 -1
  20. package/dist/src/room/events.d.ts +12 -3
  21. package/dist/src/room/events.d.ts.map +1 -1
  22. package/dist/src/room/participant/LocalParticipant.d.ts +5 -2
  23. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  24. package/dist/src/room/participant/Participant.d.ts +1 -0
  25. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  26. package/dist/src/room/participant/RemoteParticipant.d.ts +1 -1
  27. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  28. package/dist/src/room/timers.d.ts +4 -4
  29. package/dist/src/room/timers.d.ts.map +1 -1
  30. package/dist/src/room/track/RemoteAudioTrack.d.ts +1 -1
  31. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  32. package/dist/src/room/track/RemoteTrack.d.ts +12 -2
  33. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  34. package/dist/src/room/track/RemoteVideoTrack.d.ts +1 -1
  35. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  36. package/dist/src/room/track/options.d.ts +1 -1
  37. package/dist/src/room/types.d.ts +2 -0
  38. package/dist/src/room/types.d.ts.map +1 -1
  39. package/dist/src/room/utils.d.ts +1 -1
  40. package/dist/src/room/utils.d.ts.map +1 -1
  41. package/dist/src/version.d.ts +1 -1
  42. package/dist/ts4.2/src/api/SignalClient.d.ts +3 -2
  43. package/dist/ts4.2/src/room/PCTransport.d.ts +1 -1
  44. package/dist/ts4.2/src/room/RTCEngine.d.ts +4 -3
  45. package/dist/ts4.2/src/room/Room.d.ts +5 -0
  46. package/dist/ts4.2/src/room/errors.d.ts +4 -3
  47. package/dist/ts4.2/src/room/events.d.ts +12 -3
  48. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +5 -2
  49. package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -0
  50. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +1 -1
  51. package/dist/ts4.2/src/room/timers.d.ts +4 -4
  52. package/dist/ts4.2/src/room/track/RemoteAudioTrack.d.ts +1 -1
  53. package/dist/ts4.2/src/room/track/RemoteTrack.d.ts +12 -2
  54. package/dist/ts4.2/src/room/track/RemoteVideoTrack.d.ts +1 -1
  55. package/dist/ts4.2/src/room/track/options.d.ts +1 -1
  56. package/dist/ts4.2/src/room/types.d.ts +2 -0
  57. package/dist/ts4.2/src/room/utils.d.ts +1 -1
  58. package/dist/ts4.2/src/version.d.ts +1 -1
  59. package/package.json +10 -10
  60. package/src/api/SignalClient.ts +12 -6
  61. package/src/connectionHelper/checks/publishAudio.ts +4 -1
  62. package/src/connectionHelper/checks/publishVideo.ts +6 -3
  63. package/src/room/PCTransport.ts +4 -1
  64. package/src/room/RTCEngine.ts +11 -5
  65. package/src/room/Room.ts +42 -5
  66. package/src/room/errors.ts +7 -3
  67. package/src/room/events.ts +12 -1
  68. package/src/room/participant/LocalParticipant.ts +125 -84
  69. package/src/room/participant/Participant.ts +1 -0
  70. package/src/room/participant/RemoteParticipant.ts +1 -1
  71. package/src/room/timers.ts +15 -6
  72. package/src/room/track/LocalVideoTrack.test.ts +60 -0
  73. package/src/room/track/LocalVideoTrack.ts +1 -1
  74. package/src/room/track/RemoteAudioTrack.ts +1 -1
  75. package/src/room/track/RemoteTrack.ts +38 -2
  76. package/src/room/track/RemoteVideoTrack.ts +2 -2
  77. package/src/room/track/options.ts +1 -1
  78. package/src/room/types.ts +2 -0
  79. package/src/room/utils.ts +10 -0
  80. package/src/version.ts +1 -1
@@ -3397,6 +3397,122 @@ target => {
3397
3397
  }
3398
3398
  });
3399
3399
 
3400
+ // @generated by protoc-gen-es v1.10.0 with parameter "target=js+dts"
3401
+ // @generated from file livekit_metrics.proto (package livekit, syntax proto3)
3402
+ /* eslint-disable */
3403
+ // @ts-nocheck
3404
+
3405
+
3406
+ /**
3407
+ * @generated from message livekit.MetricsBatch
3408
+ */
3409
+ const MetricsBatch = /*@__PURE__*/proto3.makeMessageType("livekit.MetricsBatch", () => [{
3410
+ no: 1,
3411
+ name: "str_data",
3412
+ kind: "scalar",
3413
+ T: 9 /* ScalarType.STRING */,
3414
+ repeated: true
3415
+ }, {
3416
+ no: 2,
3417
+ name: "time_series",
3418
+ kind: "message",
3419
+ T: TimeSeriesMetric,
3420
+ repeated: true
3421
+ }, {
3422
+ no: 3,
3423
+ name: "events",
3424
+ kind: "message",
3425
+ T: EventMetric,
3426
+ repeated: true
3427
+ }]);
3428
+
3429
+ /**
3430
+ * @generated from message livekit.TimeSeriesMetric
3431
+ */
3432
+ const TimeSeriesMetric = /*@__PURE__*/proto3.makeMessageType("livekit.TimeSeriesMetric", () => [{
3433
+ no: 1,
3434
+ name: "label",
3435
+ kind: "scalar",
3436
+ T: 13 /* ScalarType.UINT32 */
3437
+ }, {
3438
+ no: 2,
3439
+ name: "participant_identity",
3440
+ kind: "scalar",
3441
+ T: 13 /* ScalarType.UINT32 */
3442
+ }, {
3443
+ no: 3,
3444
+ name: "track_sid",
3445
+ kind: "scalar",
3446
+ T: 13 /* ScalarType.UINT32 */
3447
+ }, {
3448
+ no: 4,
3449
+ name: "start_timestamp",
3450
+ kind: "scalar",
3451
+ T: 3 /* ScalarType.INT64 */
3452
+ }, {
3453
+ no: 5,
3454
+ name: "end_timestamp",
3455
+ kind: "scalar",
3456
+ T: 3 /* ScalarType.INT64 */
3457
+ }, {
3458
+ no: 6,
3459
+ name: "samples",
3460
+ kind: "message",
3461
+ T: MetricSample,
3462
+ repeated: true
3463
+ }]);
3464
+
3465
+ /**
3466
+ * @generated from message livekit.MetricSample
3467
+ */
3468
+ const MetricSample = /*@__PURE__*/proto3.makeMessageType("livekit.MetricSample", () => [{
3469
+ no: 1,
3470
+ name: "timestamp",
3471
+ kind: "scalar",
3472
+ T: 3 /* ScalarType.INT64 */
3473
+ }, {
3474
+ no: 2,
3475
+ name: "value",
3476
+ kind: "scalar",
3477
+ T: 2 /* ScalarType.FLOAT */
3478
+ }]);
3479
+
3480
+ /**
3481
+ * @generated from message livekit.EventMetric
3482
+ */
3483
+ const EventMetric = /*@__PURE__*/proto3.makeMessageType("livekit.EventMetric", () => [{
3484
+ no: 1,
3485
+ name: "label",
3486
+ kind: "scalar",
3487
+ T: 13 /* ScalarType.UINT32 */
3488
+ }, {
3489
+ no: 2,
3490
+ name: "participant_identity",
3491
+ kind: "scalar",
3492
+ T: 13 /* ScalarType.UINT32 */
3493
+ }, {
3494
+ no: 3,
3495
+ name: "track_sid",
3496
+ kind: "scalar",
3497
+ T: 13 /* ScalarType.UINT32 */
3498
+ }, {
3499
+ no: 4,
3500
+ name: "start_timestamp",
3501
+ kind: "scalar",
3502
+ T: 3 /* ScalarType.INT64 */
3503
+ }, {
3504
+ no: 5,
3505
+ name: "end_timestamp",
3506
+ kind: "scalar",
3507
+ T: 3 /* ScalarType.INT64 */,
3508
+ opt: true
3509
+ }, {
3510
+ no: 6,
3511
+ name: "metadata",
3512
+ kind: "scalar",
3513
+ T: 9 /* ScalarType.STRING */
3514
+ }]);
3515
+
3400
3516
  // Copyright 2023 LiveKit, Inc.
3401
3517
  //
3402
3518
  // Licensed under the Apache License, Version 2.0 (the "License");
@@ -3527,6 +3643,9 @@ const DisconnectReason = /*@__PURE__*/proto3.makeEnum("livekit.DisconnectReason"
3527
3643
  }, {
3528
3644
  no: 9,
3529
3645
  name: "SIGNAL_CLOSE"
3646
+ }, {
3647
+ no: 10,
3648
+ name: "ROOM_CLOSED"
3530
3649
  }]);
3531
3650
 
3532
3651
  /**
@@ -3716,6 +3835,11 @@ const ParticipantPermission = /*@__PURE__*/proto3.makeMessageType("livekit.Parti
3716
3835
  name: "agent",
3717
3836
  kind: "scalar",
3718
3837
  T: 8 /* ScalarType.BOOL */
3838
+ }, {
3839
+ no: 12,
3840
+ name: "can_subscribe_metrics",
3841
+ kind: "scalar",
3842
+ T: 8 /* ScalarType.BOOL */
3719
3843
  }]);
3720
3844
 
3721
3845
  /**
@@ -3791,6 +3915,11 @@ const ParticipantInfo = /*@__PURE__*/proto3.makeMessageType("livekit.Participant
3791
3915
  kind: "scalar",
3792
3916
  T: 9 /* ScalarType.STRING */
3793
3917
  }
3918
+ }, {
3919
+ no: 16,
3920
+ name: "disconnect_reason",
3921
+ kind: "enum",
3922
+ T: proto3.getEnumType(DisconnectReason)
3794
3923
  }]);
3795
3924
 
3796
3925
  /**
@@ -4050,6 +4179,12 @@ const DataPacket = /*@__PURE__*/proto3.makeMessageType("livekit.DataPacket", ()
4050
4179
  kind: "message",
4051
4180
  T: Transcription,
4052
4181
  oneof: "value"
4182
+ }, {
4183
+ no: 8,
4184
+ name: "metrics",
4185
+ kind: "message",
4186
+ T: MetricsBatch,
4187
+ oneof: "value"
4053
4188
  }]);
4054
4189
 
4055
4190
  /**
@@ -4742,9 +4877,15 @@ const SignalResponse = /*@__PURE__*/proto3.makeMessageType("livekit.SignalRespon
4742
4877
  oneof: "message"
4743
4878
  }, {
4744
4879
  no: 22,
4745
- name: "error_response",
4880
+ name: "request_response",
4746
4881
  kind: "message",
4747
- T: ErrorResponse,
4882
+ T: RequestResponse,
4883
+ oneof: "message"
4884
+ }, {
4885
+ no: 23,
4886
+ name: "track_subscribed",
4887
+ kind: "message",
4888
+ T: TrackSubscribed,
4748
4889
  oneof: "message"
4749
4890
  }]);
4750
4891
 
@@ -4858,6 +4999,11 @@ const TrickleRequest = /*@__PURE__*/proto3.makeMessageType("livekit.TrickleReque
4858
4999
  name: "target",
4859
5000
  kind: "enum",
4860
5001
  T: proto3.getEnumType(SignalTarget)
5002
+ }, {
5003
+ no: 3,
5004
+ name: "final",
5005
+ kind: "scalar",
5006
+ T: 8 /* ScalarType.BOOL */
4861
5007
  }]);
4862
5008
 
4863
5009
  /**
@@ -4945,6 +5091,17 @@ const JoinResponse = /*@__PURE__*/proto3.makeMessageType("livekit.JoinResponse",
4945
5091
  name: "sif_trailer",
4946
5092
  kind: "scalar",
4947
5093
  T: 12 /* ScalarType.BYTES */
5094
+ }, {
5095
+ no: 14,
5096
+ name: "enabled_publish_codecs",
5097
+ kind: "message",
5098
+ T: Codec,
5099
+ repeated: true
5100
+ }, {
5101
+ no: 15,
5102
+ name: "fast_publish",
5103
+ kind: "scalar",
5104
+ T: 8 /* ScalarType.BOOL */
4948
5105
  }]);
4949
5106
 
4950
5107
  /**
@@ -5615,9 +5772,9 @@ const SubscriptionResponse = /*@__PURE__*/proto3.makeMessageType("livekit.Subscr
5615
5772
  }]);
5616
5773
 
5617
5774
  /**
5618
- * @generated from message livekit.ErrorResponse
5775
+ * @generated from message livekit.RequestResponse
5619
5776
  */
5620
- const ErrorResponse = /*@__PURE__*/proto3.makeMessageType("livekit.ErrorResponse", () => [{
5777
+ const RequestResponse = /*@__PURE__*/proto3.makeMessageType("livekit.RequestResponse", () => [{
5621
5778
  no: 1,
5622
5779
  name: "request_id",
5623
5780
  kind: "scalar",
@@ -5626,7 +5783,7 @@ const ErrorResponse = /*@__PURE__*/proto3.makeMessageType("livekit.ErrorResponse
5626
5783
  no: 2,
5627
5784
  name: "reason",
5628
5785
  kind: "enum",
5629
- T: proto3.getEnumType(ErrorResponse_Reason)
5786
+ T: proto3.getEnumType(RequestResponse_Reason)
5630
5787
  }, {
5631
5788
  no: 3,
5632
5789
  name: "message",
@@ -5635,11 +5792,11 @@ const ErrorResponse = /*@__PURE__*/proto3.makeMessageType("livekit.ErrorResponse
5635
5792
  }]);
5636
5793
 
5637
5794
  /**
5638
- * @generated from enum livekit.ErrorResponse.Reason
5795
+ * @generated from enum livekit.RequestResponse.Reason
5639
5796
  */
5640
- const ErrorResponse_Reason = /*@__PURE__*/proto3.makeEnum("livekit.ErrorResponse.Reason", [{
5797
+ const RequestResponse_Reason = /*@__PURE__*/proto3.makeEnum("livekit.RequestResponse.Reason", [{
5641
5798
  no: 0,
5642
- name: "UNKNOWN"
5799
+ name: "OK"
5643
5800
  }, {
5644
5801
  no: 1,
5645
5802
  name: "NOT_FOUND"
@@ -5648,7 +5805,17 @@ const ErrorResponse_Reason = /*@__PURE__*/proto3.makeEnum("livekit.ErrorResponse
5648
5805
  name: "NOT_ALLOWED"
5649
5806
  }, {
5650
5807
  no: 3,
5651
- name: "INVALID_ARGUMENT"
5808
+ name: "LIMIT_EXCEEDED"
5809
+ }]);
5810
+
5811
+ /**
5812
+ * @generated from message livekit.TrackSubscribed
5813
+ */
5814
+ const TrackSubscribed = /*@__PURE__*/proto3.makeMessageType("livekit.TrackSubscribed", () => [{
5815
+ no: 1,
5816
+ name: "track_sid",
5817
+ kind: "scalar",
5818
+ T: 9 /* ScalarType.STRING */
5652
5819
  }]);
5653
5820
 
5654
5821
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -9818,8 +9985,7 @@ class PublishDataError extends LivekitError {
9818
9985
  }
9819
9986
  }
9820
9987
  class SignalRequestError extends LivekitError {
9821
- constructor(message) {
9822
- let reason = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ErrorResponse_Reason.UNKNOWN;
9988
+ constructor(message, reason) {
9823
9989
  super(15, message);
9824
9990
  this.reason = reason;
9825
9991
  }
@@ -10154,6 +10320,10 @@ var RoomEvent;
10154
10320
  * args: (kind: MediaDeviceKind, deviceId: string)
10155
10321
  */
10156
10322
  RoomEvent["ActiveDeviceChanged"] = "activeDeviceChanged";
10323
+ /**
10324
+ * fired when the first remote participant has subscribed to the localParticipant's track
10325
+ */
10326
+ RoomEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
10157
10327
  })(RoomEvent || (RoomEvent = {}));
10158
10328
  var ParticipantEvent;
10159
10329
  (function (ParticipantEvent) {
@@ -10317,6 +10487,10 @@ var ParticipantEvent;
10317
10487
  * When a participant's attributes changed, this event will be emitted with the changed attributes
10318
10488
  */
10319
10489
  ParticipantEvent["AttributesChanged"] = "attributesChanged";
10490
+ /**
10491
+ * fired on local participant only, when the first remote participant has subscribed to the track specified in the payload
10492
+ */
10493
+ ParticipantEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
10320
10494
  })(ParticipantEvent || (ParticipantEvent = {}));
10321
10495
  /** @internal */
10322
10496
  var EngineEvent;
@@ -10346,8 +10520,9 @@ var EngineEvent;
10346
10520
  EngineEvent["RemoteMute"] = "remoteMute";
10347
10521
  EngineEvent["SubscribedQualityUpdate"] = "subscribedQualityUpdate";
10348
10522
  EngineEvent["LocalTrackUnpublished"] = "localTrackUnpublished";
10523
+ EngineEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
10349
10524
  EngineEvent["Offline"] = "offline";
10350
- EngineEvent["SignalRequestError"] = "signalRequestError";
10525
+ EngineEvent["SignalRequestResponse"] = "signalRequestResponse";
10351
10526
  })(EngineEvent || (EngineEvent = {}));
10352
10527
  var TrackEvent;
10353
10528
  (function (TrackEvent) {
@@ -10539,10 +10714,10 @@ function getOSVersion(ua) {
10539
10714
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
10540
10715
  }
10541
10716
 
10542
- var version$1 = "2.4.2";
10717
+ var version$1 = "2.5.1";
10543
10718
 
10544
10719
  const version = version$1;
10545
- const protocolVersion = 13;
10720
+ const protocolVersion = 15;
10546
10721
 
10547
10722
  /**
10548
10723
  * Timers that can be overridden with platform specific implementations
@@ -10550,12 +10725,12 @@ const protocolVersion = 13;
10550
10725
  * that the timer fires on time.
10551
10726
  */
10552
10727
  class CriticalTimers {}
10553
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
10554
10728
  CriticalTimers.setTimeout = function () {
10555
10729
  return setTimeout(...arguments);
10556
10730
  };
10731
+ CriticalTimers.setInterval =
10557
10732
  // eslint-disable-next-line @typescript-eslint/no-implied-eval
10558
- CriticalTimers.setInterval = function () {
10733
+ function () {
10559
10734
  return setInterval(...arguments);
10560
10735
  };
10561
10736
  CriticalTimers.clearTimeout = function () {
@@ -11667,7 +11842,7 @@ function toHttpUrl(url) {
11667
11842
  }
11668
11843
  return url;
11669
11844
  }
11670
- function extractTranscriptionSegments(transcription) {
11845
+ function extractTranscriptionSegments(transcription, firstReceivedTimesMap) {
11671
11846
  return transcription.segments.map(_ref => {
11672
11847
  let {
11673
11848
  id,
@@ -11677,13 +11852,23 @@ function extractTranscriptionSegments(transcription) {
11677
11852
  endTime,
11678
11853
  final
11679
11854
  } = _ref;
11855
+ var _a;
11856
+ const firstReceivedTime = (_a = firstReceivedTimesMap.get(id)) !== null && _a !== void 0 ? _a : Date.now();
11857
+ const lastReceivedTime = Date.now();
11858
+ if (final) {
11859
+ firstReceivedTimesMap.delete(id);
11860
+ } else {
11861
+ firstReceivedTimesMap.set(id, firstReceivedTime);
11862
+ }
11680
11863
  return {
11681
11864
  id,
11682
11865
  text,
11683
11866
  startTime: Number.parseInt(startTime.toString()),
11684
11867
  endTime: Number.parseInt(endTime.toString()),
11685
11868
  final,
11686
- language
11869
+ language,
11870
+ firstReceivedTime,
11871
+ lastReceivedTime
11687
11872
  };
11688
11873
  });
11689
11874
  }
@@ -12863,6 +13048,7 @@ class SignalClient {
12863
13048
  return function* () {
12864
13049
  const unlock = yield _this.closingLock.lock();
12865
13050
  try {
13051
+ _this.clearPingInterval();
12866
13052
  if (updateState) {
12867
13053
  _this.state = SignalConnectionState.DISCONNECTING;
12868
13054
  }
@@ -12891,7 +13077,6 @@ class SignalClient {
12891
13077
  if (updateState) {
12892
13078
  _this.state = SignalConnectionState.DISCONNECTED;
12893
13079
  }
12894
- _this.clearPingInterval();
12895
13080
  unlock();
12896
13081
  }
12897
13082
  }();
@@ -13158,9 +13343,13 @@ class SignalClient {
13158
13343
  this.rtt = Date.now() - Number.parseInt(msg.value.lastPingTimestamp.toString());
13159
13344
  this.resetPingTimeout();
13160
13345
  pingHandled = true;
13161
- } else if (msg.case === 'errorResponse') {
13162
- if (this.onErrorResponse) {
13163
- this.onErrorResponse(msg.value);
13346
+ } else if (msg.case === 'requestResponse') {
13347
+ if (this.onRequestResponse) {
13348
+ this.onRequestResponse(msg.value);
13349
+ }
13350
+ } else if (msg.case === 'trackSubscribed') {
13351
+ if (this.onLocalTrackSubscribed) {
13352
+ this.onLocalTrackSubscribed(msg.value.trackSid);
13164
13353
  }
13165
13354
  } else {
13166
13355
  this.log.debug('unsupported message', Object.assign(Object.assign({}, this.logContext), {
@@ -13980,6 +14169,7 @@ the first few seconds. So we use a 70% of target bitrate here as the start bitra
13980
14169
  eliminate this issue.
13981
14170
  */
13982
14171
  const startBitrateForSVC = 0.7;
14172
+ const debounceInterval = 20;
13983
14173
  const PCEvents = {
13984
14174
  NegotiationStarted: 'negotiationStarted',
13985
14175
  NegotiationComplete: 'negotiationComplete',
@@ -14016,7 +14206,7 @@ class PCTransport extends eventsExports.EventEmitter {
14016
14206
  throw e;
14017
14207
  }
14018
14208
  }
14019
- }), 100);
14209
+ }), debounceInterval);
14020
14210
  this.close = () => {
14021
14211
  if (!this._pc) {
14022
14212
  return;
@@ -14195,6 +14385,9 @@ class PCTransport extends eventsExports.EventEmitter {
14195
14385
  // actually negotiate
14196
14386
  this.log.debug('starting to negotiate', this.logContext);
14197
14387
  const offer = yield this.pc.createOffer(options);
14388
+ this.log.debug('original offer', Object.assign({
14389
+ sdp: offer.sdp
14390
+ }, this.logContext));
14198
14391
  const sdpParsed = parse((_a = offer.sdp) !== null && _a !== void 0 ? _a : '');
14199
14392
  sdpParsed.media.forEach(media => {
14200
14393
  if (media.type === 'audio') {
@@ -15981,7 +16174,7 @@ function videoLayersFromEncodings(width, height, encodings, svc) {
15981
16174
  const bitratesRatio = sm.suffix == 'h' ? 2 : 3;
15982
16175
  for (let i = 0; i < sm.spatial; i += 1) {
15983
16176
  layers.push(new VideoLayer({
15984
- quality: VideoQuality.HIGH - i,
16177
+ quality: Math.min(VideoQuality.HIGH, sm.spatial - 1) - i,
15985
16178
  width: Math.ceil(width / Math.pow(resRatio, i)),
15986
16179
  height: Math.ceil(height / Math.pow(resRatio, i)),
15987
16180
  bitrate: encodings[0].maxBitrate ? Math.ceil(encodings[0].maxBitrate / Math.pow(bitratesRatio, i)) : 0,
@@ -16211,7 +16404,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16211
16404
  this.client.onSubscriptionPermissionUpdate = update => this.emit(EngineEvent.SubscriptionPermissionUpdate, update);
16212
16405
  this.client.onSpeakersChanged = update => this.emit(EngineEvent.SpeakersChanged, update);
16213
16406
  this.client.onStreamStateUpdate = update => this.emit(EngineEvent.StreamStateChanged, update);
16214
- this.client.onErrorResponse = error => this.emit(EngineEvent.SignalRequestError, error);
16407
+ this.client.onRequestResponse = response => this.emit(EngineEvent.SignalRequestResponse, response);
16215
16408
  }
16216
16409
  /** @internal */
16217
16410
  get logContext() {
@@ -16240,7 +16433,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16240
16433
  yield this.configure(joinResponse);
16241
16434
  }
16242
16435
  // create offer
16243
- if (!this.subscriberPrimary) {
16436
+ if (!this.subscriberPrimary || joinResponse.fastPublish) {
16244
16437
  this.negotiate();
16245
16438
  }
16246
16439
  this.clientConfiguration = joinResponse.clientConfiguration;
@@ -16477,6 +16670,9 @@ class RTCEngine extends eventsExports.EventEmitter {
16477
16670
  this.client.onLocalTrackUnpublished = response => {
16478
16671
  this.emit(EngineEvent.LocalTrackUnpublished, response);
16479
16672
  };
16673
+ this.client.onLocalTrackSubscribed = trackSid => {
16674
+ this.emit(EngineEvent.LocalTrackSubscribed, trackSid);
16675
+ };
16480
16676
  this.client.onTokenRefresh = token => {
16481
16677
  this.token = token;
16482
16678
  };
@@ -17198,6 +17394,9 @@ class RemoteTrack extends Track {
17198
17394
  const onRemoveTrack = event => {
17199
17395
  if (event.track === this._mediaStreamTrack) {
17200
17396
  stream.removeEventListener('removetrack', onRemoveTrack);
17397
+ if (this.receiver && 'playoutDelayHint' in this.receiver) {
17398
+ this.receiver.playoutDelayHint = undefined;
17399
+ }
17201
17400
  this.receiver = undefined;
17202
17401
  this._currentBitrate = 0;
17203
17402
  this.emit(TrackEvent.Ended, this);
@@ -17231,6 +17430,37 @@ class RemoteTrack extends Track {
17231
17430
  return statsReport;
17232
17431
  });
17233
17432
  }
17433
+ /**
17434
+ * Allows to set a playout delay (in seconds) for this track.
17435
+ * A higher value allows for more buffering of the track in the browser
17436
+ * and will result in a delay of media being played back of `delayInSeconds`
17437
+ */
17438
+ setPlayoutDelay(delayInSeconds) {
17439
+ if (this.receiver) {
17440
+ if ('playoutDelayHint' in this.receiver) {
17441
+ this.receiver.playoutDelayHint = delayInSeconds;
17442
+ } else {
17443
+ this.log.warn('Playout delay not supported in this browser');
17444
+ }
17445
+ } else {
17446
+ this.log.warn('Cannot set playout delay, track already ended');
17447
+ }
17448
+ }
17449
+ /**
17450
+ * Returns the current playout delay (in seconds) of this track.
17451
+ */
17452
+ getPlayoutDelay() {
17453
+ if (this.receiver) {
17454
+ if ('playoutDelayHint' in this.receiver) {
17455
+ return this.receiver.playoutDelayHint;
17456
+ } else {
17457
+ this.log.warn('Playout delay not supported in this browser');
17458
+ }
17459
+ } else {
17460
+ this.log.warn('Cannot get playout delay, track already ended');
17461
+ }
17462
+ return 0;
17463
+ }
17234
17464
  /* @internal */
17235
17465
  startMonitor() {
17236
17466
  if (!this.monitorInterval) {
@@ -18242,6 +18472,7 @@ class LocalParticipant extends Participant {
18242
18472
  this.participantTrackPermissions = [];
18243
18473
  this.allParticipantsAllowedToSubscribe = true;
18244
18474
  this.encryptionType = Encryption_Type.NONE;
18475
+ this.enabledPublishVideoCodecs = [];
18245
18476
  this.handleReconnecting = () => {
18246
18477
  if (!this.reconnectFuture) {
18247
18478
  this.reconnectFuture = new Future();
@@ -18261,15 +18492,17 @@ class LocalParticipant extends Participant {
18261
18492
  this.reconnectFuture = undefined;
18262
18493
  }
18263
18494
  };
18264
- this.handleSignalRequestError = error => {
18495
+ this.handleSignalRequestResponse = response => {
18265
18496
  const {
18266
18497
  requestId,
18267
18498
  reason,
18268
18499
  message
18269
- } = error;
18270
- const failedRequest = this.pendingSignalRequests.get(requestId);
18271
- if (failedRequest) {
18272
- failedRequest.reject(new SignalRequestError(message, reason));
18500
+ } = response;
18501
+ const targetRequest = this.pendingSignalRequests.get(requestId);
18502
+ if (targetRequest) {
18503
+ if (reason !== RequestResponse_Reason.OK) {
18504
+ targetRequest.reject(new SignalRequestError(message, reason));
18505
+ }
18273
18506
  this.pendingSignalRequests.delete(requestId);
18274
18507
  }
18275
18508
  };
@@ -18453,7 +18686,7 @@ class LocalParticipant extends Participant {
18453
18686
  pub.unmute();
18454
18687
  }
18455
18688
  });
18456
- this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished).on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate).on(EngineEvent.Disconnected, this.handleDisconnected).on(EngineEvent.SignalRequestError, this.handleSignalRequestError);
18689
+ this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished).on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate).on(EngineEvent.Disconnected, this.handleDisconnected).on(EngineEvent.SignalRequestResponse, this.handleSignalRequestResponse);
18457
18690
  }
18458
18691
  /**
18459
18692
  * Sets and updates the metadata of the local participant.
@@ -18532,7 +18765,7 @@ class LocalParticipant extends Participant {
18532
18765
  }
18533
18766
  yield sleep(50);
18534
18767
  }
18535
- reject(new SignalRequestError('Request to update local metadata timed out'));
18768
+ reject(new SignalRequestError('Request to update local metadata timed out', 'TimeoutError'));
18536
18769
  } catch (e) {
18537
18770
  if (e instanceof Error) reject(e);
18538
18771
  }
@@ -18904,7 +19137,7 @@ class LocalParticipant extends Participant {
18904
19137
  }
18905
19138
  publish(track, opts, isStereo) {
18906
19139
  return __awaiter(this, void 0, void 0, function* () {
18907
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
19140
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
18908
19141
  const existingTrackOfSource = Array.from(this.trackPublications.values()).find(publishedTrack => track instanceof LocalTrack && publishedTrack.source === track.source);
18909
19142
  if (existingTrackOfSource && track.source !== Track.Source.Unknown) {
18910
19143
  this.log.info("publishing a second track with the same source: ".concat(track.source), Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)));
@@ -18927,6 +19160,12 @@ class LocalParticipant extends Participant {
18927
19160
  if (opts.videoCodec === undefined) {
18928
19161
  opts.videoCodec = defaultVideoCodec;
18929
19162
  }
19163
+ if (this.enabledPublishVideoCodecs.length > 0) {
19164
+ // fallback to a supported codec if it is not supported
19165
+ if (!this.enabledPublishVideoCodecs.some(c => opts.videoCodec === mimeTypeToVideoCodecString(c.mime))) {
19166
+ opts.videoCodec = mimeTypeToVideoCodecString(this.enabledPublishVideoCodecs[0].mime);
19167
+ }
19168
+ }
18930
19169
  const videoCodec = opts.videoCodec;
18931
19170
  // handle track actions
18932
19171
  track.on(TrackEvent.Muted, this.onTrackMuted);
@@ -19029,25 +19268,75 @@ class LocalParticipant extends Participant {
19029
19268
  if (!this.engine || this.engine.isClosed) {
19030
19269
  throw new UnexpectedConnectionState('cannot publish track when not connected');
19031
19270
  }
19032
- const ti = yield this.engine.addTrack(req);
19033
- // server might not support the codec the client has requested, in that case, fallback
19034
- // to a supported codec
19035
- let primaryCodecMime;
19036
- ti.codecs.forEach(codec => {
19037
- if (primaryCodecMime === undefined) {
19038
- primaryCodecMime = codec.mimeType;
19271
+ const negotiate = () => __awaiter(this, void 0, void 0, function* () {
19272
+ var _a, _b, _c;
19273
+ if (!this.engine.pcManager) {
19274
+ throw new UnexpectedConnectionState('pcManager is not ready');
19275
+ }
19276
+ track.sender = yield this.engine.createSender(track, opts, encodings);
19277
+ if (track instanceof LocalVideoTrack) {
19278
+ (_a = opts.degradationPreference) !== null && _a !== void 0 ? _a : opts.degradationPreference = getDefaultDegradationPreference(track);
19279
+ track.setDegradationPreference(opts.degradationPreference);
19280
+ }
19281
+ if (encodings) {
19282
+ if (isFireFox() && track.kind === Track.Kind.Audio) {
19283
+ /* Refer to RFC https://datatracker.ietf.org/doc/html/rfc7587#section-6.1,
19284
+ livekit-server uses maxaveragebitrate=510000 in the answer sdp to permit client to
19285
+ publish high quality audio track. But firefox always uses this value as the actual
19286
+ bitrates, causing the audio bitrates to rise to 510Kbps in any stereo case unexpectedly.
19287
+ So the client need to modify maxaverragebitrates in answer sdp to user provided value to
19288
+ fix the issue.
19289
+ */
19290
+ let trackTransceiver = undefined;
19291
+ for (const transceiver of this.engine.pcManager.publisher.getTransceivers()) {
19292
+ if (transceiver.sender === track.sender) {
19293
+ trackTransceiver = transceiver;
19294
+ break;
19295
+ }
19296
+ }
19297
+ if (trackTransceiver) {
19298
+ this.engine.pcManager.publisher.setTrackCodecBitrate({
19299
+ transceiver: trackTransceiver,
19300
+ codec: 'opus',
19301
+ maxbr: ((_b = encodings[0]) === null || _b === void 0 ? void 0 : _b.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
19302
+ });
19303
+ }
19304
+ } else if (track.codec && isSVCCodec(track.codec) && ((_c = encodings[0]) === null || _c === void 0 ? void 0 : _c.maxBitrate)) {
19305
+ this.engine.pcManager.publisher.setTrackCodecBitrate({
19306
+ cid: req.cid,
19307
+ codec: track.codec,
19308
+ maxbr: encodings[0].maxBitrate / 1000
19309
+ });
19310
+ }
19039
19311
  }
19312
+ yield this.engine.negotiate();
19040
19313
  });
19041
- if (primaryCodecMime && track.kind === Track.Kind.Video) {
19042
- const updatedCodec = mimeTypeToVideoCodecString(primaryCodecMime);
19043
- if (updatedCodec !== videoCodec) {
19044
- this.log.debug('falling back to server selected codec', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
19045
- codec: updatedCodec
19046
- }));
19047
- opts.videoCodec = updatedCodec;
19048
- // recompute encodings since bitrates/etc could have changed
19049
- encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, req.width, req.height, opts);
19314
+ let ti;
19315
+ if (this.enabledPublishVideoCodecs.length > 0) {
19316
+ const rets = yield Promise.all([this.engine.addTrack(req), negotiate()]);
19317
+ ti = rets[0];
19318
+ } else {
19319
+ ti = yield this.engine.addTrack(req);
19320
+ // server might not support the codec the client has requested, in that case, fallback
19321
+ // to a supported codec
19322
+ let primaryCodecMime;
19323
+ ti.codecs.forEach(codec => {
19324
+ if (primaryCodecMime === undefined) {
19325
+ primaryCodecMime = codec.mimeType;
19326
+ }
19327
+ });
19328
+ if (primaryCodecMime && track.kind === Track.Kind.Video) {
19329
+ const updatedCodec = mimeTypeToVideoCodecString(primaryCodecMime);
19330
+ if (updatedCodec !== videoCodec) {
19331
+ this.log.debug('falling back to server selected codec', Object.assign(Object.assign(Object.assign({}, this.logContext), getLogContextFromTrack(track)), {
19332
+ codec: updatedCodec
19333
+ }));
19334
+ opts.videoCodec = updatedCodec;
19335
+ // recompute encodings since bitrates/etc could have changed
19336
+ encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, req.width, req.height, opts);
19337
+ }
19050
19338
  }
19339
+ yield negotiate();
19051
19340
  }
19052
19341
  const publication = new LocalTrackPublication(track.kind, ti, track, {
19053
19342
  loggerName: this.roomOptions.loggerName,
@@ -19056,50 +19345,10 @@ class LocalParticipant extends Participant {
19056
19345
  // save options for when it needs to be republished again
19057
19346
  publication.options = opts;
19058
19347
  track.sid = ti.sid;
19059
- if (!this.engine.pcManager) {
19060
- throw new UnexpectedConnectionState('pcManager is not ready');
19061
- }
19062
19348
  this.log.debug("publishing ".concat(track.kind, " with encodings"), Object.assign(Object.assign({}, this.logContext), {
19063
19349
  encodings,
19064
19350
  trackInfo: ti
19065
19351
  }));
19066
- track.sender = yield this.engine.createSender(track, opts, encodings);
19067
- if (track instanceof LocalVideoTrack) {
19068
- (_l = opts.degradationPreference) !== null && _l !== void 0 ? _l : opts.degradationPreference = getDefaultDegradationPreference(track);
19069
- track.setDegradationPreference(opts.degradationPreference);
19070
- }
19071
- if (encodings) {
19072
- if (isFireFox() && track.kind === Track.Kind.Audio) {
19073
- /* Refer to RFC https://datatracker.ietf.org/doc/html/rfc7587#section-6.1,
19074
- livekit-server uses maxaveragebitrate=510000 in the answer sdp to permit client to
19075
- publish high quality audio track. But firefox always uses this value as the actual
19076
- bitrates, causing the audio bitrates to rise to 510Kbps in any stereo case unexpectedly.
19077
- So the client need to modify maxaverragebitrates in answer sdp to user provided value to
19078
- fix the issue.
19079
- */
19080
- let trackTransceiver = undefined;
19081
- for (const transceiver of this.engine.pcManager.publisher.getTransceivers()) {
19082
- if (transceiver.sender === track.sender) {
19083
- trackTransceiver = transceiver;
19084
- break;
19085
- }
19086
- }
19087
- if (trackTransceiver) {
19088
- this.engine.pcManager.publisher.setTrackCodecBitrate({
19089
- transceiver: trackTransceiver,
19090
- codec: 'opus',
19091
- maxbr: ((_m = encodings[0]) === null || _m === void 0 ? void 0 : _m.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
19092
- });
19093
- }
19094
- } else if (track.codec && isSVCCodec(track.codec) && ((_o = encodings[0]) === null || _o === void 0 ? void 0 : _o.maxBitrate)) {
19095
- this.engine.pcManager.publisher.setTrackCodecBitrate({
19096
- cid: req.cid,
19097
- codec: track.codec,
19098
- maxbr: encodings[0].maxBitrate / 1000
19099
- });
19100
- }
19101
- }
19102
- yield this.engine.negotiate();
19103
19352
  if (track instanceof LocalVideoTrack) {
19104
19353
  track.startMonitor(this.engine.client);
19105
19354
  } else if (track instanceof LocalAudioTrack) {
@@ -19165,9 +19414,12 @@ class LocalParticipant extends Participant {
19165
19414
  if (!this.engine || this.engine.isClosed) {
19166
19415
  throw new UnexpectedConnectionState('cannot publish track when not connected');
19167
19416
  }
19168
- const ti = yield this.engine.addTrack(req);
19169
- yield this.engine.createSimulcastSender(track, simulcastTrack, opts, encodings);
19170
- yield this.engine.negotiate();
19417
+ const negotiate = () => __awaiter(this, void 0, void 0, function* () {
19418
+ yield this.engine.createSimulcastSender(track, simulcastTrack, opts, encodings);
19419
+ yield this.engine.negotiate();
19420
+ });
19421
+ const rets = yield Promise.all([this.engine.addTrack(req), negotiate()]);
19422
+ const ti = rets[0];
19171
19423
  this.log.debug("published ".concat(videoCodec, " for track ").concat(track.sid), Object.assign(Object.assign({}, this.logContext), {
19172
19424
  encodings,
19173
19425
  trackInfo: ti
@@ -19351,6 +19603,10 @@ class LocalParticipant extends Participant {
19351
19603
  }
19352
19604
  }
19353
19605
  /** @internal */
19606
+ setEnabledPublishCodecs(codecs) {
19607
+ this.enabledPublishVideoCodecs = codecs.filter(c => c.mime.split('/')[0].toLowerCase() === 'video');
19608
+ }
19609
+ /** @internal */
19354
19610
  updateInfo(info) {
19355
19611
  if (info.sid !== this.sid) {
19356
19612
  // drop updates that specify a wrong sid.
@@ -20072,6 +20328,7 @@ class Room extends eventsExports.EventEmitter {
20072
20328
  const pi = joinResponse.participant;
20073
20329
  this.localParticipant.sid = pi.sid;
20074
20330
  this.localParticipant.identity = pi.identity;
20331
+ this.localParticipant.setEnabledPublishCodecs(joinResponse.enabledPublishCodecs);
20075
20332
  if (this.options.e2ee && this.e2eeManager) {
20076
20333
  try {
20077
20334
  this.e2eeManager.setSifTrailer(joinResponse.sifTrailer);
@@ -20484,7 +20741,7 @@ class Room extends eventsExports.EventEmitter {
20484
20741
  // find the participant
20485
20742
  const participant = transcription.transcribedParticipantIdentity === this.localParticipant.identity ? this.localParticipant : this.getParticipantByIdentity(transcription.transcribedParticipantIdentity);
20486
20743
  const publication = participant === null || participant === void 0 ? void 0 : participant.trackPublications.get(transcription.trackId);
20487
- const segments = extractTranscriptionSegments(transcription);
20744
+ const segments = extractTranscriptionSegments(transcription, this.transcriptionReceivedTimes);
20488
20745
  publication === null || publication === void 0 ? void 0 : publication.emit(TrackEvent.TranscriptionReceived, segments);
20489
20746
  participant === null || participant === void 0 ? void 0 : participant.emit(ParticipantEvent.TranscriptionReceived, segments, publication);
20490
20747
  this.emit(RoomEvent.TranscriptionReceived, segments, participant, publication);
@@ -20599,6 +20856,7 @@ class Room extends eventsExports.EventEmitter {
20599
20856
  this.sidToIdentity = new Map();
20600
20857
  this.options = Object.assign(Object.assign({}, roomOptionDefaults), options);
20601
20858
  this.log = getLogger((_a = this.options.loggerName) !== null && _a !== void 0 ? _a : LoggerNames.Room);
20859
+ this.transcriptionReceivedTimes = new Map();
20602
20860
  this.options.audioCaptureDefaults = Object.assign(Object.assign({}, audioDefaults), options === null || options === void 0 ? void 0 : options.audioCaptureDefaults);
20603
20861
  this.options.videoCaptureDefaults = Object.assign(Object.assign({}, videoDefaults), options === null || options === void 0 ? void 0 : options.videoCaptureDefaults);
20604
20862
  this.options.publishDefaults = Object.assign(Object.assign({}, publishDefaults), options === null || options === void 0 ? void 0 : options.publishDefaults);
@@ -20744,6 +21002,19 @@ class Room extends eventsExports.EventEmitter {
20744
21002
  }
20745
21003
  }).on(EngineEvent.DCBufferStatusChanged, (status, kind) => {
20746
21004
  this.emit(RoomEvent.DCBufferStatusChanged, status, kind);
21005
+ }).on(EngineEvent.LocalTrackSubscribed, subscribedSid => {
21006
+ const trackPublication = this.localParticipant.getTrackPublications().find(_ref2 => {
21007
+ let {
21008
+ trackSid
21009
+ } = _ref2;
21010
+ return trackSid === subscribedSid;
21011
+ });
21012
+ if (!trackPublication) {
21013
+ this.log.warn('could not find local track subscription for subscribed event', this.logContext);
21014
+ return;
21015
+ }
21016
+ this.localParticipant.emit(ParticipantEvent.LocalTrackSubscribed, trackPublication);
21017
+ this.emitWhenConnected(RoomEvent.LocalTrackSubscribed, trackPublication, this.localParticipant);
20747
21018
  });
20748
21019
  if (this.localParticipant) {
20749
21020
  this.localParticipant.setupEngine(this.engine);
@@ -21113,6 +21384,7 @@ class Room extends eventsExports.EventEmitter {
21113
21384
  this.clearConnectionReconcile();
21114
21385
  this.isResuming = false;
21115
21386
  this.bufferedEvents = [];
21387
+ this.transcriptionReceivedTimes.clear();
21116
21388
  if (this.state === ConnectionState.Disconnected) {
21117
21389
  return;
21118
21390
  }
@@ -21356,8 +21628,8 @@ class Room extends eventsExports.EventEmitter {
21356
21628
  return true;
21357
21629
  }
21358
21630
  emitBufferedEvents() {
21359
- this.bufferedEvents.forEach(_ref2 => {
21360
- let [ev, args] = _ref2;
21631
+ this.bufferedEvents.forEach(_ref3 => {
21632
+ let [ev, args] = _ref3;
21361
21633
  this.emit(ev, ...args);
21362
21634
  });
21363
21635
  this.bufferedEvents = [];
@@ -21468,7 +21740,7 @@ class Room extends eventsExports.EventEmitter {
21468
21740
  sid: Math.floor(Math.random() * 10000).toString(),
21469
21741
  type: TrackType.AUDIO
21470
21742
  });
21471
- p.addSubscribedMediaTrack(dummyVideo, videoTrack.sid, new MediaStream([dummyVideo]));
21743
+ p.addSubscribedMediaTrack(dummyVideo, videoTrack.sid, new MediaStream([dummyVideo]), new RTCRtpReceiver());
21472
21744
  info.tracks = [...info.tracks, videoTrack];
21473
21745
  }
21474
21746
  if (participantOptions.audio) {
@@ -21478,7 +21750,7 @@ class Room extends eventsExports.EventEmitter {
21478
21750
  sid: Math.floor(Math.random() * 10000).toString(),
21479
21751
  type: TrackType.AUDIO
21480
21752
  });
21481
- p.addSubscribedMediaTrack(dummyTrack, audioTrack.sid, new MediaStream([dummyTrack]));
21753
+ p.addSubscribedMediaTrack(dummyTrack, audioTrack.sid, new MediaStream([dummyTrack]), new RTCRtpReceiver());
21482
21754
  info.tracks = [...info.tracks, audioTrack];
21483
21755
  }
21484
21756
  p.updateInfo(info);
@@ -21774,7 +22046,7 @@ class PublishAudioCheck extends Checker {
21774
22046
  }
21775
22047
  let numPackets = 0;
21776
22048
  stats.forEach(stat => {
21777
- if (stat.type === 'outbound-rtp' && stat.mediaType === 'audio') {
22049
+ if (stat.type === 'outbound-rtp' && (stat.kind === 'audio' || !stat.kind && stat.mediaType === 'audio')) {
21778
22050
  numPackets = stat.packetsSent;
21779
22051
  }
21780
22052
  });
@@ -21797,7 +22069,7 @@ class PublishVideoCheck extends Checker {
21797
22069
  const track = yield createLocalVideoTrack();
21798
22070
  room.localParticipant.publishTrack(track);
21799
22071
  // wait for a few seconds to publish
21800
- yield new Promise(resolve => setTimeout(resolve, 3000));
22072
+ yield new Promise(resolve => setTimeout(resolve, 5000));
21801
22073
  // verify RTC stats that it's publishing
21802
22074
  const stats = yield (_a = track.sender) === null || _a === void 0 ? void 0 : _a.getStats();
21803
22075
  if (!stats) {
@@ -21805,8 +22077,8 @@ class PublishVideoCheck extends Checker {
21805
22077
  }
21806
22078
  let numPackets = 0;
21807
22079
  stats.forEach(stat => {
21808
- if (stat.type === 'outbound-rtp' && stat.mediaType === 'video') {
21809
- numPackets = stat.packetsSent;
22080
+ if (stat.type === 'outbound-rtp' && (stat.kind === 'video' || !stat.kind && stat.mediaType === 'video')) {
22081
+ numPackets += stat.packetsSent;
21810
22082
  }
21811
22083
  });
21812
22084
  if (numPackets === 0) {