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
@@ -89,6 +89,38 @@ export function streamStateToJSON(object: StreamState): string {
89
89
  }
90
90
  }
91
91
 
92
+ export enum CandidateProtocol {
93
+ UDP = 0,
94
+ TCP = 1,
95
+ UNRECOGNIZED = -1,
96
+ }
97
+
98
+ export function candidateProtocolFromJSON(object: any): CandidateProtocol {
99
+ switch (object) {
100
+ case 0:
101
+ case 'UDP':
102
+ return CandidateProtocol.UDP;
103
+ case 1:
104
+ case 'TCP':
105
+ return CandidateProtocol.TCP;
106
+ case -1:
107
+ case 'UNRECOGNIZED':
108
+ default:
109
+ return CandidateProtocol.UNRECOGNIZED;
110
+ }
111
+ }
112
+
113
+ export function candidateProtocolToJSON(object: CandidateProtocol): string {
114
+ switch (object) {
115
+ case CandidateProtocol.UDP:
116
+ return 'UDP';
117
+ case CandidateProtocol.TCP:
118
+ return 'TCP';
119
+ default:
120
+ return 'UNKNOWN';
121
+ }
122
+ }
123
+
92
124
  export interface SignalRequest {
93
125
  /** initial join exchange, for publisher */
94
126
  offer?: SessionDescription | undefined;
@@ -156,6 +188,12 @@ export interface SignalResponse {
156
188
  trackUnpublished?: TrackUnpublishedResponse | undefined;
157
189
  }
158
190
 
191
+ export interface SimulcastCodec {
192
+ codec: string;
193
+ cid: string;
194
+ enableSimulcastLayers: boolean;
195
+ }
196
+
159
197
  export interface AddTrackRequest {
160
198
  /** client ID of track, to match it when RTC track is received */
161
199
  cid: string;
@@ -170,6 +208,7 @@ export interface AddTrackRequest {
170
208
  disableDtx: boolean;
171
209
  source: TrackSource;
172
210
  layers: VideoLayer[];
211
+ simulcastCodecs: SimulcastCodec[];
173
212
  }
174
213
 
175
214
  export interface TrickleRequest {
@@ -289,9 +328,15 @@ export interface SubscribedQuality {
289
328
  enabled: boolean;
290
329
  }
291
330
 
331
+ export interface SubscribedCodec {
332
+ codec: string;
333
+ qualities: SubscribedQuality[];
334
+ }
335
+
292
336
  export interface SubscribedQualityUpdate {
293
337
  trackSid: string;
294
338
  subscribedQualities: SubscribedQuality[];
339
+ subscribedCodecs: SubscribedCodec[];
295
340
  }
296
341
 
297
342
  export interface TrackPermission {
@@ -335,6 +380,8 @@ export interface SimulateScenario {
335
380
  migration: boolean | undefined;
336
381
  /** server to send leave */
337
382
  serverLeave: boolean | undefined;
383
+ /** switch candidate protocol to tcp */
384
+ switchCandidateProtocol: CandidateProtocol | undefined;
338
385
  }
339
386
 
340
387
  function createBaseSignalRequest(): SignalRequest {
@@ -864,6 +911,76 @@ export const SignalResponse = {
864
911
  },
865
912
  };
866
913
 
914
+ function createBaseSimulcastCodec(): SimulcastCodec {
915
+ return { codec: '', cid: '', enableSimulcastLayers: false };
916
+ }
917
+
918
+ export const SimulcastCodec = {
919
+ encode(message: SimulcastCodec, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
920
+ if (message.codec !== '') {
921
+ writer.uint32(10).string(message.codec);
922
+ }
923
+ if (message.cid !== '') {
924
+ writer.uint32(18).string(message.cid);
925
+ }
926
+ if (message.enableSimulcastLayers === true) {
927
+ writer.uint32(24).bool(message.enableSimulcastLayers);
928
+ }
929
+ return writer;
930
+ },
931
+
932
+ decode(input: _m0.Reader | Uint8Array, length?: number): SimulcastCodec {
933
+ const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
934
+ let end = length === undefined ? reader.len : reader.pos + length;
935
+ const message = createBaseSimulcastCodec();
936
+ while (reader.pos < end) {
937
+ const tag = reader.uint32();
938
+ switch (tag >>> 3) {
939
+ case 1:
940
+ message.codec = reader.string();
941
+ break;
942
+ case 2:
943
+ message.cid = reader.string();
944
+ break;
945
+ case 3:
946
+ message.enableSimulcastLayers = reader.bool();
947
+ break;
948
+ default:
949
+ reader.skipType(tag & 7);
950
+ break;
951
+ }
952
+ }
953
+ return message;
954
+ },
955
+
956
+ fromJSON(object: any): SimulcastCodec {
957
+ return {
958
+ codec: isSet(object.codec) ? String(object.codec) : '',
959
+ cid: isSet(object.cid) ? String(object.cid) : '',
960
+ enableSimulcastLayers: isSet(object.enableSimulcastLayers)
961
+ ? Boolean(object.enableSimulcastLayers)
962
+ : false,
963
+ };
964
+ },
965
+
966
+ toJSON(message: SimulcastCodec): unknown {
967
+ const obj: any = {};
968
+ message.codec !== undefined && (obj.codec = message.codec);
969
+ message.cid !== undefined && (obj.cid = message.cid);
970
+ message.enableSimulcastLayers !== undefined &&
971
+ (obj.enableSimulcastLayers = message.enableSimulcastLayers);
972
+ return obj;
973
+ },
974
+
975
+ fromPartial<I extends Exact<DeepPartial<SimulcastCodec>, I>>(object: I): SimulcastCodec {
976
+ const message = createBaseSimulcastCodec();
977
+ message.codec = object.codec ?? '';
978
+ message.cid = object.cid ?? '';
979
+ message.enableSimulcastLayers = object.enableSimulcastLayers ?? false;
980
+ return message;
981
+ },
982
+ };
983
+
867
984
  function createBaseAddTrackRequest(): AddTrackRequest {
868
985
  return {
869
986
  cid: '',
@@ -875,6 +992,7 @@ function createBaseAddTrackRequest(): AddTrackRequest {
875
992
  disableDtx: false,
876
993
  source: 0,
877
994
  layers: [],
995
+ simulcastCodecs: [],
878
996
  };
879
997
  }
880
998
 
@@ -907,6 +1025,9 @@ export const AddTrackRequest = {
907
1025
  for (const v of message.layers) {
908
1026
  VideoLayer.encode(v!, writer.uint32(74).fork()).ldelim();
909
1027
  }
1028
+ for (const v of message.simulcastCodecs) {
1029
+ SimulcastCodec.encode(v!, writer.uint32(82).fork()).ldelim();
1030
+ }
910
1031
  return writer;
911
1032
  },
912
1033
 
@@ -944,6 +1065,9 @@ export const AddTrackRequest = {
944
1065
  case 9:
945
1066
  message.layers.push(VideoLayer.decode(reader, reader.uint32()));
946
1067
  break;
1068
+ case 10:
1069
+ message.simulcastCodecs.push(SimulcastCodec.decode(reader, reader.uint32()));
1070
+ break;
947
1071
  default:
948
1072
  reader.skipType(tag & 7);
949
1073
  break;
@@ -965,6 +1089,9 @@ export const AddTrackRequest = {
965
1089
  layers: Array.isArray(object?.layers)
966
1090
  ? object.layers.map((e: any) => VideoLayer.fromJSON(e))
967
1091
  : [],
1092
+ simulcastCodecs: Array.isArray(object?.simulcastCodecs)
1093
+ ? object.simulcastCodecs.map((e: any) => SimulcastCodec.fromJSON(e))
1094
+ : [],
968
1095
  };
969
1096
  },
970
1097
 
@@ -983,6 +1110,13 @@ export const AddTrackRequest = {
983
1110
  } else {
984
1111
  obj.layers = [];
985
1112
  }
1113
+ if (message.simulcastCodecs) {
1114
+ obj.simulcastCodecs = message.simulcastCodecs.map((e) =>
1115
+ e ? SimulcastCodec.toJSON(e) : undefined,
1116
+ );
1117
+ } else {
1118
+ obj.simulcastCodecs = [];
1119
+ }
986
1120
  return obj;
987
1121
  },
988
1122
 
@@ -997,6 +1131,8 @@ export const AddTrackRequest = {
997
1131
  message.disableDtx = object.disableDtx ?? false;
998
1132
  message.source = object.source ?? 0;
999
1133
  message.layers = object.layers?.map((e) => VideoLayer.fromPartial(e)) || [];
1134
+ message.simulcastCodecs =
1135
+ object.simulcastCodecs?.map((e) => SimulcastCodec.fromPartial(e)) || [];
1000
1136
  return message;
1001
1137
  },
1002
1138
  };
@@ -2284,8 +2420,72 @@ export const SubscribedQuality = {
2284
2420
  },
2285
2421
  };
2286
2422
 
2423
+ function createBaseSubscribedCodec(): SubscribedCodec {
2424
+ return { codec: '', qualities: [] };
2425
+ }
2426
+
2427
+ export const SubscribedCodec = {
2428
+ encode(message: SubscribedCodec, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
2429
+ if (message.codec !== '') {
2430
+ writer.uint32(10).string(message.codec);
2431
+ }
2432
+ for (const v of message.qualities) {
2433
+ SubscribedQuality.encode(v!, writer.uint32(18).fork()).ldelim();
2434
+ }
2435
+ return writer;
2436
+ },
2437
+
2438
+ decode(input: _m0.Reader | Uint8Array, length?: number): SubscribedCodec {
2439
+ const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
2440
+ let end = length === undefined ? reader.len : reader.pos + length;
2441
+ const message = createBaseSubscribedCodec();
2442
+ while (reader.pos < end) {
2443
+ const tag = reader.uint32();
2444
+ switch (tag >>> 3) {
2445
+ case 1:
2446
+ message.codec = reader.string();
2447
+ break;
2448
+ case 2:
2449
+ message.qualities.push(SubscribedQuality.decode(reader, reader.uint32()));
2450
+ break;
2451
+ default:
2452
+ reader.skipType(tag & 7);
2453
+ break;
2454
+ }
2455
+ }
2456
+ return message;
2457
+ },
2458
+
2459
+ fromJSON(object: any): SubscribedCodec {
2460
+ return {
2461
+ codec: isSet(object.codec) ? String(object.codec) : '',
2462
+ qualities: Array.isArray(object?.qualities)
2463
+ ? object.qualities.map((e: any) => SubscribedQuality.fromJSON(e))
2464
+ : [],
2465
+ };
2466
+ },
2467
+
2468
+ toJSON(message: SubscribedCodec): unknown {
2469
+ const obj: any = {};
2470
+ message.codec !== undefined && (obj.codec = message.codec);
2471
+ if (message.qualities) {
2472
+ obj.qualities = message.qualities.map((e) => (e ? SubscribedQuality.toJSON(e) : undefined));
2473
+ } else {
2474
+ obj.qualities = [];
2475
+ }
2476
+ return obj;
2477
+ },
2478
+
2479
+ fromPartial<I extends Exact<DeepPartial<SubscribedCodec>, I>>(object: I): SubscribedCodec {
2480
+ const message = createBaseSubscribedCodec();
2481
+ message.codec = object.codec ?? '';
2482
+ message.qualities = object.qualities?.map((e) => SubscribedQuality.fromPartial(e)) || [];
2483
+ return message;
2484
+ },
2485
+ };
2486
+
2287
2487
  function createBaseSubscribedQualityUpdate(): SubscribedQualityUpdate {
2288
- return { trackSid: '', subscribedQualities: [] };
2488
+ return { trackSid: '', subscribedQualities: [], subscribedCodecs: [] };
2289
2489
  }
2290
2490
 
2291
2491
  export const SubscribedQualityUpdate = {
@@ -2296,6 +2496,9 @@ export const SubscribedQualityUpdate = {
2296
2496
  for (const v of message.subscribedQualities) {
2297
2497
  SubscribedQuality.encode(v!, writer.uint32(18).fork()).ldelim();
2298
2498
  }
2499
+ for (const v of message.subscribedCodecs) {
2500
+ SubscribedCodec.encode(v!, writer.uint32(26).fork()).ldelim();
2501
+ }
2299
2502
  return writer;
2300
2503
  },
2301
2504
 
@@ -2312,6 +2515,9 @@ export const SubscribedQualityUpdate = {
2312
2515
  case 2:
2313
2516
  message.subscribedQualities.push(SubscribedQuality.decode(reader, reader.uint32()));
2314
2517
  break;
2518
+ case 3:
2519
+ message.subscribedCodecs.push(SubscribedCodec.decode(reader, reader.uint32()));
2520
+ break;
2315
2521
  default:
2316
2522
  reader.skipType(tag & 7);
2317
2523
  break;
@@ -2326,6 +2532,9 @@ export const SubscribedQualityUpdate = {
2326
2532
  subscribedQualities: Array.isArray(object?.subscribedQualities)
2327
2533
  ? object.subscribedQualities.map((e: any) => SubscribedQuality.fromJSON(e))
2328
2534
  : [],
2535
+ subscribedCodecs: Array.isArray(object?.subscribedCodecs)
2536
+ ? object.subscribedCodecs.map((e: any) => SubscribedCodec.fromJSON(e))
2537
+ : [],
2329
2538
  };
2330
2539
  },
2331
2540
 
@@ -2339,6 +2548,13 @@ export const SubscribedQualityUpdate = {
2339
2548
  } else {
2340
2549
  obj.subscribedQualities = [];
2341
2550
  }
2551
+ if (message.subscribedCodecs) {
2552
+ obj.subscribedCodecs = message.subscribedCodecs.map((e) =>
2553
+ e ? SubscribedCodec.toJSON(e) : undefined,
2554
+ );
2555
+ } else {
2556
+ obj.subscribedCodecs = [];
2557
+ }
2342
2558
  return obj;
2343
2559
  },
2344
2560
 
@@ -2349,6 +2565,8 @@ export const SubscribedQualityUpdate = {
2349
2565
  message.trackSid = object.trackSid ?? '';
2350
2566
  message.subscribedQualities =
2351
2567
  object.subscribedQualities?.map((e) => SubscribedQuality.fromPartial(e)) || [];
2568
+ message.subscribedCodecs =
2569
+ object.subscribedCodecs?.map((e) => SubscribedCodec.fromPartial(e)) || [];
2352
2570
  return message;
2353
2571
  },
2354
2572
  };
@@ -2757,6 +2975,7 @@ function createBaseSimulateScenario(): SimulateScenario {
2757
2975
  nodeFailure: undefined,
2758
2976
  migration: undefined,
2759
2977
  serverLeave: undefined,
2978
+ switchCandidateProtocol: undefined,
2760
2979
  };
2761
2980
  }
