livekit-client 0.18.6 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/README.md +1 -1
  2. package/dist/livekit-client.esm.mjs +1034 -438
  3. package/dist/livekit-client.esm.mjs.map +1 -1
  4. package/dist/livekit-client.umd.js +1 -1
  5. package/dist/livekit-client.umd.js.map +1 -1
  6. package/dist/{api → src/api}/RequestQueue.d.ts +0 -0
  7. package/dist/src/api/RequestQueue.d.ts.map +1 -0
  8. package/dist/{api → src/api}/SignalClient.d.ts +3 -3
  9. package/dist/src/api/SignalClient.d.ts.map +1 -0
  10. package/dist/{index.d.ts → src/index.d.ts} +3 -4
  11. package/dist/src/index.d.ts.map +1 -0
  12. package/dist/{logger.d.ts → src/logger.d.ts} +0 -0
  13. package/dist/src/logger.d.ts.map +1 -0
  14. package/dist/src/options.d.ts +61 -0
  15. package/dist/src/options.d.ts.map +1 -0
  16. package/dist/{proto → src/proto}/google/protobuf/timestamp.d.ts +0 -0
  17. package/dist/src/proto/google/protobuf/timestamp.d.ts.map +1 -0
  18. package/dist/{proto → src/proto}/livekit_models.d.ts +80 -0
  19. package/dist/src/proto/livekit_models.d.ts.map +1 -0
  20. package/dist/{proto → src/proto}/livekit_rtc.d.ts +661 -0
  21. package/dist/src/proto/livekit_rtc.d.ts.map +1 -0
  22. package/dist/{room → src/room}/DeviceManager.d.ts +0 -0
  23. package/dist/src/room/DeviceManager.d.ts.map +1 -0
  24. package/dist/{room → src/room}/PCTransport.d.ts +0 -0
  25. package/dist/src/room/PCTransport.d.ts.map +1 -0
  26. package/dist/{room → src/room}/RTCEngine.d.ts +4 -2
  27. package/dist/src/room/RTCEngine.d.ts.map +1 -0
  28. package/dist/{room → src/room}/Room.d.ts +13 -7
  29. package/dist/src/room/Room.d.ts.map +1 -0
  30. package/dist/{room → src/room}/errors.d.ts +0 -0
  31. package/dist/src/room/errors.d.ts.map +1 -0
  32. package/dist/{room → src/room}/events.d.ts +11 -13
  33. package/dist/src/room/events.d.ts.map +1 -0
  34. package/dist/{room → src/room}/participant/LocalParticipant.d.ts +4 -1
  35. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -0
  36. package/dist/{room → src/room}/participant/Participant.d.ts +0 -4
  37. package/dist/src/room/participant/Participant.d.ts.map +1 -0
  38. package/dist/{room → src/room}/participant/ParticipantTrackPermission.d.ts +0 -0
  39. package/dist/src/room/participant/ParticipantTrackPermission.d.ts.map +1 -0
  40. package/dist/{room → src/room}/participant/RemoteParticipant.d.ts +3 -2
  41. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -0
  42. package/dist/{room → src/room}/participant/publishUtils.d.ts +0 -0
  43. package/dist/src/room/participant/publishUtils.d.ts.map +1 -0
  44. package/dist/{room → src/room}/stats.d.ts +1 -0
  45. package/dist/src/room/stats.d.ts.map +1 -0
  46. package/dist/{room → src/room}/track/LocalAudioTrack.d.ts +0 -0
  47. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -0
  48. package/dist/{room → src/room}/track/LocalTrack.d.ts +3 -0
  49. package/dist/src/room/track/LocalTrack.d.ts.map +1 -0
  50. package/dist/{room → src/room}/track/LocalTrackPublication.d.ts +0 -0
  51. package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -0
  52. package/dist/{room → src/room}/track/LocalVideoTrack.d.ts +17 -2
  53. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -0
  54. package/dist/{room → src/room}/track/RemoteAudioTrack.d.ts +0 -0
  55. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -0
  56. package/dist/{room → src/room}/track/RemoteTrack.d.ts +0 -1
  57. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -0
  58. package/dist/{room → src/room}/track/RemoteTrackPublication.d.ts +0 -0
  59. package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -0
  60. package/dist/{room → src/room}/track/RemoteVideoTrack.d.ts +25 -1
  61. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -0
  62. package/dist/{room → src/room}/track/Track.d.ts +6 -1
  63. package/dist/src/room/track/Track.d.ts.map +1 -0
  64. package/dist/{room → src/room}/track/TrackPublication.d.ts +0 -0
  65. package/dist/src/room/track/TrackPublication.d.ts.map +1 -0
  66. package/dist/{room → src/room}/track/create.d.ts +0 -0
  67. package/dist/src/room/track/create.d.ts.map +1 -0
  68. package/dist/{room → src/room}/track/defaults.d.ts +0 -0
  69. package/dist/src/room/track/defaults.d.ts.map +1 -0
  70. package/dist/{room → src/room}/track/options.d.ts +2 -31
  71. package/dist/src/room/track/options.d.ts.map +1 -0
  72. package/dist/{room → src/room}/track/types.d.ts +5 -0
  73. package/dist/src/room/track/types.d.ts.map +1 -0
  74. package/dist/{room → src/room}/track/utils.d.ts +0 -0
  75. package/dist/src/room/track/utils.d.ts.map +1 -0
  76. package/dist/{room → src/room}/utils.d.ts +0 -0
  77. package/dist/src/room/utils.d.ts.map +1 -0
  78. package/dist/src/test/MockMediaStreamTrack.d.ts +26 -0
  79. package/dist/src/test/MockMediaStreamTrack.d.ts.map +1 -0
  80. package/dist/{test → src/test}/mocks.d.ts +0 -0
  81. package/dist/src/test/mocks.d.ts.map +1 -0
  82. package/dist/src/version.d.ts +3 -0
  83. package/dist/src/version.d.ts.map +1 -0
  84. package/package.json +6 -2
  85. package/src/api/SignalClient.ts +34 -9
  86. package/src/index.ts +4 -3
  87. package/src/options.ts +0 -82
  88. package/src/proto/livekit_models.ts +90 -0
  89. package/src/proto/livekit_rtc.ts +235 -1
  90. package/src/room/DeviceManager.ts +4 -1
  91. package/src/room/RTCEngine.ts +46 -9
  92. package/src/room/Room.ts +122 -53
  93. package/src/room/events.ts +12 -14
  94. package/src/room/participant/LocalParticipant.ts +108 -23
  95. package/src/room/participant/Participant.ts +0 -5
  96. package/src/room/participant/RemoteParticipant.ts +17 -5
  97. package/src/room/participant/publishUtils.test.ts +2 -2
  98. package/src/room/stats.ts +2 -0
  99. package/src/room/track/LocalAudioTrack.ts +4 -0
  100. package/src/room/track/LocalTrack.ts +12 -5
  101. package/src/room/track/LocalVideoTrack.ts +144 -56
  102. package/src/room/track/RemoteTrack.ts +0 -2
  103. package/src/room/track/RemoteVideoTrack.test.ts +149 -0
  104. package/src/room/track/RemoteVideoTrack.ts +118 -37
  105. package/src/room/track/Track.ts +23 -2
  106. package/src/room/track/create.ts +1 -1
  107. package/src/room/track/options.ts +2 -31
  108. package/src/room/track/types.ts +5 -0
  109. package/src/room/track/utils.test.ts +6 -6
  110. package/src/test/MockMediaStreamTrack.ts +83 -0
  111. package/src/version.ts +4 -2
  112. package/dist/api/RequestQueue.d.ts.map +0 -1
  113. package/dist/api/SignalClient.d.ts.map +0 -1
  114. package/dist/connect.d.ts +0 -24
  115. package/dist/connect.d.ts.map +0 -1
  116. package/dist/index.d.ts.map +0 -1
  117. package/dist/logger.d.ts.map +0 -1
  118. package/dist/options.d.ts +0 -128
  119. package/dist/options.d.ts.map +0 -1
  120. package/dist/proto/google/protobuf/timestamp.d.ts.map +0 -1
  121. package/dist/proto/livekit_models.d.ts.map +0 -1
  122. package/dist/proto/livekit_rtc.d.ts.map +0 -1
  123. package/dist/room/DeviceManager.d.ts.map +0 -1
  124. package/dist/room/PCTransport.d.ts.map +0 -1
  125. package/dist/room/RTCEngine.d.ts.map +0 -1
  126. package/dist/room/Room.d.ts.map +0 -1
  127. package/dist/room/errors.d.ts.map +0 -1
  128. package/dist/room/events.d.ts.map +0 -1
  129. package/dist/room/participant/LocalParticipant.d.ts.map +0 -1
  130. package/dist/room/participant/Participant.d.ts.map +0 -1
  131. package/dist/room/participant/ParticipantTrackPermission.d.ts.map +0 -1
  132. package/dist/room/participant/RemoteParticipant.d.ts.map +0 -1
  133. package/dist/room/participant/publishUtils.d.ts.map +0 -1
  134. package/dist/room/stats.d.ts.map +0 -1
  135. package/dist/room/track/LocalAudioTrack.d.ts.map +0 -1
  136. package/dist/room/track/LocalTrack.d.ts.map +0 -1
  137. package/dist/room/track/LocalTrackPublication.d.ts.map +0 -1
  138. package/dist/room/track/LocalVideoTrack.d.ts.map +0 -1
  139. package/dist/room/track/RemoteAudioTrack.d.ts.map +0 -1
  140. package/dist/room/track/RemoteTrack.d.ts.map +0 -1
  141. package/dist/room/track/RemoteTrackPublication.d.ts.map +0 -1
  142. package/dist/room/track/RemoteVideoTrack.d.ts.map +0 -1
  143. package/dist/room/track/Track.d.ts.map +0 -1
  144. package/dist/room/track/TrackPublication.d.ts.map +0 -1
  145. package/dist/room/track/create.d.ts.map +0 -1
  146. package/dist/room/track/defaults.d.ts.map +0 -1
  147. package/dist/room/track/options.d.ts.map +0 -1
  148. package/dist/room/track/types.d.ts.map +0 -1
  149. package/dist/room/track/utils.d.ts.map +0 -1
  150. package/dist/room/utils.d.ts.map +0 -1
  151. package/dist/test/mocks.d.ts.map +0 -1
  152. package/dist/version.d.ts +0 -3
  153. package/dist/version.d.ts.map +0 -1
  154. package/src/connect.ts +0 -98
@@ -5200,6 +5200,91 @@ const ParticipantInfo = {
5200
5200
 
5201
5201
  };
5202
5202
 
5203
+ function createBaseSimulcastCodecInfo() {
5204
+ return {
5205
+ mimeType: '',
5206
+ mid: '',
5207
+ cid: ''
5208
+ };
5209
+ }
5210
+
5211
+ const SimulcastCodecInfo = {
5212
+ encode(message) {
5213
+ let writer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : minimal.Writer.create();
5214
+
5215
+ if (message.mimeType !== '') {
5216
+ writer.uint32(10).string(message.mimeType);
5217
+ }
5218
+
5219
+ if (message.mid !== '') {
5220
+ writer.uint32(18).string(message.mid);
5221
+ }
5222
+
5223
+ if (message.cid !== '') {
5224
+ writer.uint32(26).string(message.cid);
5225
+ }
5226
+
5227
+ return writer;
5228
+ },
5229
+
5230
+ decode(input, length) {
5231
+ const reader = input instanceof minimal.Reader ? input : new minimal.Reader(input);
5232
+ let end = length === undefined ? reader.len : reader.pos + length;
5233
+ const message = createBaseSimulcastCodecInfo();
5234
+
5235
+ while (reader.pos < end) {
5236
+ const tag = reader.uint32();
5237
+
5238
+ switch (tag >>> 3) {
5239
+ case 1:
5240
+ message.mimeType = reader.string();
5241
+ break;
5242
+
5243
+ case 2:
5244
+ message.mid = reader.string();
5245
+ break;
5246
+
5247
+ case 3:
5248
+ message.cid = reader.string();
5249
+ break;
5250
+
5251
+ default:
5252
+ reader.skipType(tag & 7);
5253
+ break;
5254
+ }
5255
+ }
5256
+
5257
+ return message;
5258
+ },
5259
+
5260
+ fromJSON(object) {
5261
+ return {
5262
+ mimeType: isSet$1(object.mimeType) ? String(object.mimeType) : '',
5263
+ mid: isSet$1(object.mid) ? String(object.mid) : '',
5264
+ cid: isSet$1(object.cid) ? String(object.cid) : ''
5265
+ };
5266
+ },
5267
+
5268
+ toJSON(message) {
5269
+ const obj = {};
5270
+ message.mimeType !== undefined && (obj.mimeType = message.mimeType);
5271
+ message.mid !== undefined && (obj.mid = message.mid);
5272
+ message.cid !== undefined && (obj.cid = message.cid);
5273
+ return obj;
5274
+ },
5275
+
5276
+ fromPartial(object) {
5277
+ var _a, _b, _c;
5278
+
5279
+ const message = createBaseSimulcastCodecInfo();
5280
+ message.mimeType = (_a = object.mimeType) !== null && _a !== void 0 ? _a : '';
5281
+ message.mid = (_b = object.mid) !== null && _b !== void 0 ? _b : '';
5282
+ message.cid = (_c = object.cid) !== null && _c !== void 0 ? _c : '';
5283
+ return message;
5284
+ }
5285
+
5286
+ };
5287
+
5203
5288
  function createBaseTrackInfo() {
5204
5289
  return {
5205
5290
  sid: '',
@@ -5213,7 +5298,8 @@ function createBaseTrackInfo() {
5213
5298
  source: 0,
5214
5299
  layers: [],
5215
5300
  mimeType: '',
5216
- mid: ''
5301
+ mid: '',
5302
+ codecs: []
5217
5303
  };
5218
5304
  }
5219
5305
 
@@ -5269,6 +5355,10 @@ const TrackInfo = {
5269
5355
  writer.uint32(98).string(message.mid);
5270
5356
  }
5271
5357
 
5358
+ for (const v of message.codecs) {
5359
+ SimulcastCodecInfo.encode(v, writer.uint32(106).fork()).ldelim();
5360
+ }
5361
+
5272
5362
  return writer;
5273
5363
  },
5274
5364
 
@@ -5329,6 +5419,10 @@ const TrackInfo = {
5329
5419
  message.mid = reader.string();
5330
5420
  break;
5331
5421
 
5422
+ case 13:
5423
+ message.codecs.push(SimulcastCodecInfo.decode(reader, reader.uint32()));
5424
+ break;
5425
+
5332
5426
  default:
5333
5427
  reader.skipType(tag & 7);
5334
5428
  break;
@@ -5351,7 +5445,8 @@ const TrackInfo = {
5351
5445
  source: isSet$1(object.source) ? trackSourceFromJSON(object.source) : 0,
5352
5446
  layers: Array.isArray(object === null || object === void 0 ? void 0 : object.layers) ? object.layers.map(e => VideoLayer.fromJSON(e)) : [],
5353
5447
  mimeType: isSet$1(object.mimeType) ? String(object.mimeType) : '',
5354
- mid: isSet$1(object.mid) ? String(object.mid) : ''
5448
+ mid: isSet$1(object.mid) ? String(object.mid) : '',
5449
+ codecs: Array.isArray(object === null || object === void 0 ? void 0 : object.codecs) ? object.codecs.map(e => SimulcastCodecInfo.fromJSON(e)) : []
5355
5450
  };
5356
5451
  },
