livekit-client 1.14.0 → 1.14.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) 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 +25 -44
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +418 -206
  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/e2ee/E2eeManager.d.ts.map +1 -1
  10. package/dist/src/e2ee/utils.d.ts +0 -1
  11. package/dist/src/e2ee/utils.d.ts.map +1 -1
  12. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  13. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
  14. package/dist/src/proto/livekit_models_pb.d.ts +87 -11
  15. package/dist/src/proto/livekit_models_pb.d.ts.map +1 -1
  16. package/dist/src/proto/livekit_rtc_pb.d.ts +0 -4
  17. package/dist/src/proto/livekit_rtc_pb.d.ts.map +1 -1
  18. package/dist/src/room/PCTransport.d.ts +20 -1
  19. package/dist/src/room/PCTransport.d.ts.map +1 -1
  20. package/dist/src/room/RTCEngine.d.ts +1 -1
  21. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  22. package/dist/src/room/Room.d.ts.map +1 -1
  23. package/dist/src/room/defaults.d.ts +1 -0
  24. package/dist/src/room/defaults.d.ts.map +1 -1
  25. package/dist/src/room/events.d.ts +1 -1
  26. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  27. package/dist/src/room/timers.d.ts +1 -1
  28. package/dist/src/room/timers.d.ts.map +1 -1
  29. package/dist/src/room/track/LocalAudioTrack.d.ts +1 -1
  30. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  31. package/dist/src/room/track/LocalTrack.d.ts +3 -3
  32. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  33. package/dist/src/room/track/LocalVideoTrack.d.ts +2 -1
  34. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  35. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -1
  36. package/dist/src/room/track/options.d.ts +6 -1
  37. package/dist/src/room/track/options.d.ts.map +1 -1
  38. package/dist/src/room/track/utils.d.ts +2 -1
  39. package/dist/src/room/track/utils.d.ts.map +1 -1
  40. package/dist/src/room/utils.d.ts.map +1 -1
  41. package/dist/src/utils/cloneDeep.d.ts +2 -0
  42. package/dist/src/utils/cloneDeep.d.ts.map +1 -0
  43. package/dist/src/version.d.ts +1 -1
  44. package/dist/src/version.d.ts.map +1 -1
  45. package/dist/ts4.2/src/e2ee/utils.d.ts +0 -1
  46. package/dist/ts4.2/src/proto/livekit_models_pb.d.ts +87 -11
  47. package/dist/ts4.2/src/proto/livekit_rtc_pb.d.ts +0 -4
  48. package/dist/ts4.2/src/room/PCTransport.d.ts +20 -1
  49. package/dist/ts4.2/src/room/RTCEngine.d.ts +1 -1
  50. package/dist/ts4.2/src/room/defaults.d.ts +1 -0
  51. package/dist/ts4.2/src/room/events.d.ts +1 -1
  52. package/dist/ts4.2/src/room/timers.d.ts +1 -1
  53. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +1 -1
  54. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -3
  55. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +2 -1
  56. package/dist/ts4.2/src/room/track/options.d.ts +6 -1
  57. package/dist/ts4.2/src/room/track/utils.d.ts +1 -0
  58. package/dist/ts4.2/src/utils/cloneDeep.d.ts +2 -0
  59. package/dist/ts4.2/src/version.d.ts +1 -1
  60. package/package.json +14 -14
  61. package/src/connectionHelper/checks/webrtc.ts +1 -1
  62. package/src/e2ee/E2eeManager.ts +2 -1
  63. package/src/e2ee/utils.ts +0 -10
  64. package/src/e2ee/worker/FrameCryptor.ts +13 -14
  65. package/src/e2ee/worker/ParticipantKeyHandler.ts +4 -5
  66. package/src/e2ee/worker/e2ee.worker.ts +3 -1
  67. package/src/proto/livekit_models_pb.ts +140 -15
  68. package/src/proto/livekit_rtc_pb.ts +1 -7
  69. package/src/room/PCTransport.ts +116 -1
  70. package/src/room/RTCEngine.ts +49 -85
  71. package/src/room/Room.ts +15 -11
  72. package/src/room/defaults.ts +4 -2
  73. package/src/room/events.ts +1 -1
  74. package/src/room/participant/LocalParticipant.ts +45 -56
  75. package/src/room/track/LocalAudioTrack.ts +1 -1
  76. package/src/room/track/LocalTrack.ts +8 -5
  77. package/src/room/track/LocalVideoTrack.ts +2 -1
  78. package/src/room/track/RemoteTrack.ts +8 -6
  79. package/src/room/track/options.ts +7 -7
  80. package/src/room/track/utils.ts +17 -8
  81. package/src/room/utils.ts +3 -0
  82. package/src/utils/cloneDeep.test.ts +54 -0
  83. package/src/utils/cloneDeep.ts +11 -0
  84. package/src/version.ts +1 -1
@@ -3572,6 +3572,28 @@ proto3.util.setEnumType(VideoCodec, "livekit.VideoCodec", [{
3572
3572
  no: 4,
3573
3573
  name: "VP8"
3574
3574
  }]);
3575
+ /**
3576
+ * @generated from enum livekit.ImageCodec
3577
+ */
3578
+ var ImageCodec;
3579
+ (function (ImageCodec) {
3580
+ /**
3581
+ * @generated from enum value: IC_DEFAULT = 0;
3582
+ */
3583
+ ImageCodec[ImageCodec["IC_DEFAULT"] = 0] = "IC_DEFAULT";
3584
+ /**
3585
+ * @generated from enum value: IC_JPEG = 1;
3586
+ */
3587
+ ImageCodec[ImageCodec["IC_JPEG"] = 1] = "IC_JPEG";
3588
+ })(ImageCodec || (ImageCodec = {}));
3589
+ // Retrieve enum metadata with: proto3.getEnumType(ImageCodec)
3590
+ proto3.util.setEnumType(ImageCodec, "livekit.ImageCodec", [{
3591
+ no: 0,
3592
+ name: "IC_DEFAULT"
3593
+ }, {
3594
+ no: 1,
3595
+ name: "IC_JPEG"
3596
+ }]);
3575
3597
  /**
3576
3598
  * @generated from enum livekit.TrackType
3577
3599
  */
@@ -3997,11 +4019,6 @@ Room$1.fields = proto3.util.newFieldList(() => [{
3997
4019
  name: "active_recording",
3998
4020
  kind: "scalar",
3999
4021
  T: 8 /* ScalarType.BOOL */
4000
- }, {
4001
- no: 12,
4002
- name: "playout_delay",
4003
- kind: "message",
4004
- T: PlayoutDelay
4005
4022
  }]);
4006
4023
  /**
4007
4024
  * @generated from message livekit.Codec
@@ -4926,6 +4943,10 @@ class UserPacket extends Message {
4926
4943
  * @generated from field: string participant_sid = 1;
4927
4944
  */
4928
4945
  this.participantSid = "";
4946
+ /**
4947
+ * @generated from field: string participant_identity = 5;
4948
+ */
4949
+ this.participantIdentity = "";
4929
4950
  /**
4930
4951
  * user defined payload
4931
4952
  *
@@ -4933,11 +4954,17 @@ class UserPacket extends Message {
4933
4954
  */
4934
4955
  this.payload = new Uint8Array(0);
4935
4956
  /**
4936
- * the ID of the participants who will receive the message (the message will be sent to all the people in the room if this variable is empty)
4957
+ * the ID of the participants who will receive the message (sent to all by default)
4937
4958
  *
4938
4959
  * @generated from field: repeated string destination_sids = 3;
4939
4960
  */
4940
4961
  this.destinationSids = [];
4962
+ /**
4963
+ * identities of participants who will receive the message (sent to all by default)
4964
+ *
4965
+ * @generated from field: repeated string destination_identities = 6;
4966
+ */
4967
+ this.destinationIdentities = [];
4941
4968
  proto3.util.initPartial(data, this);
4942
4969
  }
