livekit-client 1.0.1 → 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 (140) hide show
  1. package/dist/livekit-client.esm.mjs +792 -197
  2. package/dist/livekit-client.esm.mjs.map +1 -1
  3. package/dist/livekit-client.umd.js +1 -1
  4. package/dist/livekit-client.umd.js.map +1 -1
  5. package/dist/{api → src/api}/RequestQueue.d.ts +0 -0
  6. package/dist/src/api/RequestQueue.d.ts.map +1 -0
  7. package/dist/{api → src/api}/SignalClient.d.ts +1 -1
  8. package/dist/src/api/SignalClient.d.ts.map +1 -0
  9. package/dist/{index.d.ts → src/index.d.ts} +0 -0
  10. package/dist/src/index.d.ts.map +1 -0
  11. package/dist/{logger.d.ts → src/logger.d.ts} +0 -0
  12. package/dist/src/logger.d.ts.map +1 -0
  13. package/dist/{options.d.ts → src/options.d.ts} +0 -0
  14. package/dist/src/options.d.ts.map +1 -0
  15. package/dist/{proto → src/proto}/google/protobuf/timestamp.d.ts +0 -0
  16. package/dist/src/proto/google/protobuf/timestamp.d.ts.map +1 -0
  17. package/dist/{proto → src/proto}/livekit_models.d.ts +80 -0
  18. package/dist/src/proto/livekit_models.d.ts.map +1 -0
  19. package/dist/{proto → src/proto}/livekit_rtc.d.ts +661 -0
  20. package/dist/src/proto/livekit_rtc.d.ts.map +1 -0
  21. package/dist/{room → src/room}/DeviceManager.d.ts +0 -0
  22. package/dist/src/room/DeviceManager.d.ts.map +1 -0
  23. package/dist/{room → src/room}/PCTransport.d.ts +0 -0
  24. package/dist/src/room/PCTransport.d.ts.map +1 -0
  25. package/dist/{room → src/room}/RTCEngine.d.ts +1 -0
  26. package/dist/src/room/RTCEngine.d.ts.map +1 -0
  27. package/dist/{room → src/room}/Room.d.ts +2 -0
  28. package/dist/src/room/Room.d.ts.map +1 -0
  29. package/dist/{room → src/room}/errors.d.ts +0 -0
  30. package/dist/src/room/errors.d.ts.map +1 -0
  31. package/dist/{room → src/room}/events.d.ts +5 -1
  32. package/dist/src/room/events.d.ts.map +1 -0
  33. package/dist/{room → src/room}/participant/LocalParticipant.d.ts +4 -1
  34. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -0
  35. package/dist/{room → src/room}/participant/Participant.d.ts +0 -0
  36. package/dist/src/room/participant/Participant.d.ts.map +1 -0
  37. package/dist/{room → src/room}/participant/ParticipantTrackPermission.d.ts +0 -0
  38. package/dist/src/room/participant/ParticipantTrackPermission.d.ts.map +1 -0
  39. package/dist/{room → src/room}/participant/RemoteParticipant.d.ts +0 -0
  40. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -0
  41. package/dist/{room → src/room}/participant/publishUtils.d.ts +0 -0
  42. package/dist/src/room/participant/publishUtils.d.ts.map +1 -0
  43. package/dist/{room → src/room}/stats.d.ts +1 -0
  44. package/dist/src/room/stats.d.ts.map +1 -0
  45. package/dist/{room → src/room}/track/LocalAudioTrack.d.ts +0 -0
  46. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -0
  47. package/dist/{room → src/room}/track/LocalTrack.d.ts +3 -0
  48. package/dist/src/room/track/LocalTrack.d.ts.map +1 -0
  49. package/dist/{room → src/room}/track/LocalTrackPublication.d.ts +0 -0
  50. package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -0
  51. package/dist/{room → src/room}/track/LocalVideoTrack.d.ts +17 -2
  52. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -0
  53. package/dist/{room → src/room}/track/RemoteAudioTrack.d.ts +0 -0
  54. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -0
  55. package/dist/{room → src/room}/track/RemoteTrack.d.ts +0 -1
  56. package/dist/src/room/track/RemoteTrack.d.ts.map +1 -0
  57. package/dist/{room → src/room}/track/RemoteTrackPublication.d.ts +0 -0
  58. package/dist/src/room/track/RemoteTrackPublication.d.ts.map +1 -0
  59. package/dist/{room → src/room}/track/RemoteVideoTrack.d.ts +2 -0
  60. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -0
  61. package/dist/{room → src/room}/track/Track.d.ts +4 -0
  62. package/dist/src/room/track/Track.d.ts.map +1 -0
  63. package/dist/{room → src/room}/track/TrackPublication.d.ts +0 -0
  64. package/dist/src/room/track/TrackPublication.d.ts.map +1 -0
  65. package/dist/{room → src/room}/track/create.d.ts +0 -0
  66. package/dist/src/room/track/create.d.ts.map +1 -0
  67. package/dist/{room → src/room}/track/defaults.d.ts +0 -0
  68. package/dist/src/room/track/defaults.d.ts.map +1 -0
  69. package/dist/{room → src/room}/track/options.d.ts +2 -1
  70. package/dist/src/room/track/options.d.ts.map +1 -0
  71. package/dist/{room → src/room}/track/types.d.ts +0 -0
  72. package/dist/src/room/track/types.d.ts.map +1 -0
  73. package/dist/{room → src/room}/track/utils.d.ts +0 -0
  74. package/dist/src/room/track/utils.d.ts.map +1 -0
  75. package/dist/{room → src/room}/utils.d.ts +0 -0
  76. package/dist/src/room/utils.d.ts.map +1 -0
  77. package/dist/{test → src/test}/MockMediaStreamTrack.d.ts +0 -0
  78. package/dist/src/test/MockMediaStreamTrack.d.ts.map +1 -0
  79. package/dist/{test → src/test}/mocks.d.ts +0 -0
  80. package/dist/src/test/mocks.d.ts.map +1 -0
  81. package/dist/src/version.d.ts +3 -0
  82. package/dist/src/version.d.ts.map +1 -0
  83. package/package.json +5 -2
  84. package/src/api/SignalClient.ts +2 -2
  85. package/src/proto/livekit_models.ts +90 -0
  86. package/src/proto/livekit_rtc.ts +235 -1
  87. package/src/room/RTCEngine.ts +30 -2
  88. package/src/room/Room.ts +60 -15
  89. package/src/room/events.ts +5 -0
  90. package/src/room/participant/LocalParticipant.ts +104 -23
  91. package/src/room/participant/RemoteParticipant.ts +1 -0
  92. package/src/room/stats.ts +2 -0
  93. package/src/room/track/LocalAudioTrack.ts +4 -0
  94. package/src/room/track/LocalTrack.ts +12 -5
  95. package/src/room/track/LocalVideoTrack.ts +143 -55
  96. package/src/room/track/RemoteTrack.ts +0 -2
  97. package/src/room/track/RemoteVideoTrack.ts +6 -0
  98. package/src/room/track/Track.ts +5 -0
  99. package/src/room/track/options.ts +2 -1
  100. package/src/version.ts +4 -2
  101. package/dist/api/RequestQueue.d.ts.map +0 -1
  102. package/dist/api/SignalClient.d.ts.map +0 -1
  103. package/dist/index.d.ts.map +0 -1
  104. package/dist/logger.d.ts.map +0 -1
  105. package/dist/options.d.ts.map +0 -1
  106. package/dist/proto/google/protobuf/timestamp.d.ts.map +0 -1
  107. package/dist/proto/livekit_models.d.ts.map +0 -1
  108. package/dist/proto/livekit_rtc.d.ts.map +0 -1
  109. package/dist/room/DeviceManager.d.ts.map +0 -1
  110. package/dist/room/PCTransport.d.ts.map +0 -1
  111. package/dist/room/RTCEngine.d.ts.map +0 -1
  112. package/dist/room/Room.d.ts.map +0 -1
  113. package/dist/room/errors.d.ts.map +0 -1
  114. package/dist/room/events.d.ts.map +0 -1
  115. package/dist/room/participant/LocalParticipant.d.ts.map +0 -1
  116. package/dist/room/participant/Participant.d.ts.map +0 -1
  117. package/dist/room/participant/ParticipantTrackPermission.d.ts.map +0 -1
  118. package/dist/room/participant/RemoteParticipant.d.ts.map +0 -1
  119. package/dist/room/participant/publishUtils.d.ts.map +0 -1
  120. package/dist/room/stats.d.ts.map +0 -1
  121. package/dist/room/track/LocalAudioTrack.d.ts.map +0 -1
  122. package/dist/room/track/LocalTrack.d.ts.map +0 -1
  123. package/dist/room/track/LocalTrackPublication.d.ts.map +0 -1
  124. package/dist/room/track/LocalVideoTrack.d.ts.map +0 -1
  125. package/dist/room/track/RemoteAudioTrack.d.ts.map +0 -1
  126. package/dist/room/track/RemoteTrack.d.ts.map +0 -1
  127. package/dist/room/track/RemoteTrackPublication.d.ts.map +0 -1
  128. package/dist/room/track/RemoteVideoTrack.d.ts.map +0 -1
  129. package/dist/room/track/Track.d.ts.map +0 -1
  130. package/dist/room/track/TrackPublication.d.ts.map +0 -1
  131. package/dist/room/track/create.d.ts.map +0 -1
  132. package/dist/room/track/defaults.d.ts.map +0 -1
  133. package/dist/room/track/options.d.ts.map +0 -1
  134. package/dist/room/track/types.d.ts.map +0 -1
  135. package/dist/room/track/utils.d.ts.map +0 -1
  136. package/dist/room/utils.d.ts.map +0 -1
  137. package/dist/test/MockMediaStreamTrack.d.ts.map +0 -1
  138. package/dist/test/mocks.d.ts.map +0 -1
  139. package/dist/version.d.ts +0 -3
  140. package/dist/version.d.ts.map +0 -1