2762
2981
 
@@ -2774,6 +2993,9 @@ export const SimulateScenario = {
2774
2993
  if (message.serverLeave !== undefined) {
2775
2994
  writer.uint32(32).bool(message.serverLeave);
2776
2995
  }
2996
+ if (message.switchCandidateProtocol !== undefined) {
2997
+ writer.uint32(40).int32(message.switchCandidateProtocol);
2998
+ }
2777
2999
  return writer;
2778
3000
  },
2779
3001
 
@@ -2796,6 +3018,9 @@ export const SimulateScenario = {
2796
3018
  case 4:
2797
3019
  message.serverLeave = reader.bool();
2798
3020
  break;
3021
+ case 5:
3022
+ message.switchCandidateProtocol = reader.int32() as any;
3023
+ break;
2799
3024
  default:
2800
3025
  reader.skipType(tag & 7);
2801
3026
  break;
@@ -2810,6 +3035,9 @@ export const SimulateScenario = {
2810
3035
  nodeFailure: isSet(object.nodeFailure) ? Boolean(object.nodeFailure) : undefined,
2811
3036
  migration: isSet(object.migration) ? Boolean(object.migration) : undefined,
2812
3037
  serverLeave: isSet(object.serverLeave) ? Boolean(object.serverLeave) : undefined,
3038
+ switchCandidateProtocol: isSet(object.switchCandidateProtocol)
3039
+ ? candidateProtocolFromJSON(object.switchCandidateProtocol)
3040
+ : undefined,
2813
3041
  };
2814
3042
  },