5357
5452
 
@@ -5375,11 +5470,18 @@ const TrackInfo = {
5375
5470
 
5376
5471
  message.mimeType !== undefined && (obj.mimeType = message.mimeType);
5377
5472
  message.mid !== undefined && (obj.mid = message.mid);
5473
+
5474
+ if (message.codecs) {
5475
+ obj.codecs = message.codecs.map(e => e ? SimulcastCodecInfo.toJSON(e) : undefined);
5476
+ } else {
5477
+ obj.codecs = [];
5478
+ }
5479
+
5378
5480
  return obj;
5379
5481
  },
5380
5482
 
5381
5483
  fromPartial(object) {
5382
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
5484
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
5383
5485
 
5384
5486
  const message = createBaseTrackInfo();
5385
5487
  message.sid = (_a = object.sid) !== null && _a !== void 0 ? _a : '';
@@ -5394,6 +5496,7 @@ const TrackInfo = {
5394
5496
  message.layers = ((_k = object.layers) === null || _k === void 0 ? void 0 : _k.map(e => VideoLayer.fromPartial(e))) || [];
5395
5497
  message.mimeType = (_l = object.mimeType) !== null && _l !== void 0 ? _l : '';
5396
5498
  message.mid = (_m = object.mid) !== null && _m !== void 0 ? _m : '';
5499
+ message.codecs = ((_o = object.codecs) === null || _o === void 0 ? void 0 : _o.map(e => SimulcastCodecInfo.fromPartial(e))) || [];
5397
5500
  return message;
5398
5501
  }
5399
5502
 
@@ -6381,6 +6484,42 @@ function streamStateToJSON(object) {
6381
6484
  return 'UNKNOWN';
6382
6485
  }
6383
6486
  }
6487
+ var CandidateProtocol;
6488
+
6489
+ (function (CandidateProtocol) {
6490
+ CandidateProtocol[CandidateProtocol["UDP"] = 0] = "UDP";
6491
+ CandidateProtocol[CandidateProtocol["TCP"] = 1] = "TCP";
6492
+ CandidateProtocol[CandidateProtocol["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
6493
+ })(CandidateProtocol || (CandidateProtocol = {}));
6494
+
6495
+ function candidateProtocolFromJSON(object) {
6496
+ switch (object) {
6497
+ case 0:
6498
+ case 'UDP':
6499
+ return CandidateProtocol.UDP;
6500
+
6501
+ case 1:
6502
+ case 'TCP':
6503
+ return CandidateProtocol.TCP;
6504
+
6505
+ case -1:
6506
+ case 'UNRECOGNIZED':
6507
+ default:
6508
+ return CandidateProtocol.UNRECOGNIZED;
6509
+ }
6510
+ }
6511
+ function candidateProtocolToJSON(object) {
6512
+ switch (object) {
6513
+ case CandidateProtocol.UDP:
6514
+ return 'UDP';
6515
+
6516
+ case CandidateProtocol.TCP:
6517
+ return 'TCP';
6518
+
6519
+ default:
6520
+ return 'UNKNOWN';
6521
+ }
6522
+ }
6384
6523
 
6385
6524
  function createBaseSignalRequest() {
6386
6525
  return {
@@ -6814,6 +6953,91 @@ const SignalResponse = {
6814
6953
 
6815
6954
  };
6816
6955
 
6956
+ function createBaseSimulcastCodec() {
6957
+ return {
6958
+ codec: '',
6959
+ cid: '',
6960
+ enableSimulcastLayers: false
6961
+ };
6962
+ }
6963
+
6964
+ const SimulcastCodec = {
6965
+ encode(message) {
6966
+ let writer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : minimal.Writer.create();
6967
+
6968
+ if (message.codec !== '') {
6969
+ writer.uint32(10).string(message.codec);
6970
+ }
6971
+
6972
+ if (message.cid !== '') {
6973
+ writer.uint32(18).string(message.cid);
6974
+ }
6975
+
6976
+ if (message.enableSimulcastLayers === true) {
6977
+ writer.uint32(24).bool(message.enableSimulcastLayers);
6978
+ }
6979
+
6980
+ return writer;
6981
+ },
6982
+
6983
+ decode(input, length) {
6984
+ const reader = input instanceof minimal.Reader ? input : new minimal.Reader(input);
6985
+ let end = length === undefined ? reader.len : reader.pos + length;
6986
+ const message = createBaseSimulcastCodec();
6987
+
6988
+ while (reader.pos < end) {
6989
+ const tag = reader.uint32();
6990
+
6991
+ switch (tag >>> 3) {
6992
+ case 1:
6993
+ message.codec = reader.string();
6994
+ break;
6995
+
6996
+ case 2:
6997
+ message.cid = reader.string();
6998
+ break;
6999
+
7000
+ case 3:
7001
+ message.enableSimulcastLayers = reader.bool();
7002
+ break;
7003
+
7004
+ default:
7005
+ reader.skipType(tag & 7);
7006
+ break;
7007
+ }
7008
+ }
7009
+
7010
+ return message;
7011
+ },
7012
+
7013
+ fromJSON(object) {
7014
+ return {
7015
+ codec: isSet(object.codec) ? String(object.codec) : '',
7016
+ cid: isSet(object.cid) ? String(object.cid) : '',
7017
+ enableSimulcastLayers: isSet(object.enableSimulcastLayers) ? Boolean(object.enableSimulcastLayers) : false
7018
+ };
7019
+ },
7020
+
7021
+ toJSON(message) {
7022
+ const obj = {};
7023
+ message.codec !== undefined && (obj.codec = message.codec);
7024
+ message.cid !== undefined && (obj.cid = message.cid);
7025
+ message.enableSimulcastLayers !== undefined && (obj.enableSimulcastLayers = message.enableSimulcastLayers);
7026
+ return obj;
7027
+ },
7028
+
7029
+ fromPartial(object) {
7030
+ var _a, _b, _c;
7031
+
7032
+ const message = createBaseSimulcastCodec();
7033
+ message.codec = (_a = object.codec) !== null && _a !== void 0 ? _a : '';
7034
+ message.cid = (_b = object.cid) !== null && _b !== void 0 ? _b : '';
7035
+ message.enableSimulcastLayers = (_c = object.enableSimulcastLayers) !== null && _c !== void 0 ? _c : false;
7036
+ return message;
7037
+ }
7038
+
7039
+ };
7040
+
6817
7041
  function createBaseAddTrackRequest() {
6818
7042
  return {
6819
7043
  cid: '',
@@ -6824,7 +7048,8 @@ function createBaseAddTrackRequest() {
6824
7048
  muted: false,
6825
7049
  disableDtx: false,
6826
7050
  source: 0,
6827
- layers: []
7051
+ layers: [],
7052
+ simulcastCodecs: []
6828
7053
  };
6829
7054
  }
6830
7055
 
@@ -6868,6 +7093,10 @@ const AddTrackRequest = {
6868
7093
  VideoLayer.encode(v, writer.uint32(74).fork()).ldelim();
6869
7094
  }
6870
7095
 
7096
+ for (const v of message.simulcastCodecs) {
7097
+ SimulcastCodec.encode(v, writer.uint32(82).fork()).ldelim();
7098
+ }
7099
+
6871
7100
  return writer;
6872
7101
  },
6873
7102
 
@@ -6916,6 +7145,10 @@ const AddTrackRequest = {
6916
7145
  message.layers.push(VideoLayer.decode(reader, reader.uint32()));
6917
7146
  break;
6918
7147
 
7148
+ case 10:
7149
+ message.simulcastCodecs.push(SimulcastCodec.decode(reader, reader.uint32()));
7150
+ break;
7151
+
6919
7152
  default:
6920
7153
  reader.skipType(tag & 7);
6921
7154
  break;
@@ -6935,7 +7168,8 @@ const AddTrackRequest = {
6935
7168
  muted: isSet(object.muted) ? Boolean(object.muted) : false,
6936
7169
  disableDtx: isSet(object.disableDtx) ? Boolean(object.disableDtx) : false,
6937
7170
  source: isSet(object.source) ? trackSourceFromJSON(object.source) : 0,
6938
- layers: Array.isArray(object === null || object === void 0 ? void 0 : object.layers) ? object.layers.map(e => VideoLayer.fromJSON(e)) : []
7171
+ layers: Array.isArray(object === null || object === void 0 ? void 0 : object.layers) ? object.layers.map(e => VideoLayer.fromJSON(e)) : [],
7172
+ simulcastCodecs: Array.isArray(object === null || object === void 0 ? void 0 : object.simulcastCodecs) ? object.simulcastCodecs.map(e => SimulcastCodec.fromJSON(e)) : []
6939
7173
  };
6940
7174
  },
6941
7175
 
@@ -6956,11 +7190,17 @@ const AddTrackRequest = {
6956
7190
  obj.layers = [];
6957
7191
  }
6958
7192
 
7193
+ if (message.simulcastCodecs) {
7194
+ obj.simulcastCodecs = message.simulcastCodecs.map(e => e ? SimulcastCodec.toJSON(e) : undefined);
7195
+ } else {
7196
+ obj.simulcastCodecs = [];
7197
+ }
7198
+
6959
7199
  return obj;
6960
7200
  },
6961
7201
 
6962
7202
  fromPartial(object) {
6963
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
7203
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
6964
7204
 
6965
7205
  const message = createBaseAddTrackRequest();
6966
7206
  message.cid = (_a = object.cid) !== null && _a !== void 0 ? _a : '';
@@ -6972,6 +7212,7 @@ const AddTrackRequest = {
6972
7212
  message.disableDtx = (_g = object.disableDtx) !== null && _g !== void 0 ? _g : false;
6973
7213
  message.source = (_h = object.source) !== null && _h !== void 0 ? _h : 0;
6974
7214
  message.layers = ((_j = object.layers) === null || _j === void 0 ? void 0 : _j.map(e => VideoLayer.fromPartial(e))) || [];
7215
+ message.simulcastCodecs = ((_k = object.simulcastCodecs) === null || _k === void 0 ? void 0 : _k.map(e => SimulcastCodec.fromPartial(e))) || [];
6975
7216
  return message;
6976
7217
  }
6977
7218
 
@@ -8512,10 +8753,90 @@ const SubscribedQuality = {
8512
8753
 
8513
8754
  };
8514
8755
 
8756
+ function createBaseSubscribedCodec() {
8757
+ return {
8758
+ codec: '',
8759
+ qualities: []
8760
+ };
8761
+ }
8762
+
8763
+ const SubscribedCodec = {
8764
+ encode(message) {
8765
+ let writer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : minimal.Writer.create();
8766
+
8767
+ if (message.codec !== '') {
8768
+ writer.uint32(10).string(message.codec);
8769
+ }
8770
+
8771
+ for (const v of message.qualities) {
8772
+ SubscribedQuality.encode(v, writer.uint32(18).fork()).ldelim();
8773
+ }
8774
+
8775
+ return writer;
8776
+ },
8777
+
8778
+ decode(input, length) {
8779
+ const reader = input instanceof minimal.Reader ? input : new minimal.Reader(input);
8780
+ let end = length === undefined ? reader.len : reader.pos + length;
8781
+ const message = createBaseSubscribedCodec();
8782
+
8783
+ while (reader.pos < end) {
8784
+ const tag = reader.uint32();
8785
+
8786
+ switch (tag >>> 3) {
8787
+ case 1:
8788
+ message.codec = reader.string();
8789
+ break;
8790
+
8791
+ case 2:
8792
+ message.qualities.push(SubscribedQuality.decode(reader, reader.uint32()));
8793
+ break;
8794
+
8795
+ default:
8796
+ reader.skipType(tag & 7);
8797
+ break;
8798
+ }
8799
+ }
8800
+
8801
+ return message;
8802
+ },
8803
+
8804
+ fromJSON(object) {
8805
+ return {
8806
+ codec: isSet(object.codec) ? String(object.codec) : '',
8807
+ qualities: Array.isArray(object === null || object === void 0 ? void 0 : object.qualities) ? object.qualities.map(e => SubscribedQuality.fromJSON(e)) : []
8808
+ };
8809
+ },
8810
+
8811
+ toJSON(message) {
8812
+ const obj = {};
8813
+ message.codec !== undefined && (obj.codec = message.codec);
8814
+
8815
+ if (message.qualities) {
8816
+ obj.qualities = message.qualities.map(e => e ? SubscribedQuality.toJSON(e) : undefined);
8817
+ } else {
8818
+ obj.qualities = [];
8819
+ }
8820
+
8821
+ return obj;
8822
+ },
8823
+
8824
+ fromPartial(object) {
8825
+ var _a, _b;
8826
+
8827
+ const message = createBaseSubscribedCodec();
8828
+ message.codec = (_a = object.codec) !== null && _a !== void 0 ? _a : '';
8829
+ message.qualities = ((_b = object.qualities) === null || _b === void 0 ? void 0 : _b.map(e => SubscribedQuality.fromPartial(e))) || [];
8830
+ return message;
8831
+ }
8832
+
8833
+ };
8834
+
8515
8835
  function createBaseSubscribedQualityUpdate() {
8516
8836
  return {
8517
8837
  trackSid: '',
8518
- subscribedQualities: []
8838
+ subscribedQualities: [],
8839
+ subscribedCodecs: []
8519
8840
  };
8520
8841
  }
8521
8842
 
@@ -8531,6 +8852,10 @@ const SubscribedQualityUpdate = {
8531
8852
  SubscribedQuality.encode(v, writer.uint32(18).fork()).ldelim();
8532
8853
  }
8533
8854
 
8855
+ for (const v of message.subscribedCodecs) {
8856
+ SubscribedCodec.encode(v, writer.uint32(26).fork()).ldelim();
8857
+ }
8858
+
8534
8859
  return writer;
8535
8860
  },
8536
8861
 
@@ -8551,6 +8876,10 @@ const SubscribedQualityUpdate = {
8551
8876
  message.subscribedQualities.push(SubscribedQuality.decode(reader, reader.uint32()));
8552
8877
  break;
8553
8878
 
8879
+ case 3:
8880
+ message.subscribedCodecs.push(SubscribedCodec.decode(reader, reader.uint32()));
8881
+ break;
8882
+
8554
8883
  default:
8555
8884
  reader.skipType(tag & 7);
8556
8885
  break;
@@ -8563,7 +8892,8 @@ const SubscribedQualityUpdate = {
8563
8892
  fromJSON(object) {
8564
8893
  return {
8565
8894
  trackSid: isSet(object.trackSid) ? String(object.trackSid) : '',
8566
- subscribedQualities: Array.isArray(object === null || object === void 0 ? void 0 : object.subscribedQualities) ? object.subscribedQualities.map(e => SubscribedQuality.fromJSON(e)) : []
8895
+ subscribedQualities: Array.isArray(object === null || object === void 0 ? void 0 : object.subscribedQualities) ? object.subscribedQualities.map(e => SubscribedQuality.fromJSON(e)) : [],
8896
+ subscribedCodecs: Array.isArray(object === null || object === void 0 ? void 0 : object.subscribedCodecs) ? object.subscribedCodecs.map(e => SubscribedCodec.fromJSON(e)) : []
8567
8897
  };
8568
8898
  },
8569
8899
 
@@ -8577,15 +8907,22 @@ const SubscribedQualityUpdate = {
8577
8907
  obj.subscribedQualities = [];
8578
8908
  }
8579
8909
 
8910
+ if (message.subscribedCodecs) {
8911
+ obj.subscribedCodecs = message.subscribedCodecs.map(e => e ? SubscribedCodec.toJSON(e) : undefined);
8912
+ } else {
8913
+ obj.subscribedCodecs = [];
8914
+ }
8915
+
8580
8916
  return obj;
8581
8917
  },
8582
8918
 
8583
8919
  fromPartial(object) {
8584
- var _a, _b;
8920
+ var _a, _b, _c;
8585
8921
 
8586
8922
  const message = createBaseSubscribedQualityUpdate();
8587
8923
  message.trackSid = (_a = object.trackSid) !== null && _a !== void 0 ? _a : '';
8588
8924
  message.subscribedQualities = ((_b = object.subscribedQualities) === null || _b === void 0 ? void 0 : _b.map(e => SubscribedQuality.fromPartial(e))) || [];
8925
+ message.subscribedCodecs = ((_c = object.subscribedCodecs) === null || _c === void 0 ? void 0 : _c.map(e => SubscribedCodec.fromPartial(e))) || [];
8589
8926
  return message;
8590
8927
  }
8591
8928
 
@@ -9056,7 +9393,8 @@ function createBaseSimulateScenario() {
9056
9393
  speakerUpdate: undefined,
9057
9394
  nodeFailure: undefined,
9058
9395
  migration: undefined,
9059
- serverLeave: undefined
9396
+ serverLeave: undefined,
9397
+ switchCandidateProtocol: undefined
9060
9398
  };
9061
9399
  }
9062
9400
 
@@ -9080,6 +9418,10 @@ const SimulateScenario = {
9080
9418
  writer.uint32(32).bool(message.serverLeave);
9081
9419
  }
9082
9420
 
9421
+ if (message.switchCandidateProtocol !== undefined) {
9422
+ writer.uint32(40).int32(message.switchCandidateProtocol);
9423
+ }
9424
+
9083
9425
  return writer;
9084
9426
  },
9085
9427
 
@@ -9108,6 +9450,10 @@ const SimulateScenario = {
9108
9450
  message.serverLeave = reader.bool();
9109
9451
  break;
9110
9452
 
9453
+ case 5:
9454
+ message.switchCandidateProtocol = reader.int32();
9455
+ break;
9456
+
9111
9457
  default:
9112
9458
  reader.skipType(tag & 7);
9113
9459
  break;
@@ -9122,7 +9468,8 @@ const SimulateScenario = {
9122
9468
  speakerUpdate: isSet(object.speakerUpdate) ? Number(object.speakerUpdate) : undefined,
9123
9469
  nodeFailure: isSet(object.nodeFailure) ? Boolean(object.nodeFailure) : undefined,
9124
9470
  migration: isSet(object.migration) ? Boolean(object.migration) : undefined,
9125
- serverLeave: isSet(object.serverLeave) ? Boolean(object.serverLeave) : undefined
9471
+ serverLeave: isSet(object.serverLeave) ? Boolean(object.serverLeave) : undefined,
9472
+ switchCandidateProtocol: isSet(object.switchCandidateProtocol) ? candidateProtocolFromJSON(object.switchCandidateProtocol) : undefined
9126
9473
  };
9127
9474
  },
9128
9475
 
@@ -9132,17 +9479,19 @@ const SimulateScenario = {
9132
9479
  message.nodeFailure !== undefined && (obj.nodeFailure = message.nodeFailure);
9133
9480
  message.migration !== undefined && (obj.migration = message.migration);
9134
9481
  message.serverLeave !== undefined && (obj.serverLeave = message.serverLeave);
9482
+ message.switchCandidateProtocol !== undefined && (obj.switchCandidateProtocol = message.switchCandidateProtocol !== undefined ? candidateProtocolToJSON(message.switchCandidateProtocol) : undefined);
9135
9483
  return obj;
9136
9484
  },
9137
9485
 
9138
9486
  fromPartial(object) {
9139
- var _a, _b, _c, _d;
9487
+ var _a, _b, _c, _d, _e;
9140
9488
 
9141
9489
  const message = createBaseSimulateScenario();
9142
9490
  message.speakerUpdate = (_a = object.speakerUpdate) !== null && _a !== void 0 ? _a : undefined;
9143
9491
  message.nodeFailure = (_b = object.nodeFailure) !== null && _b !== void 0 ? _b : undefined;
9144
9492
  message.migration = (_c = object.migration) !== null && _c !== void 0 ? _c : undefined;
9145
9493
  message.serverLeave = (_d = object.serverLeave) !== null && _d !== void 0 ? _d : undefined;
9494
+ message.switchCandidateProtocol = (_e = object.switchCandidateProtocol) !== null && _e !== void 0 ? _e : undefined;
9146
9495
  return message;
9147
9496
  }
9148
9497
 
@@ -9260,10 +9609,15 @@ var RoomEvent;
9260
9609
  /**
9261
9610
  * Whenever the connection state of the room changes
9262
9611
  *
9263
- * args: ([[RoomState]])
9612
+ * args: ([[ConnectionState]])
9613
+ */
9614
+
9615
+ RoomEvent["ConnectionStateChanged"] = "connectionStateChanged";
9616
+ /**
9617
+ * @deprecated StateChanged has been renamed to ConnectionStateChanged
9264
9618
  */
9265
9619
 
9266
- RoomEvent["StateChanged"] = "stateChanged";
9620
+ RoomEvent["StateChanged"] = "connectionStateChanged";
9267
9621
  /**
9268
9622
  * When input or output devices on the machine have changed.
9269
9623
  */
@@ -9370,12 +9724,6 @@ var RoomEvent;
9370
9724
  */
9371
9725
 
9372
9726
  RoomEvent["ActiveSpeakersChanged"] = "activeSpeakersChanged";
9373
- /**
9374
- * @deprecated Use ParticipantMetadataChanged instead
9375
- * @internal
9376
- */
9377
-
9378
- RoomEvent["MetadataChanged"] = "metadataChanged";
9379
9727
  /**
9380
9728
  * Participant metadata is a simple way for app-specific state to be pushed to
9381
9729
  * all users.
@@ -9463,6 +9811,11 @@ var RoomEvent;
9463
9811
  */
9464
9812
 
9465
9813
  RoomEvent["ParticipantPermissionsChanged"] = "participantPermissionsChanged";
9814
+ /**
9815
+ * Signal connected, can publish tracks.
9816
+ */
9817
+
9818
+ RoomEvent["SignalConnected"] = "signalConnected";
9466
9819
  })(RoomEvent || (RoomEvent = {}));