@@ -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
 
@@ -9462,6 +9811,11 @@ var RoomEvent;
9462
9811
  */
9463
9812
 
9464
9813
  RoomEvent["ParticipantPermissionsChanged"] = "participantPermissionsChanged";
9814
+ /**
9815
+ * Signal connected, can publish tracks.
9816
+ */
9817
+
9818
+ RoomEvent["SignalConnected"] = "signalConnected";
9465
9819
  })(RoomEvent || (RoomEvent = {}));
9466
9820
 
9467
9821
  var ParticipantEvent;
@@ -9704,83 +10058,10 @@ function computeBitrate(currentStats, prevStats) {
9704
10058
  return (bytesNow - bytesPrev) * 8 * 1000 / (currentStats.timestamp - prevStats.timestamp);
9705
10059
  }
9706
10060
 
9707
- const defaultId = 'default';
9708
- class DeviceManager {
9709
- static getInstance() {
9710
- if (this.instance === undefined) {
9711
- this.instance = new DeviceManager();
9712
- }
9713
-
9714
- return this.instance;
9715
- }
9716
-
9717
- async getDevices(kind) {
9718
- let requestPermissions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
9719
- let devices = await navigator.mediaDevices.enumerateDevices();
9720
-
9721
- if (requestPermissions) {
9722
- const isDummyDeviceOrEmpty = devices.length === 0 || devices.some(device => {
9723
- const noLabel = device.label === '';
9724
- const isRelevant = kind ? device.kind === kind : true;
9725
- return noLabel && isRelevant;
9726
- });
9727
-
9728
- if (isDummyDeviceOrEmpty) {
9729
- const permissionsToAcquire = {
9730
- video: kind !== 'audioinput' && kind !== 'audiooutput',
9731
- audio: kind !== 'videoinput'
9732
- };
9733
- const stream = await navigator.mediaDevices.getUserMedia(permissionsToAcquire);
9734
- devices = await navigator.mediaDevices.enumerateDevices();
9735
- stream.getTracks().forEach(track => {
9736
- track.stop();
9737
- });
9738
- }
9739
- }
9740
-
9741
- if (kind) {
9742
- devices = devices.filter(device => device.kind === kind);
9743
- } // Chrome returns 'default' devices, we would filter them out, but put the default
9744
- // device at first
9745
- // we would only do this if there are more than 1 device though
9746
-
9747
-
9748
- if (devices.length > 1 && devices[0].deviceId === defaultId) {
9749
- // find another device with matching group id, and move that to 0
9750
- const defaultDevice = devices[0];
9751
-
9752
- for (let i = 1; i < devices.length; i += 1) {
9753
- if (devices[i].groupId === defaultDevice.groupId) {
9754
- const temp = devices[0];
9755
- devices[0] = devices[i];
9756
- devices[i] = temp;
9757
- break;
9758
- }
9759
- }
9760
-
9761
- return devices.filter(device => device !== defaultDevice);
9762
- }
9763
-
9764
- return devices;
9765
- }
9766
-
9767
- async normalizeDeviceId(kind, deviceId, groupId) {
9768
- if (deviceId !== defaultId) {
9769
- return deviceId;
9770
- } // resolve actual device id if it's 'default': Chrome returns it when no
9771
- // device has been chosen
9772
-
9773
-
9774
- const devices = await this.getDevices(kind);
9775
- const device = devices.find(d => d.groupId === groupId && d.deviceId !== defaultId);
9776
- return device === null || device === void 0 ? void 0 : device.deviceId;
9777
- }
9778
-
9779
- }
9780
- DeviceManager.mediaDeviceKinds = ['audioinput', 'audiooutput', 'videoinput'];
9781
-
9782
- const version = '1.0.1';
9783
- const protocolVersion = 7;
10061
+ var version$1 = "1.0.2";
10062
+
10063
+ const version = version$1;
10064
+ const protocolVersion = 8;
9784
10065
 