2815
3043
 
@@ -2819,6 +3047,11 @@ export const SimulateScenario = {
2819
3047
  message.nodeFailure !== undefined && (obj.nodeFailure = message.nodeFailure);
2820
3048
  message.migration !== undefined && (obj.migration = message.migration);
2821
3049
  message.serverLeave !== undefined && (obj.serverLeave = message.serverLeave);
3050
+ message.switchCandidateProtocol !== undefined &&
3051
+ (obj.switchCandidateProtocol =
3052
+ message.switchCandidateProtocol !== undefined
3053
+ ? candidateProtocolToJSON(message.switchCandidateProtocol)
3054
+ : undefined);
2822
3055
  return obj;
2823
3056
  },
2824
3057
 
@@ -2828,6 +3061,7 @@ export const SimulateScenario = {
2828
3061
  message.nodeFailure = object.nodeFailure ?? undefined;
2829
3062
  message.migration = object.migration ?? undefined;
2830
3063
  message.serverLeave = object.serverLeave ?? undefined;
3064
+ message.switchCandidateProtocol = object.switchCandidateProtocol ?? undefined;
2831
3065
  return message;
2832
3066
  },
2833
3067
  };
@@ -32,8 +32,11 @@ export default class DeviceManager {
32
32
  video: kind !== 'audioinput' && kind !== 'audiooutput',
33
33
  audio: kind !== 'videoinput',
34
34
  };