9467
9820
 
9468
9821
  var ParticipantEvent;
@@ -9541,12 +9894,6 @@ var ParticipantEvent;
9541
9894
  */
9542
9895
 
9543
9896
  ParticipantEvent["LocalTrackUnpublished"] = "localTrackUnpublished";
9544
- /**
9545
- * @deprecated Use ParticipantMetadataChanged instead
9546
- * @internal
9547
- */
9548
-
9549
- ParticipantEvent["MetadataChanged"] = "metadataChanged";
9550
9897
  /**
9551
9898
  * Participant metadata is a simple way for app-specific state to be pushed to
9552
9899
  * all users.
@@ -9711,80 +10058,10 @@ function computeBitrate(currentStats, prevStats) {
9711
10058
  return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
9712
10059
  }
9713
10060
 
9714
- const defaultId = 'default';
9715
- class DeviceManager {
9716
- static getInstance() {
9717
- if (this.instance === undefined) {
9718
- this.instance = new DeviceManager();
9719
- }
9720
-
9721
- return this.instance;
9722
- }
9723
-
9724
- async getDevices(kind) {
9725
- let requestPermissions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
9726
- let devices = await navigator.mediaDevices.enumerateDevices();
9727
-
9728
- if (requestPermissions) {
9729
- const isDummyDeviceOrEmpty = devices.length === 0 || devices.some(device => {
9730
- const noLabel = device.label === '';
9731
- const isRelevant = kind ? device.kind === kind : true;
9732
- return noLabel && isRelevant;
9733
- });
9734
-
9735
- if (isDummyDeviceOrEmpty) {
9736
- const permissionsToAcquire = {
9737
- video: kind !== 'audioinput' && kind !== 'audiooutput',
9738
- audio: kind !== 'videoinput'
9739
- };
9740
- await navigator.mediaDevices.getUserMedia(permissionsToAcquire);
9741
- devices = await navigator.mediaDevices.enumerateDevices();
9742
- }
9743
- }
9744
-
9745
- if (kind) {
9746
- devices = devices.filter(device => device.kind === kind);
9747
- } // Chrome returns 'default' devices, we would filter them out, but put the default
9748
- // device at first
9749
- // we would only do this if there are more than 1 device though
9750
-
9751
-
9752
- if (devices.length > 1 && devices[0].deviceId === defaultId) {
9753
- // find another device with matching group id, and move that to 0
9754
- const defaultDevice = devices[0];
9755
-
9756
- for (let i = 1; i < devices.length; i += 1) {
9757
- if (devices[i].groupId === defaultDevice.groupId) {
9758
- const temp = devices[0];
9759
- devices[0] = devices[i];
9760
- devices[i] = temp;
9761
- break;
9762
- }
9763
- }
9764
-
9765
- return devices.filter(device => device !== defaultDevice);
9766
- }
9767
-
9768
- return devices;
9769
- }
9770
-
9771
- async normalizeDeviceId(kind, deviceId, groupId) {
9772
- if (deviceId !== defaultId) {
9773
- return deviceId;
9774
- } // resolve actual device id if it's 'default': Chrome returns it when no
9775
- // device has been chosen
9776
-
9777
-
9778
- const devices = await this.getDevices(kind);
9779
- const device = devices.find(d => d.groupId === groupId && d.deviceId !== defaultId);
9780
- return device === null || device === void 0 ? void 0 : device.deviceId;
9781
- }
9782
-
9783
- }
9784
- DeviceManager.mediaDeviceKinds = ['audioinput', 'audiooutput', 'videoinput'];
10061
+ var version$1 = "1.0.2";
9785
10062
 
9786
- const version = '0.18.6';
9787
- const protocolVersion = 7;
10063
+ const version = version$1;
10064
+ const protocolVersion = 8;
9788
10065
 
9789
10066
  const separator = '|';
9790
10067
  function unpackStreamId(packed) {
@@ -9891,6 +10168,81 @@ function getEmptyAudioStreamTrack() {
9891
10168
  return emptyAudioStreamTrack;
9892
10169
  }
9893
10170
 
10171
+ const defaultId = 'default';
10172
+ class DeviceManager {
10173
+ static getInstance() {
10174
+ if (this.instance === undefined) {
10175
+ this.instance = new DeviceManager();
10176
+ }
10177
+
10178
+ return this.instance;
10179
+ }
10180
+
10181
+ async getDevices(kind) {
10182
+ let requestPermissions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
10183
+ let devices = await navigator.mediaDevices.enumerateDevices();
10184
+
10185
+ if (requestPermissions) {
10186
+ const isDummyDeviceOrEmpty = devices.length === 0 || devices.some(device => {
10187
+ const noLabel = device.label === '';
10188
+ const isRelevant = kind ? device.kind === kind : true;
10189
+ return noLabel && isRelevant;
10190
+ });
10191
+
10192
+ if (isDummyDeviceOrEmpty) {
10193
+ const permissionsToAcquire = {
10194
+ video: kind !== 'audioinput' && kind !== 'audiooutput',
10195
+ audio: kind !== 'videoinput'
10196
+ };
10197
+ const stream = await navigator.mediaDevices.getUserMedia(permissionsToAcquire);
10198
+ devices = await navigator.mediaDevices.enumerateDevices();
10199
+ stream.getTracks().forEach(track => {
10200
+ track.stop();
10201
+ });
10202
+ }
10203
+ }
10204
+
10205
+ if (kind) {
10206
+ devices = devices.filter(device => device.kind === kind);
10207
+ } // Chrome returns 'default' devices, we would filter them out, but put the default
10208
+ // device at first
10209
+ // we would only do this if there are more than 1 device though
10210
+
10211
+
10212
+ if (devices.length > 1 && devices[0].deviceId === defaultId) {
10213
+ // find another device with matching group id, and move that to 0
10214
+ const defaultDevice = devices[0];
10215
+
10216
+ for (let i = 1; i < devices.length; i += 1) {
10217
+ if (devices[i].groupId === defaultDevice.groupId) {
10218
+ const temp = devices[0];
10219
+ devices[0] = devices[i];
10220
+ devices[i] = temp;
10221
+ break;
10222
+ }
10223
+ }
10224
+
10225
+ return devices.filter(device => device !== defaultDevice);
10226
+ }
10227
+
10228
+ return devices;
10229
+ }
10230
+
10231
+ async normalizeDeviceId(kind, deviceId, groupId) {
10232
+ if (deviceId !== defaultId) {
10233
+ return deviceId;
10234
+ } // resolve actual device id if it's 'default': Chrome returns it when no
10235
+ // device has been chosen
10236
+
10237
+
10238
+ const devices = await this.getDevices(kind);
10239
+ const device = devices.find(d => d.groupId === groupId && d.deviceId !== defaultId);
10240
+ return device === null || device === void 0 ? void 0 : device.deviceId;
10241
+ }
10242
+
10243
+ }
10244
+ DeviceManager.mediaDeviceKinds = ['audioinput', 'audiooutput', 'videoinput'];
10245
+
9894
10246
  var events = {exports: {}};
9895
10247
 
9896
10248
  var R = typeof Reflect === 'object' ? Reflect : null;
@@ -10336,6 +10688,7 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
10336
10688
  }
10337
10689
  }
10338
10690
 
10691
+ const BACKGROUND_REACTION_DELAY = 5000; // keep old audio elements when detached, we would re-use them since on iOS
10339
10692
  // Safari tracks which audio elements have been "blessed" by the user.
10340
10693
 
10341
10694
  const recycledElements = [];
@@ -10344,10 +10697,25 @@ class Track extends events.exports.EventEmitter {
10344
10697
  super();
10345
10698
  this.attachedElements = [];
10346
10699
  this.isMuted = false;
10700
+ /**
10701
+ * indicates current state of stream
10702
+ */
10703
+
10704
+ this.streamState = Track.StreamState.Active;
10347
10705
  this._currentBitrate = 0;
10348
10706
 
