livekit-client 2.4.2 → 2.5.1

Sign up to get free protection for your applications and to get access to all the features.
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) {