4943
4970
  static fromBinary(bytes, options) {
@@ -4960,6 +4987,11 @@ UserPacket.fields = proto3.util.newFieldList(() => [{
4960
4987
  name: "participant_sid",
4961
4988
  kind: "scalar",
4962
4989
  T: 9 /* ScalarType.STRING */
4990
+ }, {
4991
+ no: 5,
4992
+ name: "participant_identity",
4993
+ kind: "scalar",
4994
+ T: 9 /* ScalarType.STRING */
4963
4995
  }, {
4964
4996
  no: 2,
4965
4997
  name: "payload",
@@ -4971,6 +5003,12 @@ UserPacket.fields = proto3.util.newFieldList(() => [{
4971
5003
  kind: "scalar",
4972
5004
  T: 9 /* ScalarType.STRING */,
4973
5005
  repeated: true
5006
+ }, {
5007
+ no: 6,
5008
+ name: "destination_identities",
5009
+ kind: "scalar",
5010
+ T: 9 /* ScalarType.STRING */,
5011
+ repeated: true
4974
5012
  }, {
4975
5013
  no: 4,
4976
5014
  name: "topic",
@@ -5286,6 +5324,14 @@ var ClientInfo_SDK;
5286
5324
  * @generated from enum value: RUST = 8;
5287
5325
  */
5288
5326
  ClientInfo_SDK[ClientInfo_SDK["RUST"] = 8] = "RUST";
5327
+ /**
5328
+ * @generated from enum value: PYTHON = 9;
5329
+ */
5330
+ ClientInfo_SDK[ClientInfo_SDK["PYTHON"] = 9] = "PYTHON";
5331
+ /**
5332
+ * @generated from enum value: CPP = 10;
5333
+ */
5334
+ ClientInfo_SDK[ClientInfo_SDK["CPP"] = 10] = "CPP";
5289
5335
  })(ClientInfo_SDK || (ClientInfo_SDK = {}));
5290
5336
  // Retrieve enum metadata with: proto3.getEnumType(ClientInfo_SDK)
5291
5337
  proto3.util.setEnumType(ClientInfo_SDK, "livekit.ClientInfo.SDK", [{
@@ -5315,6 +5361,12 @@ proto3.util.setEnumType(ClientInfo_SDK, "livekit.ClientInfo.SDK", [{
5315
5361
  }, {
5316
5362
  no: 8,
5317
5363
  name: "RUST"
5364
+ }, {
5365
+ no: 9,
5366
+ name: "PYTHON"
5367
+ }, {
5368
+ no: 10,
5369
+ name: "CPP"
5318
5370
  }]);
5319
5371
  /**
5320
5372
  * server provided client configuration
@@ -5456,6 +5508,103 @@ DisabledCodecs.fields = proto3.util.newFieldList(() => [{
5456
5508
  T: Codec,
5457
5509
  repeated: true
5458
5510
  }]);
5511
+ /**
5512
+ * @generated from message livekit.RTPDrift
5513
+ */
5514
+ class RTPDrift extends Message {
5515
+ constructor(data) {
5516
+ super();
5517
+ /**
5518
+ * @generated from field: double duration = 3;
5519
+ */
5520
+ this.duration = 0;
5521
+ /**
5522
+ * @generated from field: uint64 start_timestamp = 4;
5523
+ */
5524
+ this.startTimestamp = protoInt64.zero;
5525
+ /**
5526
+ * @generated from field: uint64 end_timestamp = 5;
5527
+ */
5528
+ this.endTimestamp = protoInt64.zero;
5529
+ /**
5530
+ * @generated from field: uint64 rtp_clock_ticks = 6;
5531
+ */
5532
+ this.rtpClockTicks = protoInt64.zero;
5533
+ /**
5534
+ * @generated from field: int64 drift_samples = 7;
5535
+ */
5536
+ this.driftSamples = protoInt64.zero;
5537
+ /**
5538
+ * @generated from field: double drift_ms = 8;
5539
+ */
5540
+ this.driftMs = 0;
5541
+ /**
5542
+ * @generated from field: double clock_rate = 9;
5543
+ */
5544
+ this.clockRate = 0;
5545
+ proto3.util.initPartial(data, this);
5546
+ }
5547
+ static fromBinary(bytes, options) {
5548
+ return new RTPDrift().fromBinary(bytes, options);
5549
+ }
5550
+ static fromJson(jsonValue, options) {
5551
+ return new RTPDrift().fromJson(jsonValue, options);
5552
+ }
5553
+ static fromJsonString(jsonString, options) {
5554
+ return new RTPDrift().fromJsonString(jsonString, options);
5555
+ }
5556
+ static equals(a, b) {
5557
+ return proto3.util.equals(RTPDrift, a, b);
5558
+ }
5559
+ }
5560
+ RTPDrift.runtime = proto3;
5561
+ RTPDrift.typeName = "livekit.RTPDrift";
5562
+ RTPDrift.fields = proto3.util.newFieldList(() => [{
5563
+ no: 1,
5564
+ name: "start_time",
5565
+ kind: "message",
5566
+ T: Timestamp
5567
+ }, {
5568
+ no: 2,
5569
+ name: "end_time",
5570
+ kind: "message",
5571
+ T: Timestamp
5572
+ }, {
5573
+ no: 3,
5574
+ name: "duration",
5575
+ kind: "scalar",
5576
+ T: 1 /* ScalarType.DOUBLE */
5577
+ }, {
5578
+ no: 4,
5579
+ name: "start_timestamp",
5580
+ kind: "scalar",
5581
+ T: 4 /* ScalarType.UINT64 */
5582
+ }, {
5583
+ no: 5,
5584
+ name: "end_timestamp",
5585
+ kind: "scalar",
5586
+ T: 4 /* ScalarType.UINT64 */
5587
+ }, {
5588
+ no: 6,
5589
+ name: "rtp_clock_ticks",
5590
+ kind: "scalar",
5591
+ T: 4 /* ScalarType.UINT64 */
5592
+ }, {
5593
+ no: 7,
5594
+ name: "drift_samples",
5595
+ kind: "scalar",
5596
+ T: 3 /* ScalarType.INT64 */
5597
+ }, {
5598
+ no: 8,
5599
+ name: "drift_ms",
5600
+ kind: "scalar",
5601
+ T: 1 /* ScalarType.DOUBLE */
5602
+ }, {
5603
+ no: 9,
5604
+ name: "clock_rate",
5605
+ kind: "scalar",
5606
+ T: 1 /* ScalarType.DOUBLE */
5607
+ }]);
5459
5608
  /**
5460
5609
  * @generated from message livekit.RTPStats
5461
5610
  */
@@ -5602,16 +5751,6 @@ class RTPStats extends Message {
5602
5751
  * @generated from field: uint32 layer_lock_plis = 35;
5603
5752
  */
5604
5753
  this.layerLockPlis = 0;
5605
- /**
5606
- * @generated from field: double sample_rate = 42;
5607
- */
5608
- this.sampleRate = 0;
5609
- /**
5610
- * NEXT_ID: 44
5611
- *
5612
- * @generated from field: double drift_ms = 43;
5613
- */
5614
- this.driftMs = 0;
5615
5754
  proto3.util.initPartial(data, this);
5616
5755
  }
5617
5756
  static fromBinary(bytes, options) {
@@ -5839,15 +5978,15 @@ RTPStats.fields = proto3.util.newFieldList(() => [{
5839
5978
  kind: "message",
5840
5979
  T: Timestamp
5841
5980
  }, {
5842
- no: 42,
5843
- name: "sample_rate",
5844
- kind: "scalar",
5845
- T: 1 /* ScalarType.DOUBLE */
5981
+ no: 44,
5982
+ name: "packet_drift",
5983
+ kind: "message",
5984
+ T: RTPDrift
5846
5985
  }, {
5847
- no: 43,
5848
- name: "drift_ms",
5849
- kind: "scalar",
5850
- T: 1 /* ScalarType.DOUBLE */
5986
+ no: 45,
5987
+ name: "report_drift",
5988
+ kind: "message",
5989
+ T: RTPDrift
5851
5990
  }]);
5852
5991
  /**
5853
5992
  * @generated from message livekit.TimedVersion
@@ -5920,7 +6059,7 @@ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
5920
6059
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
5921
6060
  PERFORMANCE OF THIS SOFTWARE.
5922
6061
  ***************************************************************************** */
5923
- /* global Reflect, Promise */
6062
+ /* global Reflect, Promise, SuppressedError, Symbol */
5924
6063
 
5925
6064
 
5926
6065
  function __awaiter(thisArg, _arguments, P, generator) {
@@ -5951,7 +6090,12 @@ function __asyncValues(o) {
5951
6090
  return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
5952
6091
  function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
5953
6092
  function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
5954
- }
6093
+ }
6094
+
6095
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
6096
+ var e = new Error(message);
6097
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
6098
+ };
5955
6099
 
5956
6100
  var events = {exports: {}};
5957
6101
 
@@ -9825,10 +9969,6 @@ class SimulcastCodec extends Message {
9825
9969
  * @generated from field: string cid = 2;
9826
9970
  */
9827
9971
  this.cid = "";
9828
- /**
9829
- * @generated from field: bool enable_simulcast_layers = 3;
9830
- */
9831
- this.enableSimulcastLayers = false;
9832
9972
  proto3.util.initPartial(data, this);
9833
9973
  }
9834
9974
  static fromBinary(bytes, options) {
@@ -9856,11 +9996,6 @@ SimulcastCodec.fields = proto3.util.newFieldList(() => [{
9856
9996
  name: "cid",
9857
9997
  kind: "scalar",
9858
9998
  T: 9 /* ScalarType.STRING */
9859
- }, {
9860
- no: 3,
9861
- name: "enable_simulcast_layers",
9862
- kind: "scalar",
9863
- T: 8 /* ScalarType.BOOL */
9864
9999
  }]);
9865
10000
  /**
9866
10001
  * @generated from message livekit.AddTrackRequest
@@ -11863,10 +11998,10 @@ function getMatch(exp, ua) {
11863
11998
  return match && match.length >= id && match[id] || '';
11864
11999
  }
11865
12000
 
11866
- var version$1 = "1.14.0";
12001
+ var version$1 = "1.14.2";
11867
12002
 
11868
12003
  const version = version$1;
11869
- const protocolVersion = 9;
12004
+ const protocolVersion = 10;
11870
12005
 
11871
12006
  class VideoPreset {
11872
12007
  constructor(width, height, maxBitrate, maxFramerate, priority) {
@@ -11892,9 +12027,6 @@ const videoCodecs = ['vp8', 'h264', 'vp9', 'av1'];
11892
12027
  function isBackupCodec(codec) {
11893
12028
  return !!backupCodecs.find(backup => backup === codec);
11894
12029
  }
11895
- function isCodecEqual(c1, c2) {
11896
- return (c1 === null || c1 === void 0 ? void 0 : c1.toLowerCase().replace(/audio\/|video\//y, '')) === (c2 === null || c2 === void 0 ? void 0 : c2.toLowerCase().replace(/audio\/|video\//y, ''));
11897
- }
11898
12030
  var AudioPresets;
11899
12031
  (function (AudioPresets) {
11900
12032
  AudioPresets.telephone = {
@@ -11953,6 +12085,17 @@ const ScreenSharePresets = {
11953
12085
  h1080fps30: new VideoPreset(1920, 1080, 4000000, 30, 'medium')
11954
12086
  };
11955
12087
 
12088
+ function cloneDeep(value) {
12089
+ if (typeof value === 'undefined') {
12090
+ return;
12091
+ }
12092
+ if (typeof structuredClone === 'function') {
12093
+ return structuredClone(value);
12094
+ } else {
12095
+ return JSON.parse(JSON.stringify(value));
12096
+ }
12097
+ }
12098
+
11956
12099
  /**
11957
12100
  * Events are the primary way LiveKit notifies your application of changes.
11958
12101
  *
@@ -12152,7 +12295,7 @@ var RoomEvent;
12152
12295
  * be emitted.
12153
12296
  *
12154
12297
  * args: (pub: [[RemoteTrackPublication]],
12155
- * status: [[TrackPublication.SubscriptionStatus]],
12298
+ * status: [[TrackPublication.PermissionStatus]],
12156
12299
  * participant: [[RemoteParticipant]])
12157
12300
  */
12158
12301
  RoomEvent["TrackSubscriptionPermissionChanged"] = "trackSubscriptionPermissionChanged";
@@ -12772,7 +12915,8 @@ function detachTrack(track, element) {
12772
12915
  })(Track || (Track = {}));
12773
12916
 
12774
12917
  function mergeDefaultOptions(options, audioDefaults, videoDefaults) {
12775
- const opts = Object.assign({}, options);
12918
+ var _a;
12919
+ const opts = (_a = cloneDeep(options)) !== null && _a !== void 0 ? _a : {};
12776
12920
  if (opts.audio === true) opts.audio = {};
12777
12921
  if (opts.video === true) opts.video = {};
12778
12922
  // use defaults
@@ -12915,6 +13059,13 @@ function screenCaptureToDisplayMediaStreamOptions(options) {
12915
13059
  systemAudio: options.systemAudio
12916
13060
  };
12917
13061
  }
13062
+ function mimeTypeToVideoCodecString(mimeType) {
13063
+ const codec = mimeType.split('/')[1].toLowerCase();
13064
+ if (!videoCodecs.includes(codec)) {
13065
+ throw Error("Video codec not supported: ".concat(codec));
13066
+ }
13067
+ return codec;
13068
+ }
12918
13069
 
12919
13070
  const separator = '|';
12920
13071
  const ddExtensionURI = 'https://aomediacodec.github.io/av1-rtp-spec/#dependency-descriptor-rtp-header-extension';
@@ -12962,6 +13113,9 @@ function supportsAV1() {
12962
13113
  }
12963
13114
  function supportsVP9() {
12964
13115
  if (!('getCapabilities' in RTCRtpSender)) {
13116
+ return false;
13117
+ }
13118
+ if (isFireFox()) {
12965
13119
  // technically speaking FireFox supports VP9, but SVC publishing is broken
12966
13120
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1633876
12967
13121
  return false;
@@ -14044,13 +14198,6 @@ function deriveKeys(material, salt) {
14044
14198
  function createE2EEKey() {
14045
14199
  return window.crypto.getRandomValues(new Uint8Array(32));
14046
14200
  }
14047
- function mimeTypeToVideoCodecString(mimeType) {
14048
- const codec = mimeType.split('/')[1].toLowerCase();
14049
- if (!videoCodecs.includes(codec)) {
14050
- throw Error("Video codec not supported: ".concat(codec));
14051
- }
14052
- return codec;
14053
- }
14054
14201
  /**
14055
14202
  * Ratchets a key. See
14056
14203
  * https://tools.ietf.org/html/draft-omara-sframe-00#section-4.3.5.1
@@ -14438,10 +14585,16 @@ class LocalTrack extends Track {
14438
14585
  }
14439
14586
  waitForDimensions() {
14440
14587
  let timeout = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultDimensionsTimeout;
14588
+ var _a;
14441
14589
  return __awaiter(this, void 0, void 0, function* () {
14442
14590
  if (this.kind === Track.Kind.Audio) {
14443
14591
  throw new Error('cannot get dimensions for audio tracks');
14444
14592
  }
14593
+ if (((_a = getBrowser()) === null || _a === void 0 ? void 0 : _a.os) === 'iOS') {
14594
+ // browsers report wrong initial resolution on iOS.
14595
+ // when slightly delaying the call to .getSettings(), the correct resolution is being reported
14596
+ yield sleep(10);
14597
+ }
14445
14598
  const started = Date.now();
14446
14599
  while (Date.now() - started < timeout) {
14447
14600
  const dims = this.dimensions;
@@ -15770,6 +15923,27 @@ class PCTransport extends eventsExports.EventEmitter {
15770
15923
  this._pc = isChromiumBased() ?
15771
15924
  // @ts-expect-error chrome allows additional media constraints to be passed into the RTCPeerConnection constructor
15772
15925
  new RTCPeerConnection(config, mediaConstraints) : new RTCPeerConnection(config);
15926
+ this._pc.onicecandidate = ev => {
15927
+ var _a;
15928
+ if (!ev.candidate) return;
15929
+ (_a = this.onIceCandidate) === null || _a === void 0 ? void 0 : _a.call(this, ev.candidate);
15930
+ };
15931
+ this._pc.onicecandidateerror = ev => {
15932
+ var _a;
15933
+ (_a = this.onIceCandidateError) === null || _a === void 0 ? void 0 : _a.call(this, ev);
15934
+ };
15935
+ this._pc.onconnectionstatechange = () => {
15936
+ var _a, _b, _c;
15937
+ (_a = this.onConnectionStateChange) === null || _a === void 0 ? void 0 : _a.call(this, (_c = (_b = this._pc) === null || _b === void 0 ? void 0 : _b.connectionState) !== null && _c !== void 0 ? _c : 'closed');
15938
+ };
15939
+ this._pc.ondatachannel = ev => {
15940
+ var _a;
15941
+ (_a = this.onDataChannel) === null || _a === void 0 ? void 0 : _a.call(this, ev);
15942
+ };
15943
+ this._pc.ontrack = ev => {
15944
+ var _a;
15945
+ (_a = this.onTrack) === null || _a === void 0 ? void 0 : _a.call(this, ev);
15946
+ };
15773
15947
  }
15774
15948
  get isICEConnected() {
15775
15949
  return this._pc !== null && (this.pc.iceConnectionState === 'connected' || this.pc.iceConnectionState === 'completed');
@@ -15952,9 +16126,85 @@ class PCTransport extends eventsExports.EventEmitter {
15952
16126
  return answer;
15953
16127
  });
15954
16128
  }
16129
+ createDataChannel(label, dataChannelDict) {
16130
+ return this.pc.createDataChannel(label, dataChannelDict);
16131
+ }
16132
+ addTransceiver(mediaStreamTrack, transceiverInit) {
16133
+ return this.pc.addTransceiver(mediaStreamTrack, transceiverInit);
16134
+ }
16135
+ addTrack(track) {
16136
+ return this.pc.addTrack(track);
16137
+ }
15955
16138
  setTrackCodecBitrate(info) {
15956
16139
  this.trackBitrates.push(info);
15957
16140
  }
16141
+ setConfiguration(rtcConfig) {
16142
+ return this.pc.setConfiguration(rtcConfig);
16143
+ }
16144
+ canRemoveTrack() {
16145
+ return !!this.pc.removeTrack;
16146
+ }
16147
+ removeTrack(sender) {
16148
+ return this.pc.removeTrack(sender);
16149
+ }
16150
+ getConnectionState() {
16151
+ return this.pc.connectionState;
16152
+ }
16153
+ getICEConnectionState() {
16154
+ return this.pc.iceConnectionState;
16155
+ }
16156
+ getSignallingState() {
16157
+ return this.pc.signalingState;
16158
+ }
16159
+ getTransceivers() {
16160
+ return this.pc.getTransceivers();
16161
+ }
16162
+ getSenders() {
16163
+ return this.pc.getSenders();
16164
+ }
16165
+ getLocalDescription() {
16166
+ return this.pc.localDescription;
16167
+ }
16168
+ getRemoteDescription() {
16169
+ return this.pc.remoteDescription;
16170
+ }
16171
+ getConnectedAddress() {
16172
+ var _a;
16173
+ return __awaiter(this, void 0, void 0, function* () {
16174
+ if (!this._pc) {
16175
+ return;
16176
+ }
16177
+ let selectedCandidatePairId = '';
16178
+ const candidatePairs = new Map();
16179
+ // id -> candidate ip
16180
+ const candidates = new Map();
16181
+ const stats = yield this._pc.getStats();
16182
+ stats.forEach(v => {
16183
+ switch (v.type) {
16184
+ case 'transport':
16185
+ selectedCandidatePairId = v.selectedCandidatePairId;
16186
+ break;
16187
+ case 'candidate-pair':
16188
+ if (selectedCandidatePairId === '' && v.selected) {
16189
+ selectedCandidatePairId = v.id;
16190
+ }
16191
+ candidatePairs.set(v.id, v);
16192
+ break;
16193
+ case 'remote-candidate':
16194
+ candidates.set(v.id, "".concat(v.address, ":").concat(v.port));
16195
+ break;
16196
+ }
16197
+ });
16198
+ if (selectedCandidatePairId === '') {
16199
+ return undefined;
16200
+ }
16201
+ const selectedID = (_a = candidatePairs.get(selectedCandidatePairId)) === null || _a === void 0 ? void 0 : _a.remoteCandidateId;
16202
+ if (selectedID === undefined) {
16203
+ return undefined;
16204
+ }
16205
+ return candidates.get(selectedID);
16206
+ });
16207
+ }
15958
16208
  close() {
15959
16209
  if (!this._pc) {
15960
16210
  return;
@@ -16115,6 +16365,7 @@ function extractStereoAndNackAudioFromOffer(offer) {
16115
16365
  };
16116
16366
  }
16117
16367
 
16368
+ const defaultVideoCodec = 'vp8';
16118
16369
  const publishDefaults = {
16119
16370
  /**
16120
16371
  * @deprecated
@@ -16127,7 +16378,7 @@ const publishDefaults = {
16127
16378
  simulcast: true,
16128
16379
  screenShareEncoding: ScreenSharePresets.h1080fps15.encoding,
16129
16380
  stopMicTrackOnMute: false,
16130
- videoCodec: 'vp8',
16381
+ videoCodec: defaultVideoCodec,
16131
16382
  backupCodec: false
16132
16383
  };
16133
16384
  const audioDefaults = {
@@ -16400,13 +16651,13 @@ class RTCEngine extends eventsExports.EventEmitter {
16400
16651
  }
16401
16652
  cleanupPeerConnections() {
16402
16653
  return __awaiter(this, void 0, void 0, function* () {
16403
- if (this.publisher && this.publisher.pc.signalingState !== 'closed') {
16404
- this.publisher.pc.getSenders().forEach(sender => {
16654
+ if (this.publisher && this.publisher.getSignallingState() !== 'closed') {
16655
+ this.publisher.getSenders().forEach(sender => {
16405
16656
  var _a, _b;
16406
16657
  try {
16407
16658
  // TODO: react-native-webrtc doesn't have removeTrack yet.
16408
- if ((_a = this.publisher) === null || _a === void 0 ? void 0 : _a.pc.removeTrack) {
16409
- (_b = this.publisher) === null || _b === void 0 ? void 0 : _b.pc.removeTrack(sender);
16659
+ if ((_a = this.publisher) === null || _a === void 0 ? void 0 : _a.canRemoveTrack()) {
16660
+ (_b = this.publisher) === null || _b === void 0 ? void 0 : _b.removeTrack(sender);
16410
16661
  }
16411
16662
  } catch (e) {
16412
16663
  livekitLogger.warn('could not removeTrack', {
@@ -16424,7 +16675,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16424
16675
  this.subscriber = undefined;
16425
16676
  }
16426
16677
  this.hasPublished = false;
16427
- this.primaryPC = undefined;
16678
+ this.primaryTransport = undefined;
16428
16679
  const dcCleanup = dc => {
16429
16680
  if (!dc) return;
16430
16681
  dc.close();
@@ -16491,7 +16742,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16491
16742
  delete this.pendingTrackResolvers[sender.track.id];
16492
16743
  }
16493
16744
  try {
16494
- (_a = this.publisher) === null || _a === void 0 ? void 0 : _a.pc.removeTrack(sender);
16745
+ (_a = this.publisher) === null || _a === void 0 ? void 0 : _a.removeTrack(sender);
16495
16746
  return true;
16496
16747
  } catch (e) {
16497
16748
  livekitLogger.warn('failed to remove track', {
@@ -16510,10 +16761,10 @@ class RTCEngine extends eventsExports.EventEmitter {
16510
16761
  }
16511
16762
  getConnectedServerAddress() {
16512
16763
  return __awaiter(this, void 0, void 0, function* () {
16513
- if (this.primaryPC === undefined) {
16764
+ if (this.primaryTransport === undefined) {
16514
16765
  return undefined;
16515
16766
  }
16516
- return getConnectedAddress(this.primaryPC);
16767
+ return this.primaryTransport.getConnectedAddress();
16517
16768
  });
16518
16769
  }
16519
16770
  /* @internal */
@@ -16542,37 +16793,35 @@ class RTCEngine extends eventsExports.EventEmitter {
16542
16793
  this.publisher = new PCTransport(rtcConfig, googConstraints);
16543
16794
  this.subscriber = new PCTransport(rtcConfig);
16544
16795
  this.emit(EngineEvent.TransportsCreated, this.publisher, this.subscriber);
16545
- this.publisher.pc.onicecandidate = ev => {
16546
- if (!ev.candidate) return;
16547
- livekitLogger.trace('adding ICE candidate for peer', ev.candidate);
16548
- this.client.sendIceCandidate(ev.candidate, SignalTarget.PUBLISHER);
16796
+ this.publisher.onIceCandidate = candidate => {
16797
+ livekitLogger.trace('adding ICE candidate for peer', candidate);
16798
+ this.client.sendIceCandidate(candidate, SignalTarget.PUBLISHER);
16549
16799
  };
16550
- this.subscriber.pc.onicecandidate = ev => {
16551
- if (!ev.candidate) return;
16552
- this.client.sendIceCandidate(ev.candidate, SignalTarget.SUBSCRIBER);
16800
+ this.subscriber.onIceCandidate = candidate => {
16801
+ this.client.sendIceCandidate(candidate, SignalTarget.SUBSCRIBER);
16553
16802
  };
16554
16803
  this.publisher.onOffer = offer => {
16555
16804
  this.client.sendOffer(offer);
16556
16805
  };
16557
- let primaryPC = this.publisher.pc;
16558
- let secondaryPC = this.subscriber.pc;
16806
+ let primaryTransport = this.publisher;
16807
+ let secondaryTransport = this.subscriber;
16559
16808
  let subscriberPrimary = joinResponse.subscriberPrimary;
16560
16809
  if (subscriberPrimary) {
16561
- primaryPC = this.subscriber.pc;
16562
- secondaryPC = this.publisher.pc;
16810
+ primaryTransport = this.subscriber;
16811
+ secondaryTransport = this.publisher;
16563
16812
  // in subscriber primary mode, server side opens sub data channels.
16564
- this.subscriber.pc.ondatachannel = this.handleDataChannel;
16813
+ this.subscriber.onDataChannel = this.handleDataChannel;
16565
16814
  }
16566
- this.primaryPC = primaryPC;
16567
- primaryPC.onconnectionstatechange = () => __awaiter(this, void 0, void 0, function* () {
16568
- livekitLogger.debug("primary PC state changed ".concat(primaryPC.connectionState));
16569
- if (primaryPC.connectionState === 'connected') {
16815
+ this.primaryTransport = primaryTransport;
16816
+ primaryTransport.onConnectionStateChange = connectionState => __awaiter(this, void 0, void 0, function* () {
16817
+ livekitLogger.debug("primary PC state changed ".concat(connectionState));
16818
+ if (connectionState === 'connected') {
16570
16819
  const shouldEmit = this.pcState === PCState.New;
16571
16820
  this.pcState = PCState.Connected;
16572
16821
  if (shouldEmit) {
16573
16822
  this.emit(EngineEvent.Connected, joinResponse);
16574
16823
  }
16575
- } else if (primaryPC.connectionState === 'failed') {
16824
+ } else if (connectionState === 'failed') {
16576
16825
  // on Safari, PeerConnection will switch to 'disconnected' during renegotiation
16577
16826
  if (this.pcState === PCState.Connected) {
16578
16827
  this.pcState = PCState.Disconnected;
@@ -16580,14 +16829,14 @@ class RTCEngine extends eventsExports.EventEmitter {
16580
16829
  }
16581
16830
  }
16582
16831
  });
16583
- secondaryPC.onconnectionstatechange = () => __awaiter(this, void 0, void 0, function* () {
16584
- livekitLogger.debug("secondary PC state changed ".concat(secondaryPC.connectionState));
16832
+ secondaryTransport.onConnectionStateChange = connectionState => __awaiter(this, void 0, void 0, function* () {
16833
+ livekitLogger.debug("secondary PC state changed ".concat(connectionState));
16585
16834
  // also reconnect if secondary peerconnection fails
16586
- if (secondaryPC.connectionState === 'failed') {
16835
+ if (connectionState === 'failed') {
16587
16836
  this.handleDisconnect('secondary peerconnection', subscriberPrimary ? ReconnectReason.RR_PUBLISHER_FAILED : ReconnectReason.RR_SUBSCRIBER_FAILED);
16588
16837
  }
16589
16838
  });
16590
- this.subscriber.pc.ontrack = ev => {
16839
+ this.subscriber.onTrack = ev => {
16591
16840
  this.emit(EngineEvent.MediaTrackAdded, ev.track, ev.streams[0], ev.receiver);
16592
16841
  };
16593
16842
  this.createDataChannels();
@@ -16600,7 +16849,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16600
16849
  }
16601
16850
  livekitLogger.debug('received server answer', {
16602
16851
  RTCSdpType: sd.type,
16603
- signalingState: this.publisher.pc.signalingState.toString()
16852
+ signalingState: this.publisher.getSignallingState().toString()
16604
16853
  });
16605
16854
  yield this.publisher.setRemoteDescription(sd);
16606
16855
  });
@@ -16626,7 +16875,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16626
16875
  }
16627
16876
  livekitLogger.debug('received server offer', {
16628
16877
  RTCSdpType: sd.type,
16629
- signalingState: this.subscriber.pc.signalingState.toString()
16878
+ signalingState: this.subscriber.getSignallingState().toString()
16630
16879
  });
16631
16880
  yield this.subscriber.setRemoteDescription(sd);
16632
16881
  // answer the offer
@@ -16654,7 +16903,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16654
16903
  this.client.onLeave = leave => {
16655
16904
  if (leave === null || leave === void 0 ? void 0 : leave.canReconnect) {
16656
16905
  this.fullReconnectOnNext = true;
16657
- this.primaryPC = undefined;
16906
+ this.primaryTransport = undefined;
16658
16907
  // reconnect immediately instead of waiting for next attempt
16659
16908
  this.handleDisconnect(leaveReconnect);
16660
16909
  } else {
@@ -16706,12 +16955,12 @@ class RTCEngine extends eventsExports.EventEmitter {
16706
16955
  this.reliableDC.onerror = null;
16707
16956
  }
16708
16957
  // create data channels
16709
- this.lossyDC = this.publisher.pc.createDataChannel(lossyDataChannel, {
16958
+ this.lossyDC = this.publisher.createDataChannel(lossyDataChannel, {
16710
16959
  // will drop older packets that arrive
16711
16960
  ordered: true,
16712
16961
  maxRetransmits: 0
16713
16962
  });
16714
- this.reliableDC = this.publisher.pc.createDataChannel(reliableDataChannel, {
16963
+ this.reliableDC = this.publisher.createDataChannel(reliableDataChannel, {
16715
16964
  ordered: true
16716
16965
  });
16717
16966
  // also handle messages over the pub channel, for backwards compatibility
@@ -16808,7 +17057,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16808
17057
  transceiverInit.sendEncodings = encodings;
16809
17058
  }
16810
17059
  // addTransceiver for react-native is async. web is synchronous, but await won't effect it.
16811
- const transceiver = yield this.publisher.pc.addTransceiver(track.mediaStreamTrack, transceiverInit);
17060
+ const transceiver = yield this.publisher.addTransceiver(track.mediaStreamTrack, transceiverInit);
16812
17061
  if (track.kind === Track.Kind.Video && opts.videoCodec) {
16813
17062
  this.setPreferredCodec(transceiver, track.kind, opts.videoCodec);
16814
17063
  track.codec = opts.videoCodec;
@@ -16828,7 +17077,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16828
17077
  transceiverInit.sendEncodings = encodings;
16829
17078
  }
16830
17079
  // addTransceiver for react-native is async. web is synchronous, but await won't effect it.
16831
- const transceiver = yield this.publisher.pc.addTransceiver(simulcastTrack.mediaStreamTrack, transceiverInit);
17080
+ const transceiver = yield this.publisher.addTransceiver(simulcastTrack.mediaStreamTrack, transceiverInit);
16832
17081
  if (!opts.videoCodec) {
16833
17082
  return;
16834
17083
  }
@@ -16842,7 +17091,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16842
17091
  if (!this.publisher) {
16843
17092
  throw new UnexpectedConnectionState('publisher is closed');
16844
17093
  }
16845
- return this.publisher.pc.addTrack(track);
17094
+ return this.publisher.addTrack(track);
16846
17095
  });
16847
17096
  }
16848
17097
  attemptReconnect(reason) {
@@ -16858,7 +17107,7 @@ class RTCEngine extends eventsExports.EventEmitter {
16858
17107
  if (((_a = this.clientConfiguration) === null || _a === void 0 ? void 0 : _a.resumeConnection) === ClientConfigSetting.DISABLED ||
16859
17108
  // signaling state could change to closed due to hardware sleep
16860
17109
  // those connections cannot be resumed
16861
- ((_c = (_b = this.primaryPC) === null || _b === void 0 ? void 0 : _b.signalingState) !== null && _c !== void 0 ? _c : 'closed') === 'closed') {
17110
+ ((_c = (_b = this.primaryTransport) === null || _b === void 0 ? void 0 : _b.getSignallingState()) !== null && _c !== void 0 ? _c : 'closed') === 'closed') {
16862
17111
  this.fullReconnectOnNext = true;
16863
17112
  }
16864
17113
  try {
@@ -16976,8 +17225,8 @@ class RTCEngine extends eventsExports.EventEmitter {
16976
17225
  const res = yield this.client.reconnect(this.url, this.token, this.participantSid, reason);
16977
17226
  if (res) {
16978
17227
  const rtcConfig = this.makeRTCConfiguration(res);
16979
- this.publisher.pc.setConfiguration(rtcConfig);
16980
- this.subscriber.pc.setConfiguration(rtcConfig);
17228
+ this.publisher.setConfiguration(rtcConfig);
17229
+ this.subscriber.setConfiguration(rtcConfig);
16981
17230
  }
16982
17231
  } catch (e) {
16983
17232
  let message = '';
@@ -17052,14 +17301,14 @@ class RTCEngine extends eventsExports.EventEmitter {
17052
17301
  this.pcState = PCState.Reconnecting;
17053
17302
  livekitLogger.debug('waiting for peer connection to reconnect');
17054
17303
  while (now - startTime < this.peerConnectionTimeout) {
17055
- if (this.primaryPC === undefined) {
17304
+ if (this.primaryTransport === undefined) {
17056
17305
  // we can abort early, connection is hosed
17057
17306
  break;
17058
17307
  } else if (
17059
17308
  // on Safari, we don't get a connectionstatechanged event during ICE restart
17060
17309
  // this means we'd have to check its status manually and update address
17061
17310
  // manually
17062
- now - startTime > minReconnectWait && ((_a = this.primaryPC) === null || _a === void 0 ? void 0 : _a.connectionState) === 'connected' && (!this.hasPublished || ((_b = this.publisher) === null || _b === void 0 ? void 0 : _b.pc.connectionState) === 'connected')) {
17311
+ now - startTime > minReconnectWait && ((_a = this.primaryTransport) === null || _a === void 0 ? void 0 : _a.getConnectionState()) === 'connected' && (!this.hasPublished || ((_b = this.publisher) === null || _b === void 0 ? void 0 : _b.getConnectionState()) === 'connected')) {
17063
17312
  this.pcState = PCState.Connected;
17064
17313
  }
17065
17314
  if (this.pcState === PCState.Connected) {
@@ -17097,7 +17346,7 @@ class RTCEngine extends eventsExports.EventEmitter {
17097
17346
  if (!transport) {
17098
17347
  throw new ConnectionError("".concat(transportName, " connection not set"));
17099
17348
  }
17100
- if (!subscriber && !((_a = this.publisher) === null || _a === void 0 ? void 0 : _a.isICEConnected) && ((_b = this.publisher) === null || _b === void 0 ? void 0 : _b.pc.iceConnectionState) !== 'checking') {
17349
+ if (!subscriber && !((_a = this.publisher) === null || _a === void 0 ? void 0 : _a.isICEConnected) && ((_b = this.publisher) === null || _b === void 0 ? void 0 : _b.getICEConnectionState()) !== 'checking') {
17101
17350
  // start negotiation
17102
17351
  this.negotiate();
17103
17352
  }
@@ -17113,7 +17362,7 @@ class RTCEngine extends eventsExports.EventEmitter {
17113
17362
  }
17114
17363
  yield sleep(50);
17115
17364
  }
17116
- throw new ConnectionError("could not establish ".concat(transportName, " connection, state: ").concat(transport.pc.iceConnectionState));
17365
+ throw new ConnectionError("could not establish ".concat(transportName, " connection, state: ").concat(transport.getICEConnectionState()));
17117
17366
  });
17118
17367
  }
17119
17368
  ensurePublisherConnected(kind) {
@@ -17124,10 +17373,10 @@ class RTCEngine extends eventsExports.EventEmitter {
17124
17373
  /* @internal */
17125
17374
  verifyTransport() {
17126
17375
  // primary connection
17127
- if (!this.primaryPC) {
17376
+ if (!this.primaryTransport) {
17128
17377
  return false;
17129
17378
  }
17130
- if (this.primaryPC.connectionState === 'closed' || this.primaryPC.connectionState === 'failed') {
17379
+ if (this.primaryTransport.getConnectionState() === 'closed' || this.primaryTransport.getConnectionState() === 'failed') {
17131
17380
  return false;
17132
17381
  }
17133
17382
  // also verify publisher connection if it's needed or different
@@ -17135,7 +17384,7 @@ class RTCEngine extends eventsExports.EventEmitter {
17135
17384
  if (!this.publisher) {
17136
17385
  return false;
17137
17386
  }
17138
- if (this.publisher.pc.connectionState === 'closed' || this.publisher.pc.connectionState === 'failed') {
17387
+ if (this.publisher.getConnectionState() === 'closed' || this.publisher.getConnectionState() === 'failed') {
17139
17388
  return false;
17140
17389
  }
17141
17390
  }
@@ -17241,40 +17490,6 @@ class RTCEngine extends eventsExports.EventEmitter {
17241
17490
  }
17242
17491
  }
17243
17492
  }
17244
- function getConnectedAddress(pc) {
17245
- var _a;
17246
- return __awaiter(this, void 0, void 0, function* () {
17247
- let selectedCandidatePairId = '';
17248
- const candidatePairs = new Map();
17249
- // id -> candidate ip
17250
- const candidates = new Map();
17251
- const stats = yield pc.getStats();
17252
- stats.forEach(v => {
17253
- switch (v.type) {
17254
- case 'transport':
17255
- selectedCandidatePairId = v.selectedCandidatePairId;
17256
- break;
17257
- case 'candidate-pair':
17258
- if (selectedCandidatePairId === '' && v.selected) {
17259
- selectedCandidatePairId = v.id;
17260
- }
17261
- candidatePairs.set(v.id, v);
17262
- break;
17263
- case 'remote-candidate':
17264
- candidates.set(v.id, "".concat(v.address, ":").concat(v.port));
17265
- break;
17266
- }
17267
- });
17268
- if (selectedCandidatePairId === '') {
17269
- return undefined;
17270
- }
17271
- const selectedID = (_a = candidatePairs.get(selectedCandidatePairId)) === null || _a === void 0 ? void 0 : _a.remoteCandidateId;
17272
- if (selectedID === undefined) {
17273
- return undefined;
17274
- }
17275
- return candidates.get(selectedID);
17276
- });
17277
- }
17278
17493
  class SignalReconnectError extends Error {}
17279
17494
 
17280
17495
  class RegionUrlProvider {
@@ -18208,7 +18423,8 @@ class LocalVideoTrack extends LocalTrack {
18208
18423
  }
18209
18424
  /**
18210
18425
  * @internal
18211
- * Sets codecs that should be publishing
18426
+ * Sets codecs that should be publishing, returns new codecs that have not yet
18427
+ * been published
18212
18428
  */
18213
18429
  setPublishingCodecs(codecs) {
18214
18430
  var _a, codecs_1, codecs_1_1;
@@ -18433,14 +18649,16 @@ class RemoteTrack extends Track {
18433
18649
  /** @internal */
18434
18650
  setMediaStream(stream) {
18435
18651
  // this is needed to determine when the track is finished
18436
- // we send each track down in its own MediaStream, so we can assume the
18437
- // current track is the only one that can be removed.
18438
18652
  this.mediaStream = stream;
18439
- stream.onremovetrack = () => {
18440
- this.receiver = undefined;
18441
- this._currentBitrate = 0;
18442
- this.emit(TrackEvent.Ended, this);
18653
+ const onRemoveTrack = event => {
18654
+ if (event.track === this._mediaStreamTrack) {
18655
+ stream.removeEventListener('removetrack', onRemoveTrack);
18656
+ this.receiver = undefined;
18657
+ this._currentBitrate = 0;
18658
+ this.emit(TrackEvent.Ended, this);
18659
+ }
18443
18660
  };
18661
+ stream.addEventListener('removetrack', onRemoveTrack);
18444
18662
  }
18445
18663
  start() {
18446
18664
  this.startMonitor();
@@ -20423,7 +20641,7 @@ class LocalParticipant extends Participant {
20423
20641
  });
20424
20642
  }
20425
20643
  publish(track, opts, isStereo) {
20426
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
20644
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
20427
20645
  return __awaiter(this, void 0, void 0, function* () {
20428
20646
  const existingTrackOfSource = Array.from(this.tracks.values()).find(publishedTrack => track instanceof LocalTrack && publishedTrack.source === track.source);
20429
20647
  if (existingTrackOfSource && track.source !== Track.Source.Unknown) {
@@ -20455,6 +20673,10 @@ class LocalParticipant extends Participant {
20455
20673
  if (opts.videoCodec === 'vp9' && !supportsVP9()) {
20456
20674
  opts.videoCodec = undefined;
20457
20675
  }
20676
+ if (opts.videoCodec === undefined) {
20677
+ opts.videoCodec = defaultVideoCodec;
20678
+ }
20679
+ const videoCodec = opts.videoCodec;
20458
20680
  // handle track actions
20459
20681
  track.on(TrackEvent.Muted, this.onTrackMuted);
20460
20682
  track.on(TrackEvent.Unmuted, this.onTrackUnmuted);
@@ -20472,11 +20694,11 @@ class LocalParticipant extends Participant {
20472
20694
  disableDtx: !((_a = opts.dtx) !== null && _a !== void 0 ? _a : true),
20473
20695
  encryption: this.encryptionType,
20474
20696
  stereo: isStereo,
20475
- disableRed: this.isE2EEEnabled || !((_b = opts.red) !== null && _b !== void 0 ? _b : true)
20697
+ disableRed: this.isE2EEEnabled || !((_b = opts.red) !== null && _b !== void 0 ? _b : true),
20698
+ stream: opts === null || opts === void 0 ? void 0 : opts.stream
20476
20699
  });
20477
20700
  // compute encodings and layers for video
20478
20701
  let encodings;
20479
- let simEncodings;
20480
20702
  if (track.kind === Track.Kind.Video) {
20481
20703
  let dims = {
20482
20704
  width: 0,
@@ -20500,74 +20722,60 @@ class LocalParticipant extends Participant {
20500
20722
  req.height = dims.height;
20501
20723
  // for svc codecs, disable simulcast and use vp8 for backup codec
20502
20724
  if (track instanceof LocalVideoTrack) {
20503
- if (isSVCCodec(opts.videoCodec)) {
20725
+ if (isSVCCodec(videoCodec)) {
20504
20726
  // vp9 svc with screenshare has problem to encode, always use L1T3 here
20505
- if (track.source === Track.Source.ScreenShare && opts.videoCodec === 'vp9') {
20727
+ if (track.source === Track.Source.ScreenShare && videoCodec === 'vp9') {
20506
20728
  opts.scalabilityMode = 'L1T3';
20507
20729
  }
20508
20730
  // set scalabilityMode to 'L3T3_KEY' by default
20509
20731
  opts.scalabilityMode = (_e = opts.scalabilityMode) !== null && _e !== void 0 ? _e : 'L3T3_KEY';
20510
20732
  }
20733
+ req.simulcastCodecs = [new SimulcastCodec({
20734
+ codec: videoCodec,
20735
+ cid: track.mediaStreamTrack.id
20736
+ })];
20511
20737
  // set up backup
20512
- if (opts.videoCodec && opts.backupCodec && opts.videoCodec !== opts.backupCodec.codec) {
20738
+ if (opts.backupCodec && videoCodec !== opts.backupCodec.codec) {
20513
20739
  if (!this.roomOptions.dynacast) {
20514
20740
  this.roomOptions.dynacast = true;
20515
20741
  }
20516
- const simOpts = Object.assign({}, opts);
20517
- simOpts.simulcast = true;
20518
- simEncodings = computeTrackBackupEncodings(track, opts.backupCodec.codec, simOpts);
20519
- req.simulcastCodecs = [new SimulcastCodec({
20520
- codec: opts.videoCodec,
20521
- cid: track.mediaStreamTrack.id,
20522
- enableSimulcastLayers: true
20523
- }), new SimulcastCodec({
20742
+ req.simulcastCodecs.push(new SimulcastCodec({
20524
20743
  codec: opts.backupCodec.codec,
20525
- cid: '',
20526
- enableSimulcastLayers: true
20527
- })];
20528
- } else if (opts.videoCodec) {
20529
- // pass codec info to sfu so it can prefer codec for the client which don't support
20530
- // setCodecPreferences
20531
- req.simulcastCodecs = [new SimulcastCodec({
20532
- codec: opts.videoCodec,
20533
- cid: track.mediaStreamTrack.id,
20534
- enableSimulcastLayers: (_f = opts.simulcast) !== null && _f !== void 0 ? _f : false
20535
- })];
20744
+ cid: ''
20745
+ }));
20536
20746
  }
20537
20747
  }
20538
- encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, dims.width, dims.height, opts);
20748
+ encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, req.width, req.height, opts);
20539
20749
  req.layers = videoLayersFromEncodings(req.width, req.height, encodings, isSVCCodec(opts.videoCodec));
20540
20750
  } else if (track.kind === Track.Kind.Audio) {
20541
20751
  encodings = [{
20542
- maxBitrate: (_h = (_g = opts.audioPreset) === null || _g === void 0 ? void 0 : _g.maxBitrate) !== null && _h !== void 0 ? _h : opts.audioBitrate,
20543
- priority: (_k = (_j = opts.audioPreset) === null || _j === void 0 ? void 0 : _j.priority) !== null && _k !== void 0 ? _k : 'high',
20544
- networkPriority: (_m = (_l = opts.audioPreset) === null || _l === void 0 ? void 0 : _l.priority) !== null && _m !== void 0 ? _m : 'high'
20752
+ maxBitrate: (_g = (_f = opts.audioPreset) === null || _f === void 0 ? void 0 : _f.maxBitrate) !== null && _g !== void 0 ? _g : opts.audioBitrate,
20753
+ priority: (_j = (_h = opts.audioPreset) === null || _h === void 0 ? void 0 : _h.priority) !== null && _j !== void 0 ? _j : 'high',
20754
+ networkPriority: (_l = (_k = opts.audioPreset) === null || _k === void 0 ? void 0 : _k.priority) !== null && _l !== void 0 ? _l : 'high'
20545
20755
  }];
20546
20756
  }
20547
20757
  if (!this.engine || this.engine.isClosed) {
20548
20758
  throw new UnexpectedConnectionState('cannot publish track when not connected');
20549
20759
  }
20550
20760
  const ti = yield this.engine.addTrack(req);
20551
- let primaryCodecSupported = false;
20552
- let backupCodecSupported = false;
20553
- ti.codecs.forEach(c => {
20554
- if (isCodecEqual(c.mimeType, opts.videoCodec)) {
20555
- primaryCodecSupported = true;
20556
- } else if (opts.backupCodec && isCodecEqual(c.mimeType, opts.backupCodec.codec)) {
20557
- backupCodecSupported = true;
20761
+ // server might not support the codec the client has requested, in that case, fallback
20762
+ // to a supported codec
20763
+ let primaryCodecMime;
20764
+ ti.codecs.forEach(codec => {
20765
+ if (primaryCodecMime === undefined) {
20766
+ primaryCodecMime = codec.mimeType;
20558
20767
  }
20559
20768
  });
20560
- if (req.simulcastCodecs.length > 0) {
20561
- if (!primaryCodecSupported && !backupCodecSupported) {
20562
- throw Error('cannot publish track, codec not supported by server');
20563
- }
20564
- if (!primaryCodecSupported && opts.backupCodec) {
20565
- const backupCodec = opts.backupCodec;
20566
- opts = Object.assign({}, opts);
20567
- livekitLogger.debug("primary codec ".concat(opts.videoCodec, " not supported, fallback to ").concat(backupCodec.codec));
20568
- opts.videoCodec = backupCodec.codec;
20569
- opts.videoEncoding = backupCodec.encoding;
20570
- encodings = simEncodings;
20769
+ if (primaryCodecMime && track.kind === Track.Kind.Video) {
20770
+ const updatedCodec = mimeTypeToVideoCodecString(primaryCodecMime);
20771
+ if (updatedCodec !== videoCodec) {
20772
+ livekitLogger.debug('falling back to server selected codec', {
20773
+ codec: updatedCodec
20774
+ });
20775
+ /* @ts-ignore */
20776
+ opts.videoCodec = updatedCodec;
20777
+ // recompute encodings since bitrates/etc could have changed
20778
+ encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, req.width, req.height, opts);
20571
20779
  }
20572
20780
  }
20573
20781
  const publication = new LocalTrackPublication(track.kind, ti, track);
@@ -20581,19 +20789,18 @@ class LocalParticipant extends Participant {
20581
20789
  encodings,
20582
20790
  trackInfo: ti
20583
20791
  });
20584
- // store RTPSender
20585
20792
  track.sender = yield this.engine.createSender(track, opts, encodings);
20586
20793
  if (encodings) {
20587
20794
  if (isFireFox() && track.kind === Track.Kind.Audio) {
20588
20795
  /* Refer to RFC https://datatracker.ietf.org/doc/html/rfc7587#section-6.1,
20589
- livekit-server uses maxaveragebitrate=510000in the answer sdp to permit client to
20796
+ livekit-server uses maxaveragebitrate=510000 in the answer sdp to permit client to
20590
20797
  publish high quality audio track. But firefox always uses this value as the actual
20591
20798
  bitrates, causing the audio bitrates to rise to 510Kbps in any stereo case unexpectedly.
20592
20799
  So the client need to modify maxaverragebitrates in answer sdp to user provided value to
20593
20800
  fix the issue.
20594
20801
  */
20595
20802
  let trackTransceiver = undefined;
20596
- for (const transceiver of this.engine.publisher.pc.getTransceivers()) {
20803
+ for (const transceiver of this.engine.publisher.getTransceivers()) {
20597
20804
  if (transceiver.sender === track.sender) {
20598
20805
  trackTransceiver = transceiver;
20599
20806
  break;
@@ -20603,10 +20810,10 @@ class LocalParticipant extends Participant {
20603
20810
  this.engine.publisher.setTrackCodecBitrate({
20604
20811
  transceiver: trackTransceiver,
20605
20812
  codec: 'opus',
20606
- maxbr: ((_o = encodings[0]) === null || _o === void 0 ? void 0 : _o.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
20813
+ maxbr: ((_m = encodings[0]) === null || _m === void 0 ? void 0 : _m.maxBitrate) ? encodings[0].maxBitrate / 1000 : 0
20607
20814
  });
20608
20815
  }
20609
- } else if (track.codec && isSVCCodec(track.codec) && ((_p = encodings[0]) === null || _p === void 0 ? void 0 : _p.maxBitrate)) {
20816
+ } else if (track.codec && isSVCCodec(track.codec) && ((_o = encodings[0]) === null || _o === void 0 ? void 0 : _o.maxBitrate)) {
20610
20817
  this.engine.publisher.setTrackCodecBitrate({
20611
20818
  cid: req.cid,
20612
20819
  codec: track.codec,
@@ -20666,8 +20873,7 @@ class LocalParticipant extends Participant {
20666
20873
  sid: track.sid,
20667
20874
  simulcastCodecs: [{
20668
20875
  codec: opts.videoCodec,
20669
- cid: simulcastTrack.mediaStreamTrack.id,
20670
- enableSimulcastLayers: opts.simulcast
20876
+ cid: simulcastTrack.mediaStreamTrack.id
20671
20877
  }]
20672
20878
  });
20673
20879
  req.layers = videoLayersFromEncodings(req.width, req.height, encodings);
@@ -20714,9 +20920,9 @@ class LocalParticipant extends Participant {
20714
20920
  let negotiationNeeded = false;
20715
20921
  const trackSender = track.sender;
20716
20922
  track.sender = undefined;
20717
- if (this.engine.publisher && this.engine.publisher.pc.connectionState !== 'closed' && trackSender) {
20923
+ if (this.engine.publisher && this.engine.publisher.getConnectionState() !== 'closed' && trackSender) {
20718
20924
  try {
20719
- for (const transceiver of this.engine.publisher.pc.getTransceivers()) {
20925
+ for (const transceiver of this.engine.publisher.getTransceivers()) {
20720
20926
  // if sender is not currently sending (after replaceTrack(null))
20721
20927
  // removeTrack would have no effect.
20722
20928
  // to ensure we end up successfully removing the track, manually set
@@ -21027,6 +21233,7 @@ class Room extends eventsExports.EventEmitter {
21027
21233
  nextUrl = yield this.regionUrlProvider.getNextBestRegionUrl((_c = this.abortController) === null || _c === void 0 ? void 0 : _c.signal);
21028
21234
  } catch (error) {
21029
21235
  if (error instanceof ConnectionError && (error.status === 401 || error.reason === 3 /* ConnectionErrorReason.Cancelled */)) {
21236
+ this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
21030
21237
  reject(error);
21031
21238
  return;
21032
21239
  }
@@ -21035,9 +21242,11 @@ class Room extends eventsExports.EventEmitter {
21035
21242
  livekitLogger.info("Initial connection failed with ConnectionError: ".concat(e.message, ". Retrying with another region: ").concat(nextUrl));
21036
21243
  yield connectFn(resolve, reject, nextUrl);
21037
21244
  } else {
21245
+ this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
21038
21246
  reject(e);
21039
21247
  }
21040
21248
  } else {
21249
+ this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
21041
21250
  reject(e);
21042
21251
  }
21043
21252
  }
@@ -21122,8 +21331,8 @@ class Room extends eventsExports.EventEmitter {
21122
21331
  this.setupLocalParticipantEvents();
21123
21332
  this.emit(RoomEvent.SignalConnected);
21124
21333
  } catch (err) {
21334
+ yield this.engine.close();
21125
21335
  this.recreateEngine();
21126
- this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
21127
21336
  const resultingError = new ConnectionError("could not establish signal connection");
21128
21337
  if (err instanceof Error) {
21129
21338
  resultingError.message = "".concat(resultingError.message, ": ").concat(err.message);
@@ -21138,15 +21347,15 @@ class Room extends eventsExports.EventEmitter {
21138
21347
  throw resultingError;
21139
21348
  }
21140
21349
  if (abortController.signal.aborted) {
21350
+ yield this.engine.close();
21141
21351
  this.recreateEngine();
21142
- this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
21143
21352
  throw new ConnectionError("Connection attempt aborted");
21144
21353
  }
21145
21354
  try {
21146
21355
  yield this.engine.waitForPCInitialConnection(this.connOptions.peerConnectionTimeout, abortController);
21147
21356
  } catch (e) {
21357
+ yield this.engine.close();
21148
21358
  this.recreateEngine();
21149
- this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
21150
21359
  throw e;
21151
21360
  }
21152
21361
  // also hook unload event
@@ -21962,8 +22171,11 @@ class Room extends eventsExports.EventEmitter {
21962
22171
  }
21963
22172
  const parts = unpackStreamId(stream.id);
21964
22173
  const participantId = parts[0];
21965
- let trackId = parts[1];
21966
- if (!trackId || trackId === '') trackId = mediaTrack.id;
22174
+ let streamId = parts[1];
22175
+ let trackId = mediaTrack.id;
22176
+ // firefox will get streamId (pID|trackId) instead of (pID|streamId) as it doesn't support sync tracks by stream
22177
+ // and generates its own track id instead of infer from sdp track id.
22178
+ if (streamId && streamId.startsWith('TR')) trackId = streamId;
21967
22179
  if (participantId === this.localParticipant.sid) {
21968
22180
  livekitLogger.warn('tried to create RemoteParticipant for local participant');
21969
22181
  return;
@@ -22138,18 +22350,18 @@ class Room extends eventsExports.EventEmitter {
22138
22350
  return participant;
22139
22351
  }
22140
22352
  sendSyncState() {
22141
- var _a, _b;
22142
- if (this.engine.subscriber === undefined || this.engine.subscriber.pc.localDescription === null) {
22353
+ var _a, _b, _c, _d;
22354
+ const previousAnswer = (_a = this.engine.subscriber) === null || _a === void 0 ? void 0 : _a.getLocalDescription();
22355
+ const previousOffer = (_b = this.engine.subscriber) === null || _b === void 0 ? void 0 : _b.getRemoteDescription();
22356
+ if (!previousAnswer) {
22143
22357
  return;
22144
22358
  }
22145
- const previousAnswer = this.engine.subscriber.pc.localDescription;
22146
- const previousOffer = this.engine.subscriber.pc.remoteDescription;
22147
22359
  /* 1. autosubscribe on, so subscribed tracks = all tracks - unsub tracks,
22148
22360
  in this case, we send unsub tracks, so server add all tracks to this
22149
22361
  subscribe pc and unsub special tracks from it.
22150
22362
  2. autosubscribe off, we send subscribed tracks.
22151
22363
  */
22152
- const autoSubscribe = (_b = (_a = this.connOptions) === null || _a === void 0 ? void 0 : _a.autoSubscribe) !== null && _b !== void 0 ? _b : true;
22364
+ const autoSubscribe = (_d = (_c = this.connOptions) === null || _c === void 0 ? void 0 : _c.autoSubscribe) !== null && _d !== void 0 ? _d : true;
22153
22365
  const trackSids = new Array();
22154
22366
  this.participants.forEach(participant => {
22155
22367
  participant.tracks.forEach(track => {
@@ -22764,7 +22976,7 @@ class WebRTCCheck extends Checker {
22764
22976
  }
22765
22977
  };
22766
22978
  if (this.room.engine.subscriber) {
22767
- this.room.engine.subscriber.pc.onicecandidateerror = ev => {
22979
+ this.room.engine.subscriber.onIceCandidateError = ev => {
22768
22980
  if (ev instanceof RTCPeerConnectionIceErrorEvent) {
22769
22981
  this.appendWarning("error with ICE candidate: ".concat(ev.errorCode, " ").concat(ev.errorText, " ").concat(ev.url));
22770
22982
  }
@@ -22983,5 +23195,5 @@ function isFacingModeValue(item) {
22983
23195
  return item === undefined || allowedValues.includes(item);
22984
23196
  }
22985
23197
 
22986
- export { AudioPresets, BaseKeyProvider, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, NegotiationError, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, importKey, isBackupCodec, isBrowserSupported, isCodecEqual, isE2EESupported, isInsertableStreamSupported, isScriptTransformSupported, isVideoFrame, mimeTypeToVideoCodecString, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
23198
+ export { AudioPresets, BaseKeyProvider, ConnectionCheck, ConnectionError, ConnectionQuality, ConnectionState, CriticalTimers, CryptorEvent, DataPacket_Kind, DefaultReconnectPolicy, DeviceUnsupportedError, DisconnectReason, EncryptionEvent, EngineEvent, ExternalE2EEKeyProvider, KeyHandlerEvent, KeyProviderEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, NegotiationError, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createAudioAnalyser, createE2EEKey, createKeyMaterialFromBuffer, createKeyMaterialFromString, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, deriveKeys, detachTrack, facingModeFromDeviceLabel, facingModeFromLocalTrack, getEmptyAudioStreamTrack, getEmptyVideoStreamTrack, importKey, isBackupCodec, isBrowserSupported, isE2EESupported, isInsertableStreamSupported, isScriptTransformSupported, isVideoFrame, needsRbspUnescaping, parseRbsp, protocolVersion, ratchet, setLogExtension, setLogLevel, supportsAV1, supportsAdaptiveStream, supportsDynacast, supportsVP9, version, videoCodecs, writeRbsp };
22987
23199
  //# sourceMappingURL=livekit-client.esm.mjs.map