9785
10066
  const separator = '|';
9786
10067
  function unpackStreamId(packed) {
@@ -9887,6 +10168,81 @@ function getEmptyAudioStreamTrack() {
9887
10168
  return emptyAudioStreamTrack;
9888
10169
  }
9889
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
+
9890
10246
  var events = {exports: {}};
9891
10247
 
9892
10248
  var R = typeof Reflect === 'object' ? Reflect : null;
@@ -10341,6 +10697,11 @@ class Track extends events.exports.EventEmitter {
10341
10697
  super();
10342
10698
  this.attachedElements = [];
10343
10699
  this.isMuted = false;
10700
+ /**
10701
+ * indicates current state of stream
10702
+ */
10703
+
10704
+ this.streamState = Track.StreamState.Active;
10344
10705
  this._currentBitrate = 0;
10345
10706
 
10346
10707
  this.appVisibilityChangedListener = () => {
@@ -10780,7 +11141,11 @@ class LocalTrack extends Track {
10780
11141
 
10781
11142
  track.addEventListener('ended', this.handleEnded);
10782
11143
  livekitLogger.debug('replace MediaStreamTrack');
10783
- await this.sender.replaceTrack(track);
11144
+
11145
+ if (this.sender) {
11146
+ await this.sender.replaceTrack(track);
11147
+ }
11148
+
10784
11149
  this._mediaStreamTrack = track;
10785
11150
  this.attachedElements.forEach(el => {
10786
11151
  attachToElement(track, el);
@@ -10790,10 +11155,6 @@ class LocalTrack extends Track {
10790
11155
  }
10791
11156
 
10792
11157
  async restart(constraints) {
10793
- if (!this.sender) {
10794
- throw new TrackInvalidError('unable to restart an unpublished track');
10795
- }
10796
-
10797
11158
  if (!constraints) {
10798
11159
  constraints = this.constraints;
10799
11160
  }
@@ -10827,7 +11188,12 @@ class LocalTrack extends Track {
10827
11188
  const newTrack = mediaStream.getTracks()[0];
10828
11189
  newTrack.addEventListener('ended', this.handleEnded);
10829
11190
  livekitLogger.debug('re-acquired MediaStreamTrack');
10830
- 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
+
10831
11197
  this._mediaStreamTrack = newTrack;
10832
11198
  this.attachedElements.forEach(el => {
10833
11199
  attachToElement(newTrack, el);
@@ -11101,6 +11467,10 @@ class LocalAudioTrack extends LocalTrack {
11101
11467
 
11102
11468
 
11103
11469
  startMonitor() {
11470
+ if (!isWeb()) {
11471
+ return;
11472
+ }
11473
+
11104
11474
  setTimeout(() => {
11105
11475
  this.monitorSender();
11106
11476
  }, monitorFrequency);
@@ -11147,6 +11517,7 @@ class LocalAudioTrack extends LocalTrack {
11147
11517
  class LocalVideoTrack extends LocalTrack {
11148
11518
  constructor(mediaTrack, constraints) {
11149
11519
  super(mediaTrack, Track.Kind.Video, constraints);
11520
+ this.simulcastCodecs = new Map();
11150
11521
 
11151
11522
  this.monitorSender = async () => {
11152
11523
  if (!this.sender) {
@@ -11198,7 +11569,13 @@ class LocalVideoTrack extends LocalTrack {
11198
11569
  startMonitor(signalClient) {
11199
11570
  var _a;
11200
11571
 
11201
- 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
+
11202
11579
 
11203
11580
  const params = (_a = this.sender) === null || _a === void 0 ? void 0 : _a.getParameters();
11204
11581
 
@@ -11216,6 +11593,11 @@ class LocalVideoTrack extends LocalTrack {
11216
11593
 
11217
11594
  this._mediaStreamTrack.getConstraints();
11218
11595
 
11596
+ this.simulcastCodecs.forEach(trackInfo => {
11597
+ trackInfo.mediaStreamTrack.stop();
11598
+ trackInfo.sender = undefined;
11599
+ });
11600
+ this.simulcastCodecs.clear();
11219
11601
  super.stop();
11220
11602
  }
11221
11603
 
@@ -11325,6 +11707,58 @@ class LocalVideoTrack extends LocalTrack {
11325
11707
 
11326
11708
  await this.restart(constraints);
11327
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
+ }
11328
11762
  /**
11329
11763
  * @internal
11330
11764
  * Sets layers that should be publishing
@@ -11338,77 +11772,87 @@ class LocalVideoTrack extends LocalTrack {
11338
11772
  return;
11339
11773
  }
11340
11774
 
11341
- const params = this.sender.getParameters();
11342
- const {
11343
- encodings
11344
- } = params;
11775
+ await setPublishingLayersForSender(this.sender, this.encodings, qualities);
11776
+ }
11345
11777
 
11346
- if (!encodings) {
11347
- return;
11348
- }
11778
+ async handleAppVisibilityChanged() {
11779
+ await super.handleAppVisibilityChanged();
11780
+ if (!isMobile()) return;
11349
11781
 
11350
- if (encodings.length !== this.encodings.length) {
11351
- livekitLogger.warn('cannot set publishing layers, encodings mismatch');
11352
- return;
11782
+ if (this.isInBackground && this.source === Track.Source.Camera) {
11783
+ this._mediaStreamTrack.enabled = false;
11353
11784
  }
11785
+ }
11354
11786
 
11355
- let hasChanged = false;
11356
- encodings.forEach((encoding, idx) => {
11357
- var _a;
11358
-
11359
- let rid = (_a = encoding.rid) !== null && _a !== void 0 ? _a : '';
11787
+ }
11360
11788
 
11361
- if (rid === '') {
11362
- rid = 'q';
11363
- }
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;
11364
11799
 
11365
- const quality = videoQualityForRid(rid);
11366
- const subscribedQuality = qualities.find(q => q.quality === quality);
11800
+ if (!encodings) {
11801
+ return;
11802
+ }
11367
11803
 
11368
- if (!subscribedQuality) {
11369
- return;
11370
- }
11804
+ if (encodings.length !== senderEncodings.length) {
11805
+ livekitLogger.warn('cannot set publishing layers, encodings mismatch');
11806
+ return;
11807
+ }
11371
11808
 
11372
- if (encoding.active !== subscribedQuality.enabled) {
11373
- hasChanged = true;
11374
- encoding.active = subscribedQuality.enabled;
11375
- livekitLogger.debug("setting layer ".concat(subscribedQuality.quality, " to ").concat(encoding.active ? 'enabled' : 'disabled')); // FireFox does not support setting encoding.active to false, so we
11376
- // have a workaround of lowering its bitrate and resolution to the min.
11809
+ let hasChanged = false;
11810
+ encodings.forEach((encoding, idx) => {
11811
+ var _a;
11377
11812
 
11378
- if (isFireFox()) {
11379
- if (subscribedQuality.enabled) {
11380
- encoding.scaleResolutionDownBy = this.encodings[idx].scaleResolutionDownBy;
11381
- encoding.maxBitrate = this.encodings[idx].maxBitrate;
11382
- /* @ts-ignore */
11813
+ let rid = (_a = encoding.rid) !== null && _a !== void 0 ? _a : '';
11383
11814
 
11384
- encoding.maxFrameRate = this.encodings[idx].maxFrameRate;
11385
- } else {
11386
- encoding.scaleResolutionDownBy = 4;
11387
- encoding.maxBitrate = 10;
11388
- /* @ts-ignore */
11815
+ if (rid === '') {
11816
+ rid = 'q';
11817
+ }
11389
11818
 
11390
- encoding.maxFrameRate = 2;
11391
- }
11392
- }
11393
- }
11394
- });
11819
+ const quality = videoQualityForRid(rid);
11820
+ const subscribedQuality = qualities.find(q => q.quality === quality);
11395
11821
 
11396
- if (hasChanged) {
11397
- params.encodings = encodings;
11398
- await this.sender.setParameters(params);
11822
+ if (!subscribedQuality) {
11823
+ return;
11399
11824
  }
11400
- }
11401
11825
 
11402
- async handleAppVisibilityChanged() {
11403
- await super.handleAppVisibilityChanged();
11404
- 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.
11405
11831
 
11406
- if (this.isInBackground && this.source === Track.Source.Camera) {
11407
- 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
+ }
11408
11847
  }
11409
- }
11848
+ });
11410
11849
 
11850
+ if (hasChanged) {
11851
+ params.encodings = encodings;
11852
+ await sender.setParameters(params);
11853
+ }
11411
11854
  }
11855
+
11412
11856
  function videoQualityForRid(rid) {
11413
11857
  switch (rid) {
11414
11858
  case 'f':
@@ -11459,7 +11903,6 @@ function videoLayersFromEncodings(width, height, encodings) {
11459
11903
  class RemoteTrack extends Track {
11460
11904
  constructor(mediaTrack, sid, kind, receiver) {
11461
11905
  super(mediaTrack, kind);
11462
- this.streamState = Track.StreamState.Active;
11463
11906
  this.sid = sid;
11464
11907
  this.receiver = receiver;
11465
11908
  }
@@ -11781,6 +12224,14 @@ class RemoteVideoTrack extends RemoteTrack {
11781
12224
 
11782
12225
  return detachedElements;
11783
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
+ }
11784
12235
 
11785
12236
  async getReceiverStats() {
11786
12237
  if (!this.receiver) {
@@ -11805,7 +12256,8 @@ class RemoteVideoTrack extends RemoteTrack {
11805
12256
  nackCount: v.nackCount,
11806
12257
  jitter: v.jitter,
11807
12258
  timestamp: v.timestamp,
11808
- bytesReceived: v.bytesReceived
12259
+ bytesReceived: v.bytesReceived,
12260
+ decoderImplementation: v.decoderImplementation
11809
12261
  };
11810
12262
  }
11811
12263
  });
@@ -12915,6 +13367,7 @@ class RemoteParticipant extends Participant {
12915
13367
  super.addTrackPublication(publication); // register action events
12916
13368
 
12917
13369
  publication.on(TrackEvent.UpdateSettings, settings => {
13370
+ livekitLogger.debug('send update settings', settings);
12918
13371
  this.signalClient.sendUpdateTrackSettings(settings);
12919
13372
  });
12920
13373
  publication.on(TrackEvent.UpdateSubscription, sub => {
@@ -13152,13 +13605,25 @@ class RemoteParticipant extends Participant {
13152
13605
 
13153
13606
  }
13154
13607
 
13608
+ const compatibleCodecForSVC = 'vp8';
13155
13609
  class LocalParticipant extends Participant {
13156
13610
  /** @internal */
13157
13611
  constructor(sid, identity, engine, options) {
13158
13612
  super(sid, identity);
13159
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
+ };
13160
13624
  /** @internal */
13161
13625
 
13626
+
13162
13627
  this.onTrackUnmuted = track => {
13163
13628
  this.onTrackMuted(track, track.isUpstreamPaused);
13164
13629
  }; // when the local track changes in mute status, we'll notify server as such
@@ -13190,7 +13655,7 @@ class LocalParticipant extends Participant {
13190
13655
  };
13191
13656
 
13192
13657
  this.handleSubscribedQualityUpdate = update => {
13193
- var _a, _b;
13658
+ var _a, _b, _c;
13194
13659
 
13195
13660
  if (!((_a = this.roomOptions) === null || _a === void 0 ? void 0 : _a.dynacast)) {
13196
13661
  return;
@@ -13206,7 +13671,11 @@ class LocalParticipant extends Participant {
13206
13671
  return;
13207
13672
  }
13208
13673
 
13209
- (_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
+ }
13210
13679
  };
13211
13680
 
13212
13681
  this.handleLocalTrackUnpublished = unpublished => {
@@ -13223,7 +13692,10 @@ class LocalParticipant extends Participant {
13223
13692
  this.unpublishTrack(track.track);
13224
13693
  };
13225
13694
 
13226
- this.onTrackUnpublish = track => {
13695
+ this.handleTrackEnded = track => {
13696
+ livekitLogger.debug('unpublishing local track due to TrackEnded', {
13697
+ track: track.sid
13698
+ });
13227
13699
  this.unpublishTrack(track);
13228
13700
  };
13229
13701
 
@@ -13249,6 +13721,7 @@ class LocalParticipant extends Participant {
13249
13721
 
13250
13722
  this.engine.client.onSubscribedQualityUpdate = this.handleSubscribedQualityUpdate;
13251
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);
13252
13725
  }
13253
13726
 
13254
13727
  get lastCameraError() {
@@ -13591,7 +14064,7 @@ class LocalParticipant extends Participant {
13591
14064
 
13592
14065
  track.on(TrackEvent.Muted, this.onTrackMuted);
13593
14066
  track.on(TrackEvent.Unmuted, this.onTrackUnmuted);
13594
- track.on(TrackEvent.Ended, this.onTrackUnpublish);
14067
+ track.on(TrackEvent.Ended, this.handleTrackEnded);
13595
14068
  track.on(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
13596
14069
  track.on(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed); // create track publication from track
13597
14070
 
@@ -13606,6 +14079,8 @@ class LocalParticipant extends Participant {
13606
14079
  }); // compute encodings and layers for video
13607
14080
 
13608
14081
  let encodings;
14082
+ let simEncodings;
14083
+ let simulcastTracks;
13609
14084
 
13610
14085
  if (track.kind === Track.Kind.Video) {
13611
14086
  // TODO: support react native, which doesn't expose getSettings
@@ -13614,21 +14089,32 @@ class LocalParticipant extends Participant {
13614
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
13615
14090
 
13616
14091
  req.width = width !== null && width !== void 0 ? width : 0;
13617
- req.height = height !== null && height !== void 0 ? height : 0; // for svc codecs, disable simulcast and enable scalability L3T3
13618
- // by default
13619
-
13620
- if (track instanceof LocalVideoTrack) {
13621
- if ((opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'vp9' || (opts === null || opts === void 0 ? void 0 : opts.videoCodec) === 'av1') {
13622
- opts.simulcast = false;
13623
- opts.scalabilityMode = (_g = opts.scalabilityMode) !== null && _g !== void 0 ? _g : 'L3T3';
13624
- } else {
13625
- // other codecs, unset scalability
13626
- opts.scalabilityMode = undefined;
13627
- }
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
+ }];
13628
14114
  }
13629
14115
 
13630
14116
  encodings = computeVideoEncodings(track.source === Track.Source.ScreenShare, width, height, opts);
13631
- req.layers = videoLayersFromEncodings(req.width, req.height, encodings);
14117
+ req.layers = videoLayersFromEncodings(req.width, req.height, simEncodings !== null && simEncodings !== void 0 ? simEncodings : encodings);
13632
14118
  } else if (track.kind === Track.Kind.Audio && opts.audioBitrate) {
13633
14119
  encodings = [{
13634
14120
  maxBitrate: opts.audioBitrate
@@ -13640,7 +14126,9 @@ class LocalParticipant extends Participant {
13640
14126
  }
13641
14127
 
13642
14128
  const ti = await this.engine.addTrack(req);
13643
- 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;
13644
14132
  track.sid = ti.sid;
13645
14133
 
13646
14134
  if (!this.engine.publisher) {
@@ -13657,12 +14145,32 @@ class LocalParticipant extends Participant {
13657
14145
 
13658
14146
  if (encodings) {
13659
14147
  transceiverInit.sendEncodings = encodings;
13660
- }
14148
+ } // addTransceiver for react-native is async. web is synchronous, but await won't effect it.
13661
14149
 
13662
- const transceiver = this.engine.publisher.pc.addTransceiver(track.mediaStreamTrack, transceiverInit);
13663
14150
 
13664
- if (opts.videoCodec) {
14151
+ const transceiver = await this.engine.publisher.pc.addTransceiver(track.mediaStreamTrack, transceiverInit);
14152
+
14153
+ if (track.kind === Track.Kind.Video && opts.videoCodec) {
13665
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
+ }
13666
14174
  }
13667
14175
 
13668
14176
  this.engine.negotiate(); // store RTPSender
@@ -13700,9 +14208,10 @@ class LocalParticipant extends Participant {
13700
14208
  }
13701
14209
 
13702
14210
  track = publication.track;
14211
+ track.sender = undefined;
13703
14212
  track.off(TrackEvent.Muted, this.onTrackMuted);
13704
14213
  track.off(TrackEvent.Unmuted, this.onTrackUnmuted);
13705
- track.off(TrackEvent.Ended, this.onTrackUnpublish);
14214
+ track.off(TrackEvent.Ended, this.handleTrackEnded);
13706
14215
  track.off(TrackEvent.UpstreamPaused, this.onTrackUpstreamPaused);
13707
14216
  track.off(TrackEvent.UpstreamResumed, this.onTrackUpstreamResumed);
13708
14217
 
@@ -13718,7 +14227,7 @@ class LocalParticipant extends Participant {
13718
14227
  mediaStreamTrack
13719
14228
  } = track;
13720
14229
 
13721
- if (this.engine.publisher) {
14230
+ if (this.engine.publisher && this.engine.publisher.pc.connectionState !== 'closed') {
13722
14231
  const senders = this.engine.publisher.pc.getSenders();
13723
14232
  senders.forEach(sender => {
13724
14233
  var _a;
@@ -13823,7 +14332,12 @@ class LocalParticipant extends Participant {
13823
14332
 
13824
14333
  setTrackSubscriptionPermissions(allParticipantsAllowed) {
13825
14334
  let participantTrackPermissions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
13826
- 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
+ }
13827
14341
  }
13828
14342
 
13829
14343
  getPublicationForTrack(track) {
@@ -13856,6 +14370,7 @@ class LocalParticipant extends Participant {
13856
14370
 
13857
14371
  const cap = RTCRtpSender.getCapabilities(kind);
13858
14372
  if (!cap) return;
14373
+ livekitLogger.debug('get capabilities', cap);
13859
14374
  let selected;
13860
14375
  const codecs = [];
13861
14376
  cap.codecs.forEach(c => {
@@ -17705,8 +18220,8 @@ class SignalClient {
17705
18220
  });
17706
18221
  }
17707
18222
 
17708
- sendLeave() {
17709
- this.sendRequest(SignalRequest.fromPartial({
18223
+ async sendLeave() {
18224
+ await this.sendRequest(SignalRequest.fromPartial({
17710
18225
  leave: {}
17711
18226
  }));
17712
18227
  }
@@ -18015,6 +18530,7 @@ class RTCEngine extends events.exports.EventEmitter {
18015
18530
  this.reconnectAttempts = 0;
18016
18531
  this.reconnectStart = 0;
18017
18532
  this.fullReconnectOnNext = false;
18533
+ this.attemptingReconnect = false;
18018
18534
 
18019
18535
  this.handleDataChannel = async _ref => {
18020
18536
  let {
@@ -18091,18 +18607,27 @@ class RTCEngine extends events.exports.EventEmitter {
18091
18607
 
18092
18608
  const delay = this.reconnectAttempts * this.reconnectAttempts * 300;
18093
18609
  setTimeout(async () => {
18094
- var _a;
18610
+ var _a, _b, _c;
18095
18611
 
18096
18612
  if (this._isClosed) {
18097
18613
  return;
18614
+ } // guard for attempting reconnection multiple times while one attempt is still not finished
18615
+
18616
+
18617
+ if (this.attemptingReconnect) {
18618
+ return;
18098
18619
  }
18099
18620
 
18100
18621
  if (isFireFox() || // TODO remove once clientConfiguration handles firefox case server side
18101
- ((_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') {
18102
18625
  this.fullReconnectOnNext = true;
18103
18626
  }
18104
18627
 
18105
18628
  try {
18629
+ this.attemptingReconnect = true;
18630
+
18106
18631
  if (this.fullReconnectOnNext) {
18107
18632
  await this.restartConnection();
18108
18633
  } else {
@@ -18113,6 +18638,7 @@ class RTCEngine extends events.exports.EventEmitter {
18113
18638
  this.fullReconnectOnNext = false;
18114
18639
  } catch (e) {
18115
18640
  this.reconnectAttempts += 1;
18641
+ let reconnectRequired = false;
18116
18642
  let recoverable = true;
18117
18643
 
18118
18644
  if (e instanceof UnexpectedConnectionState) {
@@ -18123,7 +18649,14 @@ class RTCEngine extends events.exports.EventEmitter {
18123
18649
  recoverable = false;
18124
18650
  } else if (!(e instanceof SignalReconnectError)) {
18125
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) {
18126
18658
  this.fullReconnectOnNext = true;
18659
+ this.reconnectAttempts = 0;
18127
18660
  }
18128
18661
 
18129
18662
  const duration = Date.now() - this.reconnectStart;
@@ -18139,6 +18672,8 @@ class RTCEngine extends events.exports.EventEmitter {
18139
18672
  this.emit(EngineEvent.Disconnected);
18140
18673
  this.close();
18141
18674
  }
18675
+ } finally {
18676
+ this.attemptingReconnect = false;
18142
18677
  }
18143
18678
  }, delay);
18144
18679
  };
@@ -18287,7 +18822,7 @@ class RTCEngine extends events.exports.EventEmitter {
18287
18822
  this.primaryPC = primaryPC;
18288
18823
 
18289
18824
  primaryPC.onconnectionstatechange = async () => {
18290
- livekitLogger.trace('connection state changed', {
18825
+ livekitLogger.debug('primary PC state changed', {
18291
18826
  state: primaryPC.connectionState
18292
18827
  });
18293
18828
 
@@ -18316,7 +18851,10 @@ class RTCEngine extends events.exports.EventEmitter {
18316
18851
  };
18317
18852
 
18318
18853
  secondaryPC.onconnectionstatechange = async () => {
18319
- // 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
+
18320
18858
  if (secondaryPC.connectionState === 'failed') {
18321
18859
  this.handleDisconnect('secondary peerconnection');
18322
18860
  }
@@ -18444,6 +18982,11 @@ class RTCEngine extends events.exports.EventEmitter {
18444
18982
  this.emit(EngineEvent.Restarting);
18445
18983
  }
18446
18984
 
18985
+ if (this.client.isConnected) {
18986
+ this.client.sendLeave();
18987
+ }
18988
+
18989
+ this.client.close();
18447
18990
  this.primaryPC = undefined;
18448
18991
  (_a = this.publisher) === null || _a === void 0 ? void 0 : _a.close();
18449
18992
  this.publisher = undefined;
@@ -18806,6 +19349,7 @@ class Room extends events.exports.EventEmitter {
18806
19349
  this.name = joinResponse.room.name;
18807
19350
  this.sid = joinResponse.room.sid;
18808
19351
  this.metadata = joinResponse.room.metadata;
19352
+ this.emit(RoomEvent.SignalConnected);
18809
19353
  } catch (err) {
18810
19354
  this.engine.close();
18811
19355
  this.setAndEmitConnectionState(ConnectionState.Disconnected);
@@ -18860,7 +19404,7 @@ class Room extends events.exports.EventEmitter {
18860
19404
  this.disconnect = function () {
18861
19405
  let stopTracks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
18862
19406
 
18863
- var _a;
19407
+ var _a, _b;
18864
19408
 
18865
19409
  if (_this.state === ConnectionState.Connecting) {
18866
19410
  // try aborting pending connection attempt
@@ -18870,9 +19414,12 @@ class Room extends events.exports.EventEmitter {
18870
19414
  } // send leave
18871
19415
 
18872
19416
 
18873
- if (_this.engine) {
19417
+ if ((_b = _this.engine) === null || _b === void 0 ? void 0 : _b.client.isConnected) {
18874
19418
  _this.engine.client.sendLeave();
19419
+ } // close engine (also closes client)
18875
19420
 
19421
+
19422
+ if (_this.engine) {
18876
19423
  _this.engine.close();
18877
19424
  }
18878
19425
 
@@ -18888,8 +19435,10 @@ class Room extends events.exports.EventEmitter {
18888
19435
  };
18889
19436
 
18890
19437
  this.handleRestarting = () => {
18891
- this.setAndEmitConnectionState(ConnectionState.Reconnecting);
18892
- this.emit(RoomEvent.Reconnecting); // 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
+
18893
19442
 
18894
19443
  for (const p of this.participants.values()) {
18895
19444
  this.handleParticipantDisconnected(p.sid, p);
@@ -18897,7 +19446,9 @@ class Room extends events.exports.EventEmitter {
18897
19446
  };
18898
19447
 
18899
19448
  this.handleRestarted = async joinResponse => {
18900
- livekitLogger.debug("reconnected to server region ".concat(joinResponse.serverRegion));
19449
+ livekitLogger.debug("reconnected to server", {
19450
+ region: joinResponse.serverRegion
19451
+ });
18901
19452
  this.setAndEmitConnectionState(ConnectionState.Connected);
18902
19453
  this.emit(RoomEvent.Reconnected); // rehydrate participants
18903
19454
 
@@ -18918,7 +19469,19 @@ class Room extends events.exports.EventEmitter {
18918
19469
  await Promise.all(localPubs.map(async pub => {
18919
19470
  const track = pub.track;
18920
19471
  this.localParticipant.unpublishTrack(track, false);
18921
- 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
+ }
18922
19485
  }));
18923
19486
  };
18924
19487
 
@@ -18928,6 +19491,14 @@ class Room extends events.exports.EventEmitter {
18928
19491
  if (info.sid === this.localParticipant.sid || info.identity === this.localParticipant.identity) {
18929
19492
  this.localParticipant.updateInfo(info);
18930
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));
18931
19502
  }
18932
19503
 
18933
19504
  let remoteParticipant = this.participants.get(info.sid);
@@ -18938,7 +19509,8 @@ class Room extends events.exports.EventEmitter {
18938
19509
  if (info.state === ParticipantInfo_State.DISCONNECTED) {
18939
19510
  this.handleParticipantDisconnected(info.sid, remoteParticipant);
18940
19511
  } else if (isNewParticipant) {
18941
- // fire connected event
19512
+ this.identityToSid.set(info.identity, info.sid); // fire connected event
19513
+
18942
19514
  this.emit(RoomEvent.ParticipantConnected, remoteParticipant);
18943
19515
  } else {
18944
19516
  // just update, no events
@@ -19107,6 +19679,7 @@ class Room extends events.exports.EventEmitter {
19107
19679
  };
19108
19680
 
19109
19681
  this.participants = new Map();
19682
+ this.identityToSid = new Map();
19110
19683
  this.options = options || {};
19111
19684
 
19112
19685
  switch ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.publishDefaults) === null || _b === void 0 ? void 0 : _b.videoCodec) {
@@ -19141,8 +19714,9 @@ class Room extends events.exports.EventEmitter {
19141
19714
  }).on(EngineEvent.Disconnected, () => {
19142
19715
  this.handleDisconnect();
19143
19716
  }).on(EngineEvent.ActiveSpeakersUpdate, this.handleActiveSpeakersUpdate).on(EngineEvent.DataPacketReceived, this.handleDataPacket).on(EngineEvent.Resuming, () => {
19144
- this.setAndEmitConnectionState(ConnectionState.Reconnecting);
19145
- this.emit(RoomEvent.Reconnecting);
19717
+ if (this.setAndEmitConnectionState(ConnectionState.Reconnecting)) {
19718
+ this.emit(RoomEvent.Reconnecting);
19719
+ }
19146
19720
  }).on(EngineEvent.Resumed, () => {
19147
19721
  this.setAndEmitConnectionState(ConnectionState.Connected);
19148
19722
  this.emit(RoomEvent.Reconnected);
@@ -19175,15 +19749,15 @@ class Room extends events.exports.EventEmitter {
19175
19749
 
19176
19750
 
19177
19751
  getParticipantByIdentity(identity) {
19178
- for (const [, p] of this.participants) {
19179
- if (p.identity === identity) {
19180
- return p;
19181
- }
19182
- }
19183
-
19184
19752
  if (this.localParticipant.identity === identity) {
19185
19753
  return this.localParticipant;
19186
19754
  }
19755
+
19756
+ const sid = this.identityToSid.get(identity);
19757
+
19758
+ if (sid) {
19759
+ return this.participants.get(sid);
19760
+ }
19187
19761
  }
19188
19762
  /**
19189
19763
  * @internal for testing
@@ -19191,6 +19765,8 @@ class Room extends events.exports.EventEmitter {
19191
19765
 
19192
19766
 
19193
19767
  simulateScenario(scenario) {
19768
+ let postAction = () => {};
19769
+
19194
19770
  let req;
19195
19771
 
19196
19772
  switch (scenario) {
@@ -19217,10 +19793,26 @@ class Room extends events.exports.EventEmitter {
19217
19793
  migration: true
19218
19794
  });
19219
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;
19220
19811
  }
19221
19812
 
19222
19813
  if (req) {
19223
19814
  this.engine.client.sendSimulateScenario(req);
19815
+ postAction();
19224
19816
  }
19225
19817
  }
19226
19818
  /**
@@ -19376,8 +19968,9 @@ class Room extends events.exports.EventEmitter {
19376
19968
  return;
19377
19969
  }
19378
19970
 
19971
+ this.identityToSid.delete(participant.identity);
19379
19972
  participant.tracks.forEach(publication => {
19380
- participant.unpublishTrack(publication.trackSid);
19973
+ participant.unpublishTrack(publication.trackSid, true);
19381
19974
  });
19382
19975
  this.emit(RoomEvent.ParticipantDisconnected, participant);
19383
19976
  }
@@ -19505,11 +20098,13 @@ class Room extends events.exports.EventEmitter {
19505
20098
 
19506
20099
  setAndEmitConnectionState(state) {
19507
20100
  if (state === this.state) {
19508
- return;
20101
+ // unchanged
20102
+ return false;
19509
20103
  }
19510
20104
 
19511
20105
  this.state = state;
19512
20106
  this.emit(RoomEvent.ConnectionStateChanged, this.state);
20107
+ return true;
19513
20108
  } // /** @internal */
19514
20109
 
19515
20110