10349
10707
  this.appVisibilityChangedListener = () => {
10350
- this.handleAppVisibilityChanged();
10708
+ if (this.backgroundTimeout) {
10709
+ clearTimeout(this.backgroundTimeout);
10710
+ } // delay app visibility update if it goes to hidden
10711
+ // update immediately if it comes back to focus
10712
+
10713
+
10714
+ if (document.visibilityState === 'hidden') {
10715
+ this.backgroundTimeout = setTimeout(() => this.handleAppVisibilityChanged(), BACKGROUND_REACTION_DELAY);
10716
+ } else {
10717
+ this.handleAppVisibilityChanged();
10718
+ }
10351
10719
  };
10352
10720
 
10353
10721
  this.kind = kind;
@@ -10773,7 +11141,11 @@ class LocalTrack extends Track {
10773
11141
 
10774
11142
  track.addEventListener('ended', this.handleEnded);
10775
11143
  livekitLogger.debug('replace MediaStreamTrack');
10776
- await this.sender.replaceTrack(track);
11144
+
11145
+ if (this.sender) {
11146
+ await this.sender.replaceTrack(track);
11147
+ }
11148
+
10777
11149
  this._mediaStreamTrack = track;
10778
11150
  this.attachedElements.forEach(el => {
10779
11151
  attachToElement(track, el);
@@ -10783,10 +11155,6 @@ class LocalTrack extends Track {
10783
11155
  }
10784
11156
 
10785
11157
  async restart(constraints) {
10786
- if (!this.sender) {
10787
- throw new TrackInvalidError('unable to restart an unpublished track');
10788
- }
10789
-
10790
11158
  if (!constraints) {
10791
11159
  constraints = this.constraints;
10792
11160
  }
@@ -10820,7 +11188,12 @@ class LocalTrack extends Track {
10820
11188
  const newTrack = mediaStream.getTracks()[0];
10821
11189
  newTrack.addEventListener('ended', this.handleEnded);
10822
11190
  livekitLogger.debug('re-acquired MediaStreamTrack');
10823
- await this.sender.replaceTrack(newTrack);
11191
+
11192
+ if (this.sender) {
11193
+ // Track can be restarted after it's unpublished
11194
+ await this.sender.replaceTrack(newTrack);
11195
+ }
11196
+
10824
11197
  this._mediaStreamTrack = newTrack;
10825
11198
  this.attachedElements.forEach(el => {
10826
11199
  attachToElement(newTrack, el);
@@ -11094,6 +11467,10 @@ class LocalAudioTrack extends LocalTrack {
11094
11467
 
11095
11468
 
11096
11469
  startMonitor() {
11470
+ if (!isWeb()) {
11471
+ return;
11472
+ }
11473
+
11097
11474
  setTimeout(() => {
11098
11475
  this.monitorSender();
11099
11476
  }, monitorFrequency);
@@ -11140,6 +11517,7 @@ class LocalAudioTrack extends LocalTrack {
11140
11517
  class LocalVideoTrack extends LocalTrack {
11141
11518
  constructor(mediaTrack, constraints) {
11142
11519
  super(mediaTrack, Track.Kind.Video, constraints);
11520
+ this.simulcastCodecs = new Map();
11143
11521
 
11144
11522
  this.monitorSender = async () => {
11145
11523
  if (!this.sender) {
@@ -11191,7 +11569,13 @@ class LocalVideoTrack extends LocalTrack {
11191
11569
  startMonitor(signalClient) {
11192
11570
  var _a;
11193
11571
 
11194
- this.signalClient = signalClient; // save original encodings
11572
+ this.signalClient = signalClient;
11573
+
11574
+ if (!isWeb()) {
11575
+ return;
11576
+ } // save original encodings
11577
+ // TODO : merge simulcast tracks stats
11578
+
11195
11579
 
11196
11580
  const params = (_a = this.sender) === null || _a === void 0 ? void 0 : _a.getParameters();
11197
11581
 
@@ -11209,6 +11593,11 @@ class LocalVideoTrack extends LocalTrack {
11209
11593
 
11210
11594
  this._mediaStreamTrack.getConstraints();
11211
11595
 
11596
+ this.simulcastCodecs.forEach(trackInfo => {
11597
+ trackInfo.mediaStreamTrack.stop();
11598
+ trackInfo.sender = undefined;
11599
+ });
11600
+ this.simulcastCodecs.clear();
11212
11601
  super.stop();
11213
11602
  }
11214
11603
 
@@ -11256,7 +11645,7 @@ class LocalVideoTrack extends LocalTrack {
11256
11645
  bytesSent: v.bytesSent,
11257
11646
  framesSent: v.framesSent,
11258
11647
  timestamp: v.timestamp,
11259
- rid: (_a = v.rid) !== null && _a !== void 0 ? _a : '',
11648
+ rid: (_a = v.rid) !== null && _a !== void 0 ? _a : v.id,
11260
11649
  retransmittedPacketsSent: v.retransmittedPacketsSent,
11261
11650
  qualityLimitationReason: v.qualityLimitationReason,
11262
11651
  qualityLimitationResolutionChanges: v.qualityLimitationResolutionChanges
@@ -11318,6 +11707,58 @@ class LocalVideoTrack extends LocalTrack {
11318
11707
 
11319
11708
  await this.restart(constraints);
11320
11709
  }
11710
+
11711
+ addSimulcastTrack(codec, encodings) {
11712
+ if (this.simulcastCodecs.has(codec)) {
11713
+ throw new Error("".concat(codec, " already added"));
11714
+ }
11715
+
11716
+ const simulcastCodecInfo = {
11717
+ codec,
11718
+ mediaStreamTrack: this.mediaStreamTrack.clone(),
11719
+ sender: undefined,
11720
+ encodings
11721
+ };
11722
+ this.simulcastCodecs.set(codec, simulcastCodecInfo);
11723
+ return simulcastCodecInfo;
11724
+ }
11725
+
11726
+ setSimulcastTrackSender(codec, sender) {
11727
+ const simulcastCodecInfo = this.simulcastCodecs.get(codec);
11728
+
11729
+ if (!simulcastCodecInfo) {
11730
+ return;
11731
+ }
11732
+
11733
+ simulcastCodecInfo.sender = sender;
11734
+ }
11735
+ /**
11736
+ * @internal
11737
+ * Sets codecs that should be publishing
11738
+ */
11739
+
11740
+
11741
+ async setPublishingCodecs(codecs) {
11742
+ livekitLogger.debug('setting publishing codecs', codecs);
11743
+
11744
+ for await (const codec of codecs) {
11745
+ if (this.codec === codec.codec) {
11746
+ await this.setPublishingLayers(codec.qualities);
11747
+ } else {
11748
+ const simulcastCodecInfo = this.simulcastCodecs.get(codec.codec);
11749
+ livekitLogger.debug("try setPublishingCodec for ".concat(codec.codec), simulcastCodecInfo);
11750
+
11751
+ if (!simulcastCodecInfo || !simulcastCodecInfo.sender) {
11752
+ return;
11753
+ }
11754
+
11755
+ if (simulcastCodecInfo.encodings) {
11756
+ livekitLogger.debug("try setPublishingLayersForSender ".concat(codec.codec));
11757
+ await setPublishingLayersForSender(simulcastCodecInfo.sender, simulcastCodecInfo.encodings, codec.qualities);
11758
+ }
11759
+ }
11760
+ }
11761
+ }
11321
11762
  /**
11322
11763
  * @internal
11323
11764
  * Sets layers that should be publishing
@@ -11331,77 +11772,87 @@ class LocalVideoTrack extends LocalTrack {
11331
11772
  return;
11332
11773
  }
11333
11774
 
11334
- const params = this.sender.getParameters();
11335
- const {
11336
- encodings
11337
- } = params;
11775
+ await setPublishingLayersForSender(this.sender, this.encodings, qualities);
11776
+ }
11338
11777
 
11339
- if (!encodings) {
11340
- return;
11341
- }
11778
+ async handleAppVisibilityChanged() {
11779
+ await super.handleAppVisibilityChanged();
11780
+ if (!isMobile()) return;
11342
11781
 
11343
- if (encodings.length !== this.encodings.length) {
11344
- livekitLogger.warn('cannot set publishing layers, encodings mismatch');
11345
- return;
11782
+ if (this.isInBackground && this.source === Track.Source.Camera) {
11783
+ this._mediaStreamTrack.enabled = false;
11346
11784
  }
11785
+ }
11347
11786
 
11348
- let hasChanged = false;
11349
- encodings.forEach((encoding, idx) => {
11350
- var _a;
11351
-
11352
- let rid = (_a = encoding.rid) !== null && _a !== void 0 ? _a : '';
11787
+ }
11353
11788
 
11354
- if (rid === '') {
11355
- rid = 'q';
11356
- }
11789
+ async function setPublishingLayersForSender(sender, senderEncodings, qualities) {
11790
+ livekitLogger.debug('setPublishingLayersForSender', {
11791
+ sender,
11792
+ qualities,
11793
+ senderEncodings
11794
+ });
11795
+ const params = sender.getParameters();
11796
+ const {
11797
+ encodings
11798
+ } = params;
11357
11799
 
11358
- const quality = videoQualityForRid(rid);
11359
- const subscribedQuality = qualities.find(q => q.quality === quality);
11800
+ if (!encodings) {
11801
+ return;
11802
+ }
11360
11803
 
11361
- if (!subscribedQuality) {
11362
- return;
11363
- }
11804
+ if (encodings.length !== senderEncodings.length) {
11805
+ livekitLogger.warn('cannot set publishing layers, encodings mismatch');
11806
+ return;
11807
+ }
11364
11808
 
11365
- if (encoding.active !== subscribedQuality.enabled) {
11366
- hasChanged = true;
11367
- encoding.active = subscribedQuality.enabled;
11368
- livekitLogger.debug("setting layer ".concat(subscribedQuality.quality, " to ").concat(encoding.active ? 'enabled' : 'disabled')); // FireFox does not support setting encoding.active to false, so we
11369
- // have a workaround of lowering its bitrate and resolution to the min.
11809
+ let hasChanged = false;
11810
+ encodings.forEach((encoding, idx) => {
11811
+ var _a;
11370
11812
 
11371
- if (isFireFox()) {
11372
- if (subscribedQuality.enabled) {
11373
- encoding.scaleResolutionDownBy = this.encodings[idx].scaleResolutionDownBy;
11374
- encoding.maxBitrate = this.encodings[idx].maxBitrate;
11375
- /* @ts-ignore */
11813
+ let rid = (_a = encoding.rid) !== null && _a !== void 0 ? _a : '';
11376
11814
 
11377
- encoding.maxFrameRate = this.encodings[idx].maxFrameRate;
11378
- } else {
11379
- encoding.scaleResolutionDownBy = 4;
11380
- encoding.maxBitrate = 10;
11381
- /* @ts-ignore */
11815
+ if (rid === '') {
11816
+ rid = 'q';
11817
+ }
11382
11818
 
11383
- encoding.maxFrameRate = 2;
11384
- }
11385
- }
11386
- }
11387
- });
11819
+ const quality = videoQualityForRid(rid);
11820
+ const subscribedQuality = qualities.find(q => q.quality === quality);
11388
11821
 
11389
- if (hasChanged) {
11390
- params.encodings = encodings;
11391
- await this.sender.setParameters(params);
11822
+ if (!subscribedQuality) {
11823
+ return;
11392
11824
  }
11393
- }
11394
11825
 
11395
- async handleAppVisibilityChanged() {
11396
- await super.handleAppVisibilityChanged();
11397
- if (!isMobile()) return;
11826
+ if (encoding.active !== subscribedQuality.enabled) {
11827
+ hasChanged = true;
11828
+ encoding.active = subscribedQuality.enabled;
11829
+ livekitLogger.debug("setting layer ".concat(subscribedQuality.quality, " to ").concat(encoding.active ? 'enabled' : 'disabled')); // FireFox does not support setting encoding.active to false, so we
11830
+ // have a workaround of lowering its bitrate and resolution to the min.
11398
11831
 
11399
- if (this.isInBackground && this.source === Track.Source.Camera) {
11400
- this._mediaStreamTrack.enabled = false;
11832
+ if (isFireFox()) {
11833
+ if (subscribedQuality.enabled) {
11834
+ encoding.scaleResolutionDownBy = senderEncodings[idx].scaleResolutionDownBy;
11835
+ encoding.maxBitrate = senderEncodings[idx].maxBitrate;
11836
+ /* @ts-ignore */
11837
+
11838
+ encoding.maxFrameRate = senderEncodings[idx].maxFrameRate;
11839
+ } else {
11840
+ encoding.scaleResolutionDownBy = 4;
11841
+ encoding.maxBitrate = 10;
11842
+ /* @ts-ignore */
11843
+
11844
+ encoding.maxFrameRate = 2;
11845
+ }
11846
+ }
11401
11847
  }
11402
- }
11848
+ });
11403
11849
 
11850
+ if (hasChanged) {
11851
+ params.encodings = encodings;
11852
+ await sender.setParameters(params);
11853
+ }
11404
11854
  }
11855
+
11405
11856
  function videoQualityForRid(rid) {
11406
11857
  switch (rid) {
11407
11858
  case 'f':
@@ -11452,7 +11903,6 @@ function videoLayersFromEncodings(width, height, encodings) {
11452
11903
  class RemoteTrack extends Track {
11453
11904
  constructor(mediaTrack, sid, kind, receiver) {
11454
11905
  super(mediaTrack, kind);
11455
- this.streamState = Track.StreamState.Active;
11456
11906
  this.sid = sid;
11457
11907
  this.receiver = receiver;
11458
11908
  }
@@ -11661,21 +12111,6 @@ class RemoteVideoTrack extends RemoteTrack {
11661
12111
  }, monitorFrequency);
11662
12112
  };
11663
12113
 
11664
- this.handleVisibilityChanged = entry => {
11665
- const {
11666
- target,
11667
- isIntersecting
11668
- } = entry;
11669
- const elementInfo = this.elementInfos.find(info => info.element === target);
11670
-
11671
- if (elementInfo) {
11672
- elementInfo.visible = isIntersecting;
11673
- elementInfo.visibilityChangedAt = Date.now();
11674
- }
11675
-
11676
- this.updateVisibility();
11677
- };
11678
-
11679
12114
  this.debouncedHandleResize = r(() => {
11680
12115
  this.updateDimensions();
11681
12116
  }, REACTION_DELAY);
@@ -11722,23 +12157,55 @@ class RemoteVideoTrack extends RemoteTrack {
11722
12157
 
11723
12158
 
11724
12159
  if (this.adaptiveStreamSettings && this.elementInfos.find(info => info.element === element) === undefined) {
11725
- this.elementInfos.push({
11726
- element,
11727
- visible: true // default visible
12160
+ const elementInfo = new HTMLElementInfo(element);
12161
+ this.observeElementInfo(elementInfo);
12162
+ }
11728
12163
 
11729
- });
11730
- element.handleResize = this.debouncedHandleResize;
11731
- element.handleVisibilityChanged = this.handleVisibilityChanged;
11732
- getIntersectionObserver().observe(element);
11733
- getResizeObserver().observe(element); // trigger the first resize update cycle
12164
+ this.hasUsedAttach = true;
12165
+ return element;
12166
+ }
12167
+ /**
12168
+ * Observe an ElementInfo for changes when adaptive streaming.
12169
+ * @param elementInfo
12170
+ * @internal
12171
+ */
12172
+
12173
+
12174
+ observeElementInfo(elementInfo) {
12175
+ if (this.adaptiveStreamSettings && this.elementInfos.find(info => info === elementInfo) === undefined) {
12176
+ elementInfo.handleResize = () => {
12177
+ this.debouncedHandleResize();
12178
+ };
12179
+
12180
+ elementInfo.handleVisibilityChanged = () => {
12181
+ this.updateVisibility();
12182
+ };
12183
+
12184
+ this.elementInfos.push(elementInfo);
12185
+ elementInfo.observe(); // trigger the first resize update cycle
11734
12186
  // if the tab is backgrounded, the initial resize event does not fire until
11735
12187
  // the tab comes into focus for the first time.
11736
12188
 
11737
12189
  this.debouncedHandleResize();
12190
+ this.updateVisibility();
12191
+ }
12192
+ }
12193
+ /**
12194
+ * Stop observing an ElementInfo for changes.
12195
+ * @param elementInfo
12196
+ * @internal
12197
+ */
12198
+
12199
+
12200
+ stopObservingElementInfo(elementInfo) {
12201
+ const stopElementInfos = this.elementInfos.filter(info => info === elementInfo);
12202
+
12203
+ for (const info of stopElementInfos) {
12204
+ info.stopObserving();
11738
12205
  }
11739
12206
 
11740
- this.hasUsedAttach = true;
11741
- return element;
12207
+ this.elementInfos = this.elementInfos.filter(info => info !== elementInfo);
12208
+ this.updateVisibility();
11742
12209
  }
11743
12210
 
11744
12211
  detach(element) {
@@ -11757,6 +12224,14 @@ class RemoteVideoTrack extends RemoteTrack {
11757
12224
 
11758
12225
  return detachedElements;
11759
12226
  }
12227
+ /** @internal */
12228
+
12229
+
12230
+ getDecoderImplementation() {
12231
+ var _a;
12232
+
12233
+ return (_a = this.prevStats) === null || _a === void 0 ? void 0 : _a.decoderImplementation;
12234
+ }
11760
12235
 
11761
12236
  async getReceiverStats() {
11762
12237
  if (!this.receiver) {
@@ -11781,7 +12256,8 @@ class RemoteVideoTrack extends RemoteTrack {
11781
12256
  nackCount: v.nackCount,
11782
12257
  jitter: v.jitter,
11783
12258
  timestamp: v.timestamp,
11784
- bytesReceived: v.bytesReceived
12259
+ bytesReceived: v.bytesReceived,
12260
+ decoderImplementation: v.decoderImplementation
11785
12261
  };
11786
12262
  }
11787
12263
  });
@@ -11789,24 +12265,28 @@ class RemoteVideoTrack extends RemoteTrack {
11789
12265
  }
11790
12266
 
11791
12267
  stopObservingElement(element) {
11792
- var _a, _b;
12268
+ const stopElementInfos = this.elementInfos.filter(info => info.element === element);
12269
+
12270
+ for (const info of stopElementInfos) {
12271
+ info.stopObserving();
12272
+ }
11793
12273
 
11794
- (_a = getIntersectionObserver()) === null || _a === void 0 ? void 0 : _a.unobserve(element);
11795
- (_b = getResizeObserver()) === null || _b === void 0 ? void 0 : _b.unobserve(element);
11796
12274
  this.elementInfos = this.elementInfos.filter(info => info.element !== element);
11797
12275
  }
11798
12276
 
11799
12277
  async handleAppVisibilityChanged() {
11800
12278
  await super.handleAppVisibilityChanged();
11801
- if (!this.isAdaptiveStream) return; // on desktop don't pause when tab is backgrounded
11802
-
11803
- if (!isMobile()) return;
12279
+ if (!this.isAdaptiveStream) return;
11804
12280
  this.updateVisibility();
11805
12281
  }
11806
12282
 
11807
12283
  updateVisibility() {
12284
+ var _a, _b;
12285
+
11808
12286
  const lastVisibilityChange = this.elementInfos.reduce((prev, info) => Math.max(prev, info.visibilityChangedAt || 0), 0);
11809
- const isVisible = this.elementInfos.some(info => info.visible) && !this.isInBackground;
12287
+ const backgroundPause = ((_b = (_a = this.adaptiveStreamSettings) === null || _a === void 0 ? void 0 : _a.pauseVideoInBackground) !== null && _b !== void 0 ? _b : true // default to true
12288
+ ) ? this.isInBackground : false;
12289
+ const isVisible = this.elementInfos.some(info => info.visible) && !backgroundPause;
11810
12290
 
11811
12291
  if (this.lastVisible === isVisible) {
11812
12292
  return;
@@ -11833,8 +12313,8 @@ class RemoteVideoTrack extends RemoteTrack {
11833
12313
  for (const info of this.elementInfos) {
11834
12314
  const pixelDensity = (_b = (_a = this.adaptiveStreamSettings) === null || _a === void 0 ? void 0 : _a.pixelDensity) !== null && _b !== void 0 ? _b : 1;
11835
12315
  const pixelDensityValue = pixelDensity === 'screen' ? window.devicePixelRatio : pixelDensity;
11836
- const currentElementWidth = info.element.clientWidth * pixelDensityValue;
11837
- const currentElementHeight = info.element.clientHeight * pixelDensityValue;
12316
+ const currentElementWidth = info.width() * pixelDensityValue;
12317
+ const currentElementHeight = info.height() * pixelDensityValue;
11838
12318
 
11839
12319
  if (currentElementWidth + currentElementHeight > maxWidth + maxHeight) {
11840
12320
  maxWidth = currentElementWidth;
@@ -11855,6 +12335,59 @@ class RemoteVideoTrack extends RemoteTrack {
11855
12335
 
11856
12336
  }
11857
12337
 
12338
+ class HTMLElementInfo {
12339
+ constructor(element) {
12340
+ let visible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
12341
+
12342
+ this.onVisibilityChanged = entry => {
12343
+ var _a;
12344
+
12345
+ const {
12346
+ target,
12347
+ isIntersecting
12348
+ } = entry;
12349
+
12350
+ if (target === this.element) {
12351
+ this.visible = isIntersecting;
12352
+ this.visibilityChangedAt = Date.now();
12353
+ (_a = this.handleVisibilityChanged) === null || _a === void 0 ? void 0 : _a.call(this);
12354
+ }
12355
+ };
12356
+
12357
+ this.element = element;
12358
+ this.visible = visible;
12359
+ this.visibilityChangedAt = 0;
12360
+ }
12361
+
12362
+ width() {
12363
+ return this.element.clientWidth;
12364
+ }
12365
+
12366
+ height() {
12367
+ return this.element.clientWidth;
12368
+ }
12369
+
12370
+ observe() {
12371
+ this.element.handleResize = () => {
12372
+ var _a;
12373
+
12374
+ (_a = this.handleResize) === null || _a === void 0 ? void 0 : _a.call(this);
12375
+ };
12376
+
12377
+ this.element.handleVisibilityChanged = this.onVisibilityChanged;
12378
+ getIntersectionObserver().observe(this.element);
12379
+ getResizeObserver().observe(this.element);
12380
+ }
12381
+
12382
+ stopObserving() {
12383
+ var _a, _b;
12384
+
12385
+ (_a = getIntersectionObserver()) === null || _a === void 0 ? void 0 : _a.unobserve(this.element);
12386
+ (_b = getResizeObserver()) === null || _b === void 0 ? void 0 : _b.unobserve(this.element);
12387
+ }
12388
+
12389
+ }
12390
+
11858
12391
  class TrackPublication extends events.exports.EventEmitter {
11859
12392
  constructor(kind, id, name) {
11860
12393
  super();
@@ -12092,22 +12625,7 @@ const VideoPresets = {
12092
12625
  h720: new VideoPreset(1280, 720, 1700000, 30),
12093
12626
  h1080: new VideoPreset(1920, 1080, 3000000, 30),
12094
12627
  h1440: new VideoPreset(2560, 1440, 5000000, 30),
12095
- h2160: new VideoPreset(3840, 2160, 8000000, 30),
12096
-
12097
- /** @deprecated */
12098
- qvga: new VideoPreset(320, 180, 120000, 10),
12099
-
12100
- /** @deprecated */
12101
- vga: new VideoPreset(640, 360, 300000, 20),
12102
-
12103
- /** @deprecated */
12104
- qhd: new VideoPreset(960, 540, 600000, 25),
12105
-
12106
- /** @deprecated */
12107
- hd: new VideoPreset(1280, 720, 1700000, 30),
12108
-
12109
- /** @deprecated */
12110
- fhd: new VideoPreset(1920, 1080, 3000000, 30)
12628
+ h2160: new VideoPreset(3840, 2160, 8000000, 30)
12111
12629
  };
12112
12630
  /**
12113
12631
  * Four by three presets
@@ -12122,44 +12640,14 @@ const VideoPresets43 = {
12122
12640
  h540: new VideoPreset(720, 540, 450000, 25),
12123
12641
  h720: new VideoPreset(960, 720, 1500000, 30),
12124
12642
  h1080: new VideoPreset(1440, 1080, 2500000, 30),
12125
- h1440: new VideoPreset(1920, 1440, 3500000, 30),
12126
-
12127
- /** @deprecated */
12128
- qvga: new VideoPreset(240, 180, 90000, 10),
12129
-
12130
- /** @deprecated */
12131
- vga: new VideoPreset(480, 360, 225000, 20),
12132
-
12133
- /** @deprecated */
12134
- qhd: new VideoPreset(720, 540, 450000, 25),
12135
-
12136
- /** @deprecated */
12137
- hd: new VideoPreset(960, 720, 1500000, 30),
12138
-
12139
- /** @deprecated */
12140
- fhd: new VideoPreset(1440, 1080, 2800000, 30)
12643
+ h1440: new VideoPreset(1920, 1440, 3500000, 30)
12141
12644
  };
12142
12645
  const ScreenSharePresets = {
12143
12646
  h360fps3: new VideoPreset(640, 360, 200000, 3),
12144
12647
  h720fps5: new VideoPreset(1280, 720, 400000, 5),
12145
12648
  h720fps15: new VideoPreset(1280, 720, 1000000, 15),
12146
12649
  h1080fps15: new VideoPreset(1920, 1080, 1500000, 15),
12147
- h1080fps30: new VideoPreset(1920, 1080, 3000000, 30),
12148
-
12149
- /** @deprecated */
12150
- vga: new VideoPreset(640, 360, 200000, 3),
12151
-
12152
- /** @deprecated */
12153
- hd_8: new VideoPreset(1280, 720, 400000, 5),
12154
-
12155
- /** @deprecated */
12156
- hd_15: new VideoPreset(1280, 720, 1000000, 15),
12157
-
12158
- /** @deprecated */
12159
- fhd_15: new VideoPreset(1920, 1080, 1500000, 15),
12160
-
12161
- /** @deprecated */
12162
- fhd_30: new VideoPreset(1920, 1080, 3000000, 30)
12650
+ h1080fps30: new VideoPreset(1920, 1080, 3000000, 30)
12163
12651
  };
12164
12652
 
12165
12653
  var ConnectionQuality;
@@ -12317,7 +12805,6 @@ class Participant extends events.exports.EventEmitter {
12317
12805
  this.metadata = md;
12318
12806
 
12319
12807
  if (changed) {
12320
- this.emit(ParticipantEvent.MetadataChanged, prevMetadata);
12321
12808
  this.emit(ParticipantEvent.ParticipantMetadataChanged, prevMetadata);
12322
12809
  }
12323
12810
  }
@@ -12880,6 +13367,7 @@ class RemoteParticipant extends Participant {
12880
13367
  super.addTrackPublication(publication); // register action events
12881
13368
 
12882
13369
  publication.on(TrackEvent.UpdateSettings, settings => {
13370
+ livekitLogger.debug('send update settings', settings);
12883
13371
  this.signalClient.sendUpdateTrackSettings(settings);
12884
13372
  });
12885
13373
  publication.on(TrackEvent.UpdateSubscription, sub => {
@@ -12909,29 +13397,32 @@ class RemoteParticipant extends Participant {
12909
13397
  }
12910
13398
  }
12911
13399
  /**
12912
- * sets the volume on the participant's microphone track if it exists.
13400
+ * sets the volume on the participant's microphone track
13401
+ * if no track exists the volume will be applied when the microphone track is added
12913
13402
  */
12914
13403
 
12915
13404
 
12916
13405
  setVolume(volume) {
13406
+ this.volume = volume;
12917
13407
  const audioPublication = this.getTrack(Track.Source.Microphone);
12918
13408
 
12919
- if (audioPublication) {
13409
+ if (audioPublication && audioPublication.track) {
12920
13410
  audioPublication.track.setVolume(volume);
12921
13411
  }
12922
13412
  }
12923
13413
  /**
12924
13414
  * gets the volume on the participant's microphone track
12925
- * returns undefined if no microphone track exists
12926
13415
  */
12927
13416
 
12928
13417
 
12929
13418
  getVolume() {
12930
13419
  const audioPublication = this.getTrack(Track.Source.Microphone);
12931
13420
 
12932
- if (audioPublication) {
13421
+ if (audioPublication && audioPublication.track) {
12933
13422
  return audioPublication.track.getVolume();
12934
13423
  }
13424
+
13425
+ return this.volume;
12935
13426
  }
12936
13427
  /** @internal */
12937
13428
 
@@ -12987,7 +13478,12 @@ class RemoteParticipant extends Participant {
12987
13478
  track.isMuted = publication.isMuted;
12988
13479
  track.setMediaStream(mediaStream);
12989
13480
  track.start();
12990
- publication.setTrack(track);
13481
+ publication.setTrack(track); // set participant volume on new microphone tracks
13482
+
13483
+ if (this.volume !== undefined && track instanceof RemoteAudioTrack && track.source === Track.Source.Microphone) {
13484
+ track.setVolume(this.volume);
13485
+ }
13486
+
12991
13487
  this.emit(ParticipantEvent.TrackSubscribed, track, publication);
12992
13488
  return publication;
12993
13489
  }
@@ -13109,13 +13605,25 @@ class RemoteParticipant extends Participant {
13109
13605
 
13110
13606
  }
13111
13607
 
13608
+ const compatibleCodecForSVC = 'vp8';
13112
13609
  class LocalParticipant extends Participant {
13113
13610
  /** @internal */
13114
13611
  constructor(sid, identity, engine, options) {
13115
13612
  super(sid, identity);
13116
13613
  this.pendingPublishing = new Set();
13614
+ this.participantTrackPermissions = [];
13615
+ this.allParticipantsAllowedToSubscribe = true;
13616
+
13617
+ this.updateTrackSubscriptionPermissions = () => {
13618
+ livekitLogger.debug('updating track subscription permissions', {
13619
+ allParticipantsAllowed: this.allParticipantsAllowedToSubscribe,
13620
+ participantTrackPermissions: this.participantTrackPermissions
13621
+ });
13622
+ this.engine.client.sendUpdateSubscriptionPermissions(this.allParticipantsAllowedToSubscribe, this.participantTrackPermissions.map(p => trackPermissionToProto(p)));
13623
+ };
13117
13624
  /** @internal */
13118
13625
 
13626
+
13119
13627
  this.onTrackUnmuted = track => {
13120
13628
  this.onTrackMuted(track, track.isUpstreamPaused);
13121
13629
  }; // when the local track changes in mute status, we'll notify server as such
@@ -13147,7 +13655,7 @@ class LocalParticipant extends Participant {
13147
13655
  };
13148
13656
 
13149
13657
  this.handleSubscribedQualityUpdate = update => {
13150
- var _a, _b;
13658
+ var _a, _b, _c;
13151
13659
 
13152
13660
  if (!((_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.dynacast)) {
13153
13661
  return;
@@ -13163,7 +13671,11 @@ class LocalParticipant extends Participant {
13163
13671
  return;
13164
13672
  }
13165
13673
 
13166
- (_b = pub.videoTrack) === null || _b === void 0 ? void 0 : _b.setPublishingLayers(update.subscribedQualities);
13674
+ if (update.subscribedCodecs.length > 0) {
13675
+ (_b = pub.videoTrack) === null || _b === void 0 ? void 0 : _b.setPublishingCodecs(update.subscribedCodecs);
13676
+ } else if (update.subscribedQualities.length > 0) {
13677
+ (_c = pub.videoTrack) === null || _c === void 0 ? void 0 : _c.setPublishingLayers(update.subscribedQualities);
13678
+ }
13167
13679
  };
13168
13680
 
13169
13681
  this.handleLocalTrackUnpublished = unpublished => {
@@ -13180,7 +13692,10 @@ class LocalParticipant extends Participant {
13180
13692
  this.unpublishTrack(track.track);
13181
13693
  };
13182
13694
 
13183
- this.onTrackUnpublish = track => {
13695
+ this.handleTrackEnded = track => {
13696
+ livekitLogger.debug('unpublishing local track due to TrackEnded', {
13697
+ track: track.sid
13698
+ });
13184
13699
  this.unpublishTrack(track);
13185
13700
  };
13186
13701
 
@@ -13206,6 +13721,7 @@ class LocalParticipant extends Participant {
13206
13721
 
13207
13722
  this.engine.client.onSubscribedQualityUpdate = this.handleSubscribedQualityUpdate;
13208
13723
  this.engine.client.onLocalTrackUnpublished = this.handleLocalTrackUnpublished;
13724
+ this.engine.on(EngineEvent.Connected, this.updateTrackSubscriptionPermissions).on(EngineEvent.Restarted, this.updateTrackSubscriptionPermissions).on(EngineEvent.Resumed, this.updateTrackSubscriptionPermissions);
13209
13725
  }
13210
13726
 
13211
13727
  get lastCameraError() {
@@ -13548,7 +14064,7 @@ class LocalParticipant extends Participant {
13548
14064
 
13549
14065
  track.on(TrackEvent.Muted, this.onTrackMuted);
13550
14066
  track.on(TrackEvent.Unmuted, this.onTrackUnmuted);
13551
- track.on(TrackEvent.Ended, this.onTrackUnpublish);
14067
+ track.on(TrackEvent.Ended, this.handleTrackEnded);
13552
14068
  track.on(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
13553
14069
  track.on(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed); // create track publication from track
13554
14070
 
@@ -13563,6 +14079,8 @@ class LocalParticipant extends Participant {
13563
14079
  }); // compute encodings and layers for video
13564
14080
 
13565
14081
  let encodings;
14082
+ let simEncodings;
14083
+ let simulcastTracks;
13566
14084
 
13567
14085
  if (track.kind === Track.Kind.Video) {
13568
14086
  // TODO: support react native, which doesn't expose getSettings
@@ -13571,29 +14089,46 @@ class LocalParticipant extends Participant {
13571
14089
  const height = (_e = settings.height) !== null && _e !== void 0 ? _e : (_f = track.dimensions) === null || _f === void 0 ? void 0 : _f.height; // width and height should be defined for video
13572
14090
 
13573
14091
  req.width = width !== null && width !== void 0 ? width : 0;
13574
- req.height = height !== null && height !== void 0 ? height : 0; // for svc codecs, disable simulcast and enable scalability L3T3
13575
- // by default
13576
-
13577
- if (track instanceof LocalVideoTrack) {
13578
- if ((opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'vp9' || (opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'av1') {
13579
- opts.simulcast = false;
13580
- opts.scalabilityMode = (_g = opts.scalabilityMode) !== null && _g !== void 0 ? _g : 'L3T3';
13581
- } else {
13582
- // other codecs, unset scalability
13583
- opts.scalabilityMode = undefined;
13584
- }
14092
+ req.height = height !== null && height !== void 0 ? height : 0; // for svc codecs, disable simulcast and use vp8 for backup codec
14093
+
14094
+ if (track instanceof LocalVideoTrack && ((opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'vp9' || (opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'av1')) {
14095
+ // set scalabilityMode to 'L3T3' by default
14096
+ opts.scalabilityMode = (_g = opts.scalabilityMode) !== null && _g !== void 0 ? _g : 'L3T3'; // add backup codec track
14097
+
14098
+ const simOpts = _objectSpread2({}, opts);
14099
+
14100
+ simOpts.simulcast = true;
14101
+ simOpts.scalabilityMode = undefined;
14102
+ simEncodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, simOpts);
14103
+ const simulcastTrack = track.addSimulcastTrack(compatibleCodecForSVC, simEncodings);
14104
+ simulcastTracks = [simulcastTrack];
14105
+ req.simulcastCodecs = [{
14106
+ codec: opts.videoCodec,
14107
+ cid: track.mediaStreamTrack.id,
14108
+ enableSimulcastLayers: true
14109
+ }, {
14110
+ codec: simulcastTrack.codec,
14111
+ cid: simulcastTrack.mediaStreamTrack.id,
14112
+ enableSimulcastLayers: true
14113
+ }];
13585
14114
  }
13586
14115
 
13587
14116
  encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, opts);
13588
- req.layers = videoLayersFromEncodings(req.width, req.height, encodings);
14117
+ req.layers = videoLayersFromEncodings(req.width, req.height, simEncodings !== null && simEncodings !== void 0 ? simEncodings : encodings);
13589
14118
  } else if (track.kind === Track.Kind.Audio && opts.audioBitrate) {
13590
14119
  encodings = [{
13591
14120
  maxBitrate: opts.audioBitrate
13592
14121
  }];
13593
14122
  }
13594
14123
 
14124
+ if (!this.engine || this.engine.isClosed) {
14125
+ throw new UnexpectedConnectionState('cannot publish track when not connected');
14126
+ }
14127
+
13595
14128
  const ti = await this.engine.addTrack(req);
13596
- const publication = new LocalTrackPublication(track.kind, ti, track);
14129
+ const publication = new LocalTrackPublication(track.kind, ti, track); // save options for when it needs to be republished again
14130
+
14131
+ publication.options = opts;
13597
14132
  track.sid = ti.sid;
13598
14133
 
13599
14134
  if (!this.engine.publisher) {
@@ -13610,12 +14145,32 @@ class LocalParticipant extends Participant {
13610
14145
 
13611
14146
  if (encodings) {
13612
14147
  transceiverInit.sendEncodings = encodings;
13613
- }
14148
+ } // addTransceiver for react-native is async. web is synchronous, but await won't effect it.
14149
+
13614
14150
 
13615
- const transceiver = this.engine.publisher.pc.addTransceiver(track.mediaStreamTrack, transceiverInit);
14151
+ const transceiver = await this.engine.publisher.pc.addTransceiver(track.mediaStreamTrack, transceiverInit);
13616
14152
 
13617
- if (opts.videoCodec) {
14153
+ if (track.kind === Track.Kind.Video && opts.videoCodec) {
13618
14154
  this.setPreferredCodec(transceiver, track.kind, opts.videoCodec);
14155
+ track.codec = opts.videoCodec;
14156
+ }
14157
+
14158
+ const localTrack = track;
14159
+
14160
+ if (simulcastTracks) {
14161
+ for await (const simulcastTrack of simulcastTracks) {
14162
+ const simTransceiverInit = {
14163
+ direction: 'sendonly'
14164
+ };
14165
+
14166
+ if (simulcastTrack.encodings) {
14167
+ simTransceiverInit.sendEncodings = simulcastTrack.encodings;
14168
+ }
14169
+
14170
+ const simTransceiver = await this.engine.publisher.pc.addTransceiver(simulcastTrack.mediaStreamTrack, simTransceiverInit);
14171
+ this.setPreferredCodec(simTransceiver, localTrack.kind, simulcastTrack.codec);
14172
+ localTrack.setSimulcastTrackSender(simulcastTrack.codec, simTransceiver.sender);
14173
+ }
13619
14174
  }
13620
14175
 
13621
14176
  this.engine.negotiate(); // store RTPSender
@@ -13653,9 +14208,10 @@ class LocalParticipant extends Participant {
13653
14208
  }
13654
14209
 
13655
14210
  track = publication.track;
14211
+ track.sender = undefined;
13656
14212
  track.off(TrackEvent.Muted, this.onTrackMuted);
13657
14213
  track.off(TrackEvent.Unmuted, this.onTrackUnmuted);
13658
- track.off(TrackEvent.Ended, this.onTrackUnpublish);
14214
+ track.off(TrackEvent.Ended, this.handleTrackEnded);
13659
14215
  track.off(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
13660
14216
  track.off(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed);
13661
14217
 
@@ -13671,7 +14227,7 @@ class LocalParticipant extends Participant {
13671
14227
  mediaStreamTrack
13672
14228
  } = track;
13673
14229
 
13674
- if (this.engine.publisher) {
14230
+ if (this.engine.publisher && this.engine.publisher.pc.connectionState !== 'closed') {
13675
14231
  const senders = this.engine.publisher.pc.getSenders();
13676
14232
  senders.forEach(sender => {
13677
14233
  var _a;
@@ -13776,7 +14332,12 @@ class LocalParticipant extends Participant {
13776
14332
 
13777
14333
  setTrackSubscriptionPermissions(allParticipantsAllowed) {
13778
14334
  let participantTrackPermissions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
13779
- this.engine.client.sendUpdateSubscriptionPermissions(allParticipantsAllowed, participantTrackPermissions.map(p => trackPermissionToProto(p)));
14335
+ this.participantTrackPermissions = participantTrackPermissions;
14336
+ this.allParticipantsAllowedToSubscribe = allParticipantsAllowed;
14337
+
14338
+ if (this.engine.client.isConnected) {
14339
+ this.updateTrackSubscriptionPermissions();
14340
+ }
13780
14341
  }
13781
14342
 
13782
14343
  getPublicationForTrack(track) {
@@ -13809,6 +14370,7 @@ class LocalParticipant extends Participant {
13809
14370
 
13810
14371
  const cap = RTCRtpSender.getCapabilities(kind);
13811
14372
  if (!cap) return;
14373
+ livekitLogger.debug('get capabilities', cap);
13812
14374
  let selected;
13813
14375
  const codecs = [];
13814
14376
  cap.codecs.forEach(c => {
@@ -17441,7 +18003,7 @@ class SignalClient {
17441
18003
  this.requestQueue = new Queue();
17442
18004
  }
17443
18005
 
17444
- async join(url, token, opts) {
18006
+ async join(url, token, opts, abortSignal) {
17445
18007
  // during a full reconnect, we'd want to start the sequence even if currently
17446
18008
  // connected
17447
18009
  this.isConnected = false;
@@ -17449,7 +18011,7 @@ class SignalClient {
17449
18011
  autoSubscribe: opts === null || opts === void 0 ? void 0 : opts.autoSubscribe,
17450
18012
  publishOnly: opts === null || opts === void 0 ? void 0 : opts.publishOnly,
17451
18013
  adaptiveStream: opts === null || opts === void 0 ? void 0 : opts.adaptiveStream
17452
- });
18014
+ }, abortSignal);
17453
18015
  return res;
17454
18016
  }
17455
18017
 
@@ -17460,7 +18022,7 @@ class SignalClient {
17460
18022
  });
17461
18023
  }
17462
18024
 
17463
- connect(url, token, opts) {
18025
+ connect(url, token, opts, abortSignal) {
17464
18026
  if (url.startsWith('http')) {
17465
18027
  url = url.replace('http', 'ws');
17466
18028
  } // strip trailing slash
@@ -17471,6 +18033,17 @@ class SignalClient {
17471
18033
  const clientInfo = getClientInfo();
17472
18034
  const params = createConnectionParams(token, clientInfo, opts);
17473
18035
  return new Promise((resolve, reject) => {
18036
+ const abortHandler = () => {
18037
+ ws.close();
18038
+ this.close();
18039
+ reject(new ConnectionError('room connection has been cancelled'));
18040
+ };
18041
+
18042
+ if (abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) {
18043
+ abortHandler();
18044
+ }
18045
+
18046
+ abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.addEventListener('abort', abortHandler);
17474
18047
  livekitLogger.debug("connecting to ".concat(url + params));
17475
18048
  this.ws = undefined;
17476
18049
  const ws = new WebSocket(url + params);
@@ -17526,6 +18099,7 @@ class SignalClient {
17526
18099
  // handle join message only
17527
18100
  if (msg.join) {
17528
18101
  this.isConnected = true;
18102
+ abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.removeEventListener('abort', abortHandler);
17529
18103
  resolve(msg.join);
17530
18104
  } else {
17531
18105
  reject(new ConnectionError('did not receive join response'));
@@ -17646,8 +18220,8 @@ class SignalClient {
17646
18220
  });
17647
18221
  }
17648
18222
 
17649
- sendLeave() {
17650
- this.sendRequest(SignalRequest.fromPartial({
18223
+ async sendLeave() {
18224
+ await this.sendRequest(SignalRequest.fromPartial({
17651
18225
  leave: {}
17652
18226
  }));
17653
18227
  }
@@ -17948,7 +18522,7 @@ class RTCEngine extends events.exports.EventEmitter {
17948
18522
  this.rtcConfig = {};
17949
18523
  this.subscriberPrimary = false;
17950
18524
  this.pcState = PCState.New;
17951
- this.isClosed = true;
18525
+ this._isClosed = true;
17952
18526
  this.pendingTrackResolvers = {}; // true if publisher connection has already been established.
17953
18527
  // this is helpful to know if we need to restart ICE on the publisher connection
17954
18528
 
@@ -17956,6 +18530,7 @@ class RTCEngine extends events.exports.EventEmitter {
17956
18530
  this.reconnectAttempts = 0;
17957
18531
  this.reconnectStart = 0;
17958
18532
  this.fullReconnectOnNext = false;
18533
+ this.attemptingReconnect = false;
17959
18534
 
17960
18535
  this.handleDataChannel = async _ref => {
17961
18536
  let {
@@ -18019,7 +18594,7 @@ class RTCEngine extends events.exports.EventEmitter {
18019
18594
 
18020
18595
 
18021
18596
  this.handleDisconnect = connection => {
18022
- if (this.isClosed) {
18597
+ if (this._isClosed) {
18023
18598
  return;
18024
18599
  }
18025
18600
 
@@ -18032,18 +18607,27 @@ class RTCEngine extends events.exports.EventEmitter {
18032
18607
 
18033
18608
  const delay = this.reconnectAttempts * this.reconnectAttempts * 300;
18034
18609
  setTimeout(async () => {
18035
- var _a;
18610
+ var _a, _b, _c;
18611
+
18612
+ if (this._isClosed) {
18613
+ return;
18614
+ } // guard for attempting reconnection multiple times while one attempt is still not finished
18615
+
18036
18616
 
18037
- if (this.isClosed) {
18617
+ if (this.attemptingReconnect) {
18038
18618
  return;
18039
18619
  }
18040
18620
 
18041
18621
  if (isFireFox() || // TODO remove once clientConfiguration handles firefox case server side
18042
- ((_a = this.clientConfiguration) === null || _a === void 0 ? void 0 : _a.resumeConnection) === ClientConfigSetting.DISABLED) {
18622
+ ((_a = this.clientConfiguration) === null || _a === void 0 ? void 0 : _a.resumeConnection) === ClientConfigSetting.DISABLED || // signaling state could change to closed due to hardware sleep
18623
+ // those connections cannot be resumed
18624
+ ((_c = (_b = this.primaryPC) === null || _b === void 0 ? void 0 : _b.signalingState) !== null && _c !== void 0 ? _c : 'closed') === 'closed') {
18043
18625
  this.fullReconnectOnNext = true;
18044
18626
  }
18045
18627
 
18046
18628
  try {
18629
+ this.attemptingReconnect = true;
18630
+
18047
18631
  if (this.fullReconnectOnNext) {
18048
18632
  await this.restartConnection();
18049
18633
  } else {
@@ -18054,6 +18638,7 @@ class RTCEngine extends events.exports.EventEmitter {
18054
18638
  this.fullReconnectOnNext = false;
18055
18639
  } catch (e) {
18056
18640
  this.reconnectAttempts += 1;
18641
+ let reconnectRequired = false;
18057
18642
  let recoverable = true;
18058
18643
 
18059
18644
  if (e instanceof UnexpectedConnectionState) {
@@ -18064,7 +18649,14 @@ class RTCEngine extends events.exports.EventEmitter {
18064
18649
  recoverable = false;
18065
18650
  } else if (!(e instanceof SignalReconnectError)) {
18066
18651
  // cannot resume
18652
+ reconnectRequired = true;
18653
+ } // when we flip from resume to reconnect, we need to reset reconnectAttempts
18654
+ // this is needed to fire the right reconnecting events
18655
+
18656
+
18657
+ if (reconnectRequired && !this.fullReconnectOnNext) {
18067
18658
  this.fullReconnectOnNext = true;
18659
+ this.reconnectAttempts = 0;
18068
18660
  }
18069
18661
 
18070
18662
  const duration = Date.now() - this.reconnectStart;
@@ -18080,6 +18672,8 @@ class RTCEngine extends events.exports.EventEmitter {
18080
18672
  this.emit(EngineEvent.Disconnected);
18081
18673
  this.close();
18082
18674
  }
18675
+ } finally {
18676
+ this.attemptingReconnect = false;
18083
18677
  }
18084
18678
  }, delay);
18085
18679
  };
@@ -18087,12 +18681,16 @@ class RTCEngine extends events.exports.EventEmitter {
18087
18681
  this.client = new SignalClient();
18088
18682
  }
18089
18683
 
18090
- async join(url, token, opts) {
18684
+ get isClosed() {
18685
+ return this._isClosed;
18686
+ }
18687
+
18688
+ async join(url, token, opts, abortSignal) {
18091
18689
  this.url = url;
18092
18690
  this.token = token;
18093
18691
  this.signalOpts = opts;
18094
- const joinResponse = await this.client.join(url, token, opts);
18095
- this.isClosed = false;
18692
+ const joinResponse = await this.client.join(url, token, opts, abortSignal);
18693
+ this._isClosed = false;
18096
18694
  this.subscriberPrimary = joinResponse.subscriberPrimary;
18097
18695
 
18098
18696
  if (!this.publisher) {
@@ -18109,7 +18707,7 @@ class RTCEngine extends events.exports.EventEmitter {
18109
18707
  }
18110
18708
 
18111
18709
  close() {
18112
- this.isClosed = true;
18710
+ this._isClosed = true;
18113
18711
  this.removeAllListeners();
18114
18712
 
18115
18713
  if (this.publisher && this.publisher.pc.signalingState !== 'closed') {
@@ -18224,7 +18822,7 @@ class RTCEngine extends events.exports.EventEmitter {
18224
18822
  this.primaryPC = primaryPC;
18225
18823
 
18226
18824
  primaryPC.onconnectionstatechange = async () => {
18227
- livekitLogger.trace('connection state changed', {
18825
+ livekitLogger.debug('primary PC state changed', {
18228
18826
  state: primaryPC.connectionState
18229
18827
  });
18230
18828
 
@@ -18253,7 +18851,10 @@ class RTCEngine extends events.exports.EventEmitter {
18253
18851
  };
18254
18852
 
18255
18853
  secondaryPC.onconnectionstatechange = async () => {
18256
- // also reconnect if secondary peerconnection fails
18854
+ livekitLogger.debug('secondary PC state changed', {
18855
+ state: secondaryPC.connectionState
18856
+ }); // also reconnect if secondary peerconnection fails
18857
+
18257
18858
  if (secondaryPC.connectionState === 'failed') {
18258
18859
  this.handleDisconnect('secondary peerconnection');
18259
18860
  }
@@ -18381,6 +18982,11 @@ class RTCEngine extends events.exports.EventEmitter {
18381
18982
  this.emit(EngineEvent.Restarting);
18382
18983
  }
18383
18984
 
18985
+ if (this.client.isConnected) {
18986
+ this.client.sendLeave();
18987
+ }
18988
+
18989
+ this.client.close();
18384
18990
  this.primaryPC = undefined;
18385
18991
  (_a = this.publisher) === null || _a === void 0 ? void 0 : _a.close();
18386
18992
  this.publisher = undefined;
@@ -18619,13 +19225,18 @@ const videoDefaults = {
18619
19225
  resolution: VideoPresets.h720.resolution
18620
19226
  };
18621
19227
 
18622
- var RoomState;
19228
+ var ConnectionState;
18623
19229
 
18624
- (function (RoomState) {
18625
- RoomState["Disconnected"] = "disconnected";
18626
- RoomState["Connected"] = "connected";
18627
- RoomState["Reconnecting"] = "reconnecting";
18628
- })(RoomState || (RoomState = {}));
19230
+ (function (ConnectionState) {
19231
+ ConnectionState["Disconnected"] = "disconnected";
19232
+ ConnectionState["Connecting"] = "connecting";
19233
+ ConnectionState["Connected"] = "connected";
19234
+ ConnectionState["Reconnecting"] = "reconnecting";
19235
+ })(ConnectionState || (ConnectionState = {}));
19236
+ /** @deprecated RoomState has been renamed to [[ConnectionState]] */
19237
+
19238
+
19239
+ const RoomState = ConnectionState;
18629
19240
  /**
18630
19241
  * In LiveKit, a room is the logical grouping for a list of participants.
18631
19242
  * Participants in a room can publish tracks, and subscribe to others' tracks.
@@ -18635,7 +19246,6 @@ var RoomState;
18635
19246
  * @noInheritDoc
18636
19247
  */
18637
19248
 
18638
-
18639
19249
  class Room extends events.exports.EventEmitter {
18640
19250
  /**
18641
19251
  * Creates a new Room, the primary construct for a LiveKit session.
@@ -18648,7 +19258,7 @@ class Room extends events.exports.EventEmitter {
18648
19258
 
18649
19259
  super();
18650
19260
  _this = this;
18651
- this.state = RoomState.Disconnected;
19261
+ this.state = ConnectionState.Disconnected;
18652
19262
  /**
18653
19263
  * list of participants that are actively speaking. when this changes
18654
19264
  * a [[RoomEvent.ActiveSpeakersChanged]] event is fired
@@ -18671,9 +19281,15 @@ class Room extends events.exports.EventEmitter {
18671
19281
  var _a, _b; // guard against calling connect
18672
19282
 
18673
19283
 
18674
- if (this.state !== RoomState.Disconnected) {
19284
+ if (this.state !== ConnectionState.Disconnected) {
18675
19285
  livekitLogger.warn("already connected to room ".concat(this.name));
18676
19286
  return;
19287
+ }
19288
+
19289
+ this.setAndEmitConnectionState(ConnectionState.Connecting);
19290
+
19291
+ if (!this.abortController || this.abortController.signal.aborted) {
19292
+ this.abortController = new AbortController();
18677
19293
  } // recreate engine if previously disconnected
18678
19294
 
18679
19295
 
@@ -18691,7 +19307,7 @@ class Room extends events.exports.EventEmitter {
18691
19307
  autoSubscribe: opts === null || opts === void 0 ? void 0 : opts.autoSubscribe,
18692
19308
  publishOnly: opts === null || opts === void 0 ? void 0 : opts.publishOnly,
18693
19309
  adaptiveStream: typeof ((_a = this.options) === null || _a === void 0 ? void 0 : _a.adaptiveStream) === 'object' ? true : (_b = this.options) === null || _b === void 0 ? void 0 : _b.adaptiveStream
18694
- });
19310
+ }, this.abortController.signal);
18695
19311
  livekitLogger.debug("connected to Livekit Server version: ".concat(joinResponse.serverVersion, ", region: ").concat(joinResponse.serverRegion));
18696
19312
 
18697
19313
  if (!joinResponse.serverVersion) {
@@ -18704,15 +19320,12 @@ class Room extends events.exports.EventEmitter {
18704
19320
  this.options.dynacast = false;
18705
19321
  }
18706
19322
 
18707
- this.state = RoomState.Connected;
18708
19323
  const pi = joinResponse.participant;
18709
19324
  this.localParticipant.sid = pi.sid;
18710
19325
  this.localParticipant.identity = pi.identity;
18711
19326
  this.localParticipant.updateInfo(pi); // forward metadata changed for the local participant
18712
19327
 
18713
- this.localParticipant.on(ParticipantEvent.MetadataChanged, metadata => {
18714
- this.emit(RoomEvent.MetadataChanged, metadata, this.localParticipant);
18715
- }).on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
19328
+ this.localParticipant.on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
18716
19329
  this.emit(RoomEvent.ParticipantMetadataChanged, metadata, this.localParticipant);
18717
19330
  }).on(ParticipantEvent.TrackMuted, pub => {
18718
19331
  this.emit(RoomEvent.TrackMuted, pub, this.localParticipant);
@@ -18736,29 +19349,49 @@ class Room extends events.exports.EventEmitter {
18736
19349
  this.name = joinResponse.room.name;
18737
19350
  this.sid = joinResponse.room.sid;
18738
19351
  this.metadata = joinResponse.room.metadata;
18739
- this.emit(RoomEvent.StateChanged, this.state);
19352
+ this.emit(RoomEvent.SignalConnected);
18740
19353
  } catch (err) {
18741
19354
  this.engine.close();
19355
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
18742
19356
  throw err;
18743
19357
  } // don't return until ICE connected
18744
19358
 
18745
19359
 
18746
19360
  return new Promise((resolve, reject) => {
19361
+ var _a, _b;
19362
+
18747
19363
  const connectTimeout = setTimeout(() => {
18748
19364
  // timeout
18749
19365
  this.engine.close();
19366
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
18750
19367
  reject(new ConnectionError('could not connect after timeout'));
18751
19368
  }, maxICEConnectTimeout);
19369
+
19370
+ const abortHandler = () => {
19371
+ livekitLogger.warn('closing engine');
19372
+ clearTimeout(connectTimeout);
19373
+ this.engine.close();
19374
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
19375
+ reject(new ConnectionError('room connection has been cancelled'));
19376
+ };
19377
+
19378
+ if ((_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
19379
+ abortHandler();
19380
+ }
19381
+
19382
+ (_b = this.abortController) === null || _b === void 0 ? void 0 : _b.signal.addEventListener('abort', abortHandler);
18752
19383
  this.engine.once(EngineEvent.Connected, () => {
18753
- var _a;
19384
+ var _a, _b;
18754
19385
 
18755
- clearTimeout(connectTimeout); // also hook unload event
19386
+ clearTimeout(connectTimeout);
19387
+ (_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.removeEventListener('abort', abortHandler); // also hook unload event
18756
19388
 
18757
19389
  if (isWeb()) {
18758
19390
  window.addEventListener('beforeunload', this.onBeforeUnload);
18759
- (_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.addEventListener('devicechange', this.handleDeviceChange);
19391
+ (_b = navigator.mediaDevices) === null || _b === void 0 ? void 0 : _b.addEventListener('devicechange', this.handleDeviceChange);
18760
19392
  }
18761
19393
 
19394
+ this.setAndEmitConnectionState(ConnectionState.Connected);
18762
19395
  resolve(this);
18763
19396
  });
18764
19397
  });
@@ -18771,10 +19404,22 @@ class Room extends events.exports.EventEmitter {
18771
19404
  this.disconnect = function () {
18772
19405
  let stopTracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
18773
19406
 
18774
- // send leave
18775
- if (_this.engine) {
19407
+ var _a, _b;
19408
+
19409
+ if (_this.state === ConnectionState.Connecting) {
19410
+ // try aborting pending connection attempt
19411
+ livekitLogger.warn('abort connection attempt');
19412
+ (_a = _this.abortController) === null || _a === void 0 ? void 0 : _a.abort();
19413
+ return;
19414
+ } // send leave
19415
+
19416
+
19417
+ if ((_b = _this.engine) === null || _b === void 0 ? void 0 : _b.client.isConnected) {
18776
19418
  _this.engine.client.sendLeave();
19419
+ } // close engine (also closes client)
18777
19420
 
19421
+
19422
+ if (_this.engine) {
18778
19423
  _this.engine.close();
18779
19424
  }
18780
19425
 
@@ -18790,9 +19435,10 @@ class Room extends events.exports.EventEmitter {
18790
19435
  };
18791
19436
 
18792
19437
  this.handleRestarting = () => {
18793
- this.state = RoomState.Reconnecting;
18794
- this.emit(RoomEvent.Reconnecting);
18795
- this.emit(RoomEvent.StateChanged, this.state); // also unwind existing participants & existing subscriptions
19438
+ if (this.setAndEmitConnectionState(ConnectionState.Reconnecting)) {
19439
+ this.emit(RoomEvent.Reconnecting);
19440
+ } // also unwind existing participants & existing subscriptions
19441
+
18796
19442
 
18797
19443
  for (const p of this.participants.values()) {
18798
19444
  this.handleParticipantDisconnected(p.sid, p);
@@ -18800,10 +19446,11 @@ class Room extends events.exports.EventEmitter {
18800
19446
  };
18801
19447
 
18802
19448
  this.handleRestarted = async joinResponse => {
18803
- livekitLogger.debug("reconnected to server region ".concat(joinResponse.serverRegion));
18804
- this.state = RoomState.Connected;
18805
- this.emit(RoomEvent.Reconnected);
18806
- this.emit(RoomEvent.StateChanged, this.state); // rehydrate participants
19449
+ livekitLogger.debug("reconnected to server", {
19450
+ region: joinResponse.serverRegion
19451
+ });
19452
+ this.setAndEmitConnectionState(ConnectionState.Connected);
19453
+ this.emit(RoomEvent.Reconnected); // rehydrate participants
18807
19454
 
18808
19455
  if (joinResponse.participant) {
18809
19456
  // with a restart, the sid will have changed, we'll map our understanding to it
@@ -18822,7 +19469,19 @@ class Room extends events.exports.EventEmitter {
18822
19469
  await Promise.all(localPubs.map(async pub => {
18823
19470
  const track = pub.track;
18824
19471
  this.localParticipant.unpublishTrack(track, false);
18825
- this.localParticipant.publishTrack(track, pub.options);
19472
+
19473
+ if (!track.isMuted) {
19474
+ if (track instanceof LocalAudioTrack || track instanceof LocalVideoTrack) {
19475
+ // we need to restart the track before publishing, often a full reconnect
19476
+ // is necessary because computer had gone to sleep.
19477
+ livekitLogger.debug('restarting existing track', {
19478
+ track: pub.trackSid
19479
+ });
19480
+ await track.restartTrack();
19481
+ }
19482
+
19483
+ await this.localParticipant.publishTrack(track, pub.options);
19484
+ }
18826
19485
  }));
18827
19486
  };
18828
19487
 
@@ -18832,6 +19491,14 @@ class Room extends events.exports.EventEmitter {
18832
19491
  if (info.sid === this.localParticipant.sid || info.identity === this.localParticipant.identity) {
18833
19492
  this.localParticipant.updateInfo(info);
18834
19493
  return;
19494
+ } // ensure identity <=> sid mapping
19495
+
19496
+
19497
+ const sid = this.identityToSid.get(info.identity);
19498
+
19499
+ if (sid && sid !== info.sid) {
19500
+ // sid had changed, need to remove previous participant
19501
+ this.handleParticipantDisconnected(sid, this.participants.get(sid));
18835
19502
  }
18836
19503
 
18837
19504
  let remoteParticipant = this.participants.get(info.sid);
@@ -18842,7 +19509,8 @@ class Room extends events.exports.EventEmitter {
18842
19509
  if (info.state === ParticipantInfo_State.DISCONNECTED) {
18843
19510
  this.handleParticipantDisconnected(info.sid, remoteParticipant);
18844
19511
  } else if (isNewParticipant) {
18845
- // fire connected event
19512
+ this.identityToSid.set(info.identity, info.sid); // fire connected event
19513
+
18846
19514
  this.emit(RoomEvent.ParticipantConnected, remoteParticipant);
18847
19515
  } else {
18848
19516
  // just update, no events
@@ -19011,6 +19679,7 @@ class Room extends events.exports.EventEmitter {
19011
19679
  };
19012
19680
 
19013
19681
  this.participants = new Map();
19682
+ this.identityToSid = new Map();
19014
19683
  this.options = options || {};
19015
19684
 
19016
19685
  switch ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.publishDefaults) === null || _b === void 0 ? void 0 : _b.videoCodec) {
@@ -19045,16 +19714,15 @@ class Room extends events.exports.EventEmitter {
19045
19714
  }).on(EngineEvent.Disconnected, () => {
19046
19715
  this.handleDisconnect();
19047
19716
  }).on(EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate).on(EngineEvent.DataPacketReceived, this.handleDataPacket).on(EngineEvent.Resuming, () => {
19048
- this.state = RoomState.Reconnecting;
19049
- this.emit(RoomEvent.Reconnecting);
19050
- this.emit(RoomEvent.StateChanged, this.state);
19717
+ if (this.setAndEmitConnectionState(ConnectionState.Reconnecting)) {
19718
+ this.emit(RoomEvent.Reconnecting);
19719
+ }
19051
19720
  }).on(EngineEvent.Resumed, () => {
19052
- this.state = RoomState.Connected;
19721
+ this.setAndEmitConnectionState(ConnectionState.Connected);
19053
19722
  this.emit(RoomEvent.Reconnected);
19054
- this.emit(RoomEvent.StateChanged, this.state);
19055
19723
  this.updateSubscriptions();
19056
19724
  }).on(EngineEvent.SignalResumed, () => {
19057
- if (this.state === RoomState.Reconnecting) {
19725
+ if (this.state === ConnectionState.Reconnecting) {
19058
19726
  this.sendSyncState();
19059
19727
  }
19060
19728
  }).on(EngineEvent.Restarting, this.handleRestarting).on(EngineEvent.Restarted, this.handleRestarted);
@@ -19081,15 +19749,15 @@ class Room extends events.exports.EventEmitter {
19081
19749
 
19082
19750
 
19083
19751
  getParticipantByIdentity(identity) {
19084
- for (const [, p] of this.participants) {
19085
- if (p.identity === identity) {
19086
- return p;
19087
- }
19088
- }
19089
-
19090
19752
  if (this.localParticipant.identity === identity) {
19091
19753
  return this.localParticipant;
19092
19754
  }
19755
+
19756
+ const sid = this.identityToSid.get(identity);
19757
+
19758
+ if (sid) {
19759
+ return this.participants.get(sid);
19760
+ }
19093
19761
  }
19094
19762
  /**
19095
19763
  * @internal for testing
@@ -19097,6 +19765,8 @@ class Room extends events.exports.EventEmitter {
19097
19765
 
19098
19766
 
19099
19767
  simulateScenario(scenario) {
19768
+ let postAction = () => {};
19769
+
19100
19770
  let req;
19101
19771
 
19102
19772
  switch (scenario) {
@@ -19123,10 +19793,26 @@ class Room extends events.exports.EventEmitter {
19123
19793
  migration: true
19124
19794
  });
19125
19795
  break;
19796
+
19797
+ case 'switch-candidate':
19798
+ req = SimulateScenario.fromPartial({
19799
+ switchCandidateProtocol: 1
19800
+ });
19801
+
19802
+ postAction = () => {
19803
+ var _a;
19804
+
19805
+ (_a = this.engine.publisher) === null || _a === void 0 ? void 0 : _a.createAndSendOffer({
19806
+ iceRestart: true
19807
+ });
19808
+ };
19809
+
19810
+ break;
19126
19811
  }
19127
19812
 
19128
19813
  if (req) {
19129
19814
  this.engine.client.sendSimulateScenario(req);
19815
+ postAction();
19130
19816
  }
19131
19817
  }
19132
19818
  /**
@@ -19240,10 +19926,6 @@ class Room extends events.exports.EventEmitter {
19240
19926
 
19241
19927
  var _a;
19242
19928
 
19243
- if (this.state === RoomState.Disconnected) {
19244
- return;
19245
- }
19246
-
19247
19929
  this.participants.forEach(p => {
19248
19930
  p.tracks.forEach(pub => {
19249
19931
  p.unpublishTrack(pub.trackSid);
@@ -19253,7 +19935,7 @@ class Room extends events.exports.EventEmitter {
19253
19935
  var _a, _b;
19254
19936
 
19255
19937
  if (pub.track) {
19256
- this.localParticipant.unpublishTrack(pub.track);
19938
+ this.localParticipant.unpublishTrack(pub.track, shouldStopTracks);
19257
19939
  }
19258
19940
 
19259
19941
  if (shouldStopTracks) {
@@ -19274,9 +19956,8 @@ class Room extends events.exports.EventEmitter {
19274
19956
  (_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.removeEventListener('devicechange', this.handleDeviceChange);
19275
19957
  }
19276
19958
 
19277
- this.state = RoomState.Disconnected;
19959
+ this.setAndEmitConnectionState(ConnectionState.Disconnected);
19278
19960
  this.emit(RoomEvent.Disconnected);
19279
- this.emit(RoomEvent.StateChanged, this.state);
19280
19961
  }
19281
19962
 
19282
19963
  handleParticipantDisconnected(sid, participant) {
@@ -19287,8 +19968,9 @@ class Room extends events.exports.EventEmitter {
19287
19968
  return;
19288
19969
  }
19289
19970
 
19971
+ this.identityToSid.delete(participant.identity);
19290
19972
  participant.tracks.forEach(publication => {
19291
- participant.unpublishTrack(publication.trackSid);
19973
+ participant.unpublishTrack(publication.trackSid, true);
19292
19974
  });
19293
19975
  this.emit(RoomEvent.ParticipantDisconnected, participant);
19294
19976
  }
@@ -19351,8 +20033,6 @@ class Room extends events.exports.EventEmitter {
19351
20033
  this.emit(RoomEvent.TrackMuted, pub, participant);
19352
20034
  }).on(ParticipantEvent.TrackUnmuted, pub => {
19353
20035
  this.emit(RoomEvent.TrackUnmuted, pub, participant);
19354
- }).on(ParticipantEvent.MetadataChanged, metadata => {
19355
- this.emit(RoomEvent.MetadataChanged, metadata, participant);
19356
20036
  }).on(ParticipantEvent.ParticipantMetadataChanged, metadata => {
19357
20037
  this.emit(RoomEvent.ParticipantMetadataChanged, metadata, participant);
19358
20038
  }).on(ParticipantEvent.ConnectionQualityChanged, quality => {
@@ -19414,6 +20094,17 @@ class Room extends events.exports.EventEmitter {
19414
20094
  }
19415
20095
  }
19416
20096
  }
20097
+ }
20098
+
20099
+ setAndEmitConnectionState(state) {
20100
+ if (state === this.state) {
20101
+ // unchanged
20102
+ return false;
20103
+ }
20104
+
20105
+ this.state = state;
20106
+ this.emit(RoomEvent.ConnectionStateChanged, this.state);
20107
+ return true;
19417
20108
  } // /** @internal */
19418
20109
 
19419
20110
 
@@ -19431,101 +20122,6 @@ class Room extends events.exports.EventEmitter {
19431
20122
 
19432
20123
  }
19433
20124
 
19434
- /**
19435
- * @deprecated Use room.connect() instead
19436
- *
19437
- * Connects to a LiveKit room, shorthand for `new Room()` and [[Room.connect]]
19438
- *
19439
- * ```typescript
19440
- * connect('wss://myhost.livekit.io', token, {
19441
- * // publish audio and video tracks on joining
19442
- * audio: true,
19443
- * video: true,
19444
- * captureDefaults: {
19445
- * facingMode: 'user',
19446
- * },
19447
- * })
19448
- * ```
19449
- * @param url URL to LiveKit server
19450
- * @param token AccessToken, a JWT token that includes authentication and room details
19451
- * @param options
19452
- */
19453
-
19454
- async function connect(url, token, options) {
19455
- var _a, _b, _c, _d;
19456
-
19457
- options !== null && options !== void 0 ? options : options = {};
19458
-
19459
- if (options.adaptiveStream === undefined) {
19460
- options.adaptiveStream = options.autoManageVideo === true ? {} : undefined;
19461
- }
19462
-
19463
- setLogLevel((_a = options.logLevel) !== null && _a !== void 0 ? _a : LogLevel.warn);
19464
- const config = (_b = options.rtcConfig) !== null && _b !== void 0 ? _b : {};
19465
-
19466
- if (options.iceServers) {
19467
- config.iceServers = options.iceServers;
19468
- }
19469
-
19470
- const room = new Room(options); // connect to room
19471
-
19472
- await room.connect(url, token, options);
19473
- const publishAudio = (_c = options.audio) !== null && _c !== void 0 ? _c : false;
19474
- const publishVideo = (_d = options.video) !== null && _d !== void 0 ? _d : false;
19475
-
19476
- if (publishAudio || publishVideo) {
19477
- setTimeout(async () => {
19478
- // if publishing both
19479
- let err;
19480
-
19481
- if (publishAudio && publishVideo) {
19482
- try {
19483
- await room.localParticipant.enableCameraAndMicrophone();
19484
- } catch (e) {
19485
- const errKind = MediaDeviceFailure.getFailure(e);
19486
- livekitLogger.warn('received error while creating media', {
19487
- error: errKind
19488
- });
19489
-
19490
- if (e instanceof Error) {
19491
- livekitLogger.warn(e.message);
19492
- } // when it's a device issue, try to publish the other kind
19493
-
19494
-
19495
- if (errKind === MediaDeviceFailure.NotFound || errKind === MediaDeviceFailure.DeviceInUse) {
19496
- try {
19497
- await room.localParticipant.setMicrophoneEnabled(true);
19498
- } catch (audioErr) {
19499
- err = audioErr;
19500
- }
19501
- } else {
19502
- err = e;
19503
- }
19504
- }
19505
- } else if (publishAudio) {
19506
- try {
19507
- await room.localParticipant.setMicrophoneEnabled(true);
19508
- } catch (e) {
19509
- err = e;
19510
- }
19511
- } else if (publishVideo) {
19512
- try {
19513
- await room.localParticipant.setCameraEnabled(true);
19514
- } catch (e) {
19515
- err = e;
19516
- }
19517
- }
19518
-
19519
- if (err) {
19520
- room.emit(RoomEvent.MediaDevicesError, err);
19521
- livekitLogger.error('could not create media', err);
19522
- }
19523
- });
19524
- }
19525
-
19526
- return room;
19527
- }
19528
-
19529
20125
  /**
19530
20126
  * Creates a local video and audio track at the same time. When acquiring both
19531
20127
  * audio and video tracks together, it'll display a single permission prompt to
@@ -19599,7 +20195,7 @@ async function createLocalScreenTracks(options) {
19599
20195
  }
19600
20196
 
19601
20197
  if (options.resolution === undefined) {
19602
- options.resolution = VideoPresets.fhd.resolution;
20198
+ options.resolution = VideoPresets.h1080.resolution;
19603
20199
  }
19604
20200
 
19605
20201
  let videoConstraints = true;
@@ -19636,5 +20232,5 @@ async function createLocalScreenTracks(options) {
19636
20232
  return localTracks;
19637
20233
  }
19638
20234
 
19639
- export { AudioPresets, ConnectionError, ConnectionQuality, DataPacket_Kind, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, connect, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, protocolVersion, setLogExtension, setLogLevel, version };
20235
+ export { AudioPresets, ConnectionError, ConnectionQuality, ConnectionState, DataPacket_Kind, EngineEvent, LivekitError, LocalAudioTrack, LocalParticipant, LocalTrack, LocalTrackPublication, LocalVideoTrack, LogLevel, MediaDeviceFailure, Participant, ParticipantEvent, PublishDataError, RemoteAudioTrack, RemoteParticipant, RemoteTrack, RemoteTrackPublication, RemoteVideoTrack, Room, RoomEvent, RoomState, ScreenSharePresets, Track, TrackEvent, TrackInvalidError, TrackPublication, UnexpectedConnectionState, UnsupportedServer, VideoPreset, VideoPresets, VideoPresets43, VideoQuality, attachToElement, createLocalAudioTrack, createLocalScreenTracks, createLocalTracks, createLocalVideoTrack, detachTrack, protocolVersion, setLogExtension, setLogLevel, version };
19640
20236
  //# sourceMappingURL=livekit-client.esm.mjs.map