35
- await navigator.mediaDevices.getUserMedia(permissionsToAcquire);
35
+ const stream = await navigator.mediaDevices.getUserMedia(permissionsToAcquire);
36
36
  devices = await navigator.mediaDevices.enumerateDevices();
37
+ stream.getTracks().forEach((track) => {
38
+ track.stop();
39
+ });
37
40
  }
38
41
  }
39
42
  if (kind) {
@@ -48,6 +48,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
48
48
 
49
49
  rtcConfig: RTCConfiguration = {};
50
50
 
51
+ get isClosed() {
52
+ return this._isClosed;
53
+ }
54
+
51
55
  private lossyDC?: RTCDataChannel;
52
56
 
53
57
  // @ts-ignore noUnusedLocals
@@ -64,7 +68,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
64
68
 
65
69
  private pcState: PCState = PCState.New;
66
70
 
67
- private isClosed: boolean = true;
71
+ private _isClosed: boolean = true;
68
72
 
69
73
  private pendingTrackResolvers: { [key: string]: (info: TrackInfo) => void } = {};
70
74
 
@@ -89,18 +93,25 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
89
93
 
90
94
  private connectedServerAddr?: string;
91
95
 
96
+ private attemptingReconnect: boolean = false;
97
+
92
98
  constructor() {
93
99
  super();
94
100
  this.client = new SignalClient();
95
101
  }
96
102
 
97
- async join(url: string, token: string, opts?: SignalOptions): Promise<JoinResponse> {
103
+ async join(
104
+ url: string,
105
+ token: string,
106
+ opts?: SignalOptions,
107
+ abortSignal?: AbortSignal,
108
+ ): Promise<JoinResponse> {
98
109
  this.url = url;
99
110
  this.token = token;
100
111
  this.signalOpts = opts;
101
112
 
102
- const joinResponse = await this.client.join(url, token, opts);
103
- this.isClosed = false;
113
+ const joinResponse = await this.client.join(url, token, opts, abortSignal);
114
+ this._isClosed = false;
104
115
 
105
116
  this.subscriberPrimary = joinResponse.subscriberPrimary;
106
117
  if (!this.publisher) {
@@ -117,7 +128,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
117
128
  }
118
129
 
119
130
  close() {
120
- this.isClosed = true;
131
+ this._isClosed = true;
121
132
 
122
133
  this.removeAllListeners();
123
134
  if (this.publisher && this.publisher.pc.signalingState !== 'closed') {
@@ -220,7 +231,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
220
231
  }
221
232
  this.primaryPC = primaryPC;
222
233
  primaryPC.onconnectionstatechange = async () => {
223
- log.trace('connection state changed', {
234
+ log.debug('primary PC state changed', {
224
235
  state: primaryPC.connectionState,
225
236
  });
226
237
  if (primaryPC.connectionState === 'connected') {
@@ -244,6 +255,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
244
255
  }
245
256
  };
246
257
  secondaryPC.onconnectionstatechange = async () => {
258
+ log.debug('secondary PC state changed', {
259
+ state: secondaryPC.connectionState,
260
+ });
247
261
  // also reconnect if secondary peerconnection fails
248
262
  if (secondaryPC.connectionState === 'failed') {
249
263
  this.handleDisconnect('secondary peerconnection');
@@ -403,7 +417,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
403
417
  // continues to work, we can reconnect to websocket to continue the session
404
418
  // after a number of retries, we'll close and give up permanently
405
419
  private handleDisconnect = (connection: string) => {
406
- if (this.isClosed) {
420
+ if (this._isClosed) {
407
421
  return;
408
422
  }
409
423
  log.debug(`${connection} disconnected`);
@@ -414,17 +428,25 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
414
428
 
415
429
  const delay = this.reconnectAttempts * this.reconnectAttempts * 300;
416
430
  setTimeout(async () => {
417
- if (this.isClosed) {
431
+ if (this._isClosed) {
432
+ return;
433
+ }
434
+ // guard for attempting reconnection multiple times while one attempt is still not finished
435
+ if (this.attemptingReconnect) {
418
436
  return;
419
437
  }
420
438
  if (
421
439
  isFireFox() || // TODO remove once clientConfiguration handles firefox case server side
422
- this.clientConfiguration?.resumeConnection === ClientConfigSetting.DISABLED
440
+ this.clientConfiguration?.resumeConnection === ClientConfigSetting.DISABLED ||
441
+ // signaling state could change to closed due to hardware sleep
442
+ // those connections cannot be resumed
443
+ (this.primaryPC?.signalingState ?? 'closed') === 'closed'
423
444
  ) {
424
445
  this.fullReconnectOnNext = true;
425
446
  }
426
447
 
427
448
  try {
449
+ this.attemptingReconnect = true;
428
450
  if (this.fullReconnectOnNext) {
429
451
  await this.restartConnection();
430
452
  } else {
@@ -434,6 +456,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
434
456
  this.fullReconnectOnNext = false;
435
457
  } catch (e) {
436
458
  this.reconnectAttempts += 1;
459
+ let reconnectRequired = false;
437
460
  let recoverable = true;
438
461
  if (e instanceof UnexpectedConnectionState) {
439
462
  log.debug('received unrecoverable error', { error: e });
@@ -441,7 +464,14 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
441
464
  recoverable = false;
442
465
  } else if (!(e instanceof SignalReconnectError)) {
443
466
  // cannot resume
467
+ reconnectRequired = true;
468
+ }
469
+
470
+ // when we flip from resume to reconnect, we need to reset reconnectAttempts
471
+ // this is needed to fire the right reconnecting events
472
+ if (reconnectRequired && !this.fullReconnectOnNext) {
444
473
  this.fullReconnectOnNext = true;
474
+ this.reconnectAttempts = 0;
445
475
  }
446
476
 
447
477
  const duration = Date.now() - this.reconnectStart;
@@ -458,6 +488,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
458
488
  this.emit(EngineEvent.Disconnected);
459
489
  this.close();
460
490
  }
491
+ } finally {
492
+ this.attemptingReconnect = false;
461
493
  }
462
494
  }, delay);
463
495
  };
@@ -473,6 +505,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
473
505
  this.emit(EngineEvent.Restarting);
474
506
  }
475
507
 
508
+ if (this.client.isConnected) {
509
+ this.client.sendLeave();
510
+ }
511
+ this.client.close();
476
512
  this.primaryPC = undefined;
477
513
  this.publisher?.close();
478
514
  this.publisher = undefined;
@@ -502,6 +538,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
502
538
  if (!this.publisher || !this.subscriber) {
503
539
  throw new UnexpectedConnectionState('publisher and subscriber connections unset');
504
540
  }
541
+
505
542
  log.info(`resuming signal connection, attempt ${this.reconnectAttempts}`);
506
543
  if (this.reconnectAttempts === 0) {
507
544
  this.emit(EngineEvent.Resuming);