livekit-client 1.6.2 → 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. package/dist/livekit-client.esm.mjs +468 -140
  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/src/api/SignalClient.d.ts +3 -3
  6. package/dist/src/api/SignalClient.d.ts.map +1 -1
  7. package/dist/src/connectionHelper/ConnectionCheck.d.ts +2 -2
  8. package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -1
  9. package/dist/src/index.d.ts +2 -1
  10. package/dist/src/index.d.ts.map +1 -1
  11. package/dist/src/proto/livekit_models.d.ts +53 -4
  12. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  13. package/dist/src/proto/livekit_rtc.d.ts +650 -91
  14. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  15. package/dist/src/room/PCTransport.d.ts +1 -0
  16. package/dist/src/room/PCTransport.d.ts.map +1 -1
  17. package/dist/src/room/RTCEngine.d.ts +2 -0
  18. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  19. package/dist/src/room/Room.d.ts +1 -1
  20. package/dist/src/room/Room.d.ts.map +1 -1
  21. package/dist/src/room/errors.d.ts +3 -0
  22. package/dist/src/room/errors.d.ts.map +1 -1
  23. package/dist/src/room/participant/LocalParticipant.d.ts +1 -3
  24. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  25. package/dist/src/room/participant/Participant.d.ts +1 -1
  26. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  27. package/dist/src/room/timers.d.ts +13 -0
  28. package/dist/src/room/timers.d.ts.map +1 -0
  29. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  30. package/dist/src/room/track/create.d.ts.map +1 -1
  31. package/dist/src/room/track/options.d.ts +2 -2
  32. package/dist/src/room/track/options.d.ts.map +1 -1
  33. package/dist/src/test/mocks.d.ts +1 -1
  34. package/dist/ts4.2/src/api/SignalClient.d.ts +3 -3
  35. package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +2 -2
  36. package/dist/ts4.2/src/index.d.ts +2 -1
  37. package/dist/ts4.2/src/proto/livekit_models.d.ts +59 -4
  38. package/dist/ts4.2/src/proto/livekit_rtc.d.ts +739 -120
  39. package/dist/ts4.2/src/room/PCTransport.d.ts +1 -0
  40. package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -0
  41. package/dist/ts4.2/src/room/Room.d.ts +1 -1
  42. package/dist/ts4.2/src/room/errors.d.ts +3 -0
  43. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +1 -3
  44. package/dist/ts4.2/src/room/participant/Participant.d.ts +1 -1
  45. package/dist/ts4.2/src/room/timers.d.ts +13 -0
  46. package/dist/ts4.2/src/room/track/options.d.ts +2 -2
  47. package/dist/ts4.2/src/test/mocks.d.ts +1 -1
  48. package/package.json +17 -17
  49. package/src/api/SignalClient.ts +33 -21
  50. package/src/connectionHelper/ConnectionCheck.ts +1 -1
  51. package/src/index.ts +2 -0
  52. package/src/proto/google/protobuf/timestamp.ts +2 -2
  53. package/src/proto/livekit_models.ts +158 -10
  54. package/src/proto/livekit_rtc.ts +205 -6
  55. package/src/room/PCTransport.ts +22 -6
  56. package/src/room/RTCEngine.ts +58 -45
  57. package/src/room/Room.ts +8 -10
  58. package/src/room/errors.ts +6 -0
  59. package/src/room/participant/LocalParticipant.ts +12 -17
  60. package/src/room/participant/Participant.ts +10 -2
  61. package/src/room/timers.ts +16 -0
  62. package/src/room/track/RemoteVideoTrack.ts +2 -1
  63. package/src/room/track/create.ts +6 -1
  64. package/src/room/track/options.ts +2 -2
@@ -9,6 +9,9 @@ import {
9
9
  DisconnectReason,
10
10
  disconnectReasonFromJSON,
11
11
  disconnectReasonToJSON,
12
+ Encryption_Type,
13
+ encryption_TypeFromJSON,
14
+ encryption_TypeToJSON,
12
15
  ParticipantInfo,
13
16
  ParticipantTracks,
14
17
  Room,
@@ -148,7 +151,8 @@ export interface SignalRequest {
148
151
  | { $case: "subscriptionPermission"; subscriptionPermission: SubscriptionPermission }
149
152
  | { $case: "syncState"; syncState: SyncState }
150
153
  | { $case: "simulate"; simulate: SimulateScenario }
151
- | { $case: "ping"; ping: number };
154
+ | { $case: "ping"; ping: number }
155
+ | { $case: "updateMetadata"; updateMetadata: UpdateParticipantMetadata };
152
156
  }
153
157
 
154
158
  export interface SignalResponse {
@@ -169,7 +173,8 @@ export interface SignalResponse {
169
173
  | { $case: "subscriptionPermissionUpdate"; subscriptionPermissionUpdate: SubscriptionPermissionUpdate }
170
174
  | { $case: "refreshToken"; refreshToken: string }
171
175
  | { $case: "trackUnpublished"; trackUnpublished: TrackUnpublishedResponse }
172
- | { $case: "pong"; pong: number };
176
+ | { $case: "pong"; pong: number }
177
+ | { $case: "reconnect"; reconnect: ReconnectResponse };
173
178
  }
174
179
 
175
180
  export interface SimulcastCodec {
@@ -198,6 +203,7 @@ export interface AddTrackRequest {
198
203
  stereo: boolean;
199
204
  /** true if RED (Redundant Encoding) is disabled for audio */
200
205
  disableRed: boolean;
206
+ encryption: Encryption_Type;
201
207
  }
202
208
 
203
209
  export interface TrickleRequest {
@@ -232,6 +238,11 @@ export interface JoinResponse {
232
238
  serverInfo?: ServerInfo;
233
239
  }
234
240
 
241
+ export interface ReconnectResponse {
242
+ iceServers: ICEServer[];
243
+ clientConfiguration?: ClientConfiguration;
244
+ }
245
+
235
246
  export interface TrackPublishedResponse {
236
247
  cid: string;
237
248
  track?: TrackInfo;
@@ -267,8 +278,17 @@ export interface UpdateTrackSettings {
267
278
  width: number;
268
279
  /** for video, height to receive */
269
280
  height: number;
270
- /** for video, frame rate to receive */
271
281
  fps: number;
282
+ /**
283
+ * subscription priority. 1 being the highest (0 is unset)
284
+ * when unset, server sill assign priority based on the order of subscription
285
+ * server will use priority in the following ways:
286
+ * 1. when subscribed tracks exceed per-participant subscription limit, server will
287
+ * pause the lowest priority tracks
288
+ * 2. when the network is congested, server will assign available bandwidth to
289
+ * higher priority tracks first. lowest priority tracks can be paused
290
+ */
291
+ priority: number;
272
292
  }
273
293
 
274
294
  export interface LeaveRequest {
@@ -286,6 +306,10 @@ export interface UpdateVideoLayers {
286
306
  layers: VideoLayer[];
287
307
  }
288
308
 
309
+ export interface UpdateParticipantMetadata {
310
+ metadata: string;
311
+ }
312
+
289
313
  export interface ICEServer {
290
314
  urls: string[];
291
315
  username: string;
@@ -425,6 +449,9 @@ export const SignalRequest = {
425
449
  if (message.message?.$case === "ping") {
426
450
  writer.uint32(112).int64(message.message.ping);
427
451
  }
452
+ if (message.message?.$case === "updateMetadata") {
453
+ UpdateParticipantMetadata.encode(message.message.updateMetadata, writer.uint32(122).fork()).ldelim();
454
+ }
428
455
  return writer;
429
456
  },
430
457
 
@@ -480,6 +507,12 @@ export const SignalRequest = {
480
507
  case 14:
481
508
  message.message = { $case: "ping", ping: longToNumber(reader.int64() as Long) };
482
509
  break;
510
+ case 15:
511
+ message.message = {
512
+ $case: "updateMetadata",
513
+ updateMetadata: UpdateParticipantMetadata.decode(reader, reader.uint32()),
514
+ };
515
+ break;
483
516
  default:
484
517
  reader.skipType(tag & 7);
485
518
  break;
@@ -519,6 +552,8 @@ export const SignalRequest = {
519
552
  ? { $case: "simulate", simulate: SimulateScenario.fromJSON(object.simulate) }
520
553
  : isSet(object.ping)
521
554
  ? { $case: "ping", ping: Number(object.ping) }
555
+ : isSet(object.updateMetadata)
556
+ ? { $case: "updateMetadata", updateMetadata: UpdateParticipantMetadata.fromJSON(object.updateMetadata) }
522
557
  : undefined,
523
558
  };
524
559
  },
@@ -555,6 +590,9 @@ export const SignalRequest = {
555
590
  message.message?.$case === "simulate" &&
556
591
  (obj.simulate = message.message?.simulate ? SimulateScenario.toJSON(message.message?.simulate) : undefined);
557
592
  message.message?.$case === "ping" && (obj.ping = Math.round(message.message?.ping));
593
+ message.message?.$case === "updateMetadata" && (obj.updateMetadata = message.message?.updateMetadata
594
+ ? UpdateParticipantMetadata.toJSON(message.message?.updateMetadata)
595
+ : undefined);
558
596
  return obj;
559
597
  },
560
598
 
@@ -641,6 +679,16 @@ export const SignalRequest = {
641
679
  if (object.message?.$case === "ping" && object.message?.ping !== undefined && object.message?.ping !== null) {
642
680
  message.message = { $case: "ping", ping: object.message.ping };
643
681
  }
682
+ if (
683
+ object.message?.$case === "updateMetadata" &&
684
+ object.message?.updateMetadata !== undefined &&
685
+ object.message?.updateMetadata !== null
686
+ ) {
687
+ message.message = {
688
+ $case: "updateMetadata",
689
+ updateMetadata: UpdateParticipantMetadata.fromPartial(object.message.updateMetadata),
690
+ };
691
+ }
644
692
  return message;
645
693
  },
646
694
  };
@@ -703,6 +751,9 @@ export const SignalResponse = {
703
751
  if (message.message?.$case === "pong") {
704
752
  writer.uint32(144).int64(message.message.pong);
705
753
  }
754
+ if (message.message?.$case === "reconnect") {
755
+ ReconnectResponse.encode(message.message.reconnect, writer.uint32(154).fork()).ldelim();
756
+ }
706
757
  return writer;
707
758
  },
708
759
 
@@ -785,6 +836,9 @@ export const SignalResponse = {
785
836
  case 18:
786
837
  message.message = { $case: "pong", pong: longToNumber(reader.int64() as Long) };
787
838
  break;
839
+ case 19:
840
+ message.message = { $case: "reconnect", reconnect: ReconnectResponse.decode(reader, reader.uint32()) };
841
+ break;
788
842
  default:
789
843
  reader.skipType(tag & 7);
790
844
  break;
@@ -835,6 +889,8 @@ export const SignalResponse = {
835
889
  ? { $case: "trackUnpublished", trackUnpublished: TrackUnpublishedResponse.fromJSON(object.trackUnpublished) }
836
890
  : isSet(object.pong)
837
891
  ? { $case: "pong", pong: Number(object.pong) }
892
+ : isSet(object.reconnect)
893
+ ? { $case: "reconnect", reconnect: ReconnectResponse.fromJSON(object.reconnect) }
838
894
  : undefined,
839
895
  };
840
896
  },
@@ -882,6 +938,8 @@ export const SignalResponse = {
882
938
  ? TrackUnpublishedResponse.toJSON(message.message?.trackUnpublished)
883
939
  : undefined);
884
940
  message.message?.$case === "pong" && (obj.pong = Math.round(message.message?.pong));
941
+ message.message?.$case === "reconnect" &&
942
+ (obj.reconnect = message.message?.reconnect ? ReconnectResponse.toJSON(message.message?.reconnect) : undefined);
885
943
  return obj;
886
944
  },
887
945
 
@@ -999,6 +1057,13 @@ export const SignalResponse = {
999
1057
  if (object.message?.$case === "pong" && object.message?.pong !== undefined && object.message?.pong !== null) {
1000
1058
  message.message = { $case: "pong", pong: object.message.pong };
1001
1059
  }
1060
+ if (
1061
+ object.message?.$case === "reconnect" &&
1062
+ object.message?.reconnect !== undefined &&
1063
+ object.message?.reconnect !== null
1064
+ ) {
1065
+ message.message = { $case: "reconnect", reconnect: ReconnectResponse.fromPartial(object.message.reconnect) };
1066
+ }
1002
1067
  return message;
1003
1068
  },
1004
1069
  };
@@ -1085,6 +1150,7 @@ function createBaseAddTrackRequest(): AddTrackRequest {
1085
1150
  sid: "",
1086
1151
  stereo: false,
1087
1152
  disableRed: false,
1153
+ encryption: 0,
1088
1154
  };
1089
1155
  }
1090
1156
 
@@ -1129,6 +1195,9 @@ export const AddTrackRequest = {
1129
1195
  if (message.disableRed === true) {
1130
1196
  writer.uint32(104).bool(message.disableRed);
1131
1197
  }
1198
+ if (message.encryption !== 0) {
1199
+ writer.uint32(112).int32(message.encryption);
1200
+ }
1132
1201
  return writer;
1133
1202
  },
1134
1203
 
@@ -1178,6 +1247,9 @@ export const AddTrackRequest = {
1178
1247
  case 13:
1179
1248
  message.disableRed = reader.bool();
1180
1249
  break;
1250
+ case 14:
1251
+ message.encryption = reader.int32() as any;
1252
+ break;
1181
1253
  default:
1182
1254
  reader.skipType(tag & 7);
1183
1255
  break;
@@ -1203,6 +1275,7 @@ export const AddTrackRequest = {
1203
1275
  sid: isSet(object.sid) ? String(object.sid) : "",
1204
1276
  stereo: isSet(object.stereo) ? Boolean(object.stereo) : false,
1205
1277
  disableRed: isSet(object.disableRed) ? Boolean(object.disableRed) : false,
1278
+ encryption: isSet(object.encryption) ? encryption_TypeFromJSON(object.encryption) : 0,
1206
1279
  };
1207
1280
  },
1208
1281
 
@@ -1229,6 +1302,7 @@ export const AddTrackRequest = {
1229
1302
  message.sid !== undefined && (obj.sid = message.sid);
1230
1303
  message.stereo !== undefined && (obj.stereo = message.stereo);
1231
1304
  message.disableRed !== undefined && (obj.disableRed = message.disableRed);
1305
+ message.encryption !== undefined && (obj.encryption = encryption_TypeToJSON(message.encryption));
1232
1306
  return obj;
1233
1307
  },
1234
1308
 
@@ -1247,6 +1321,7 @@ export const AddTrackRequest = {
1247
1321
  message.sid = object.sid ?? "";
1248
1322
  message.stereo = object.stereo ?? false;
1249
1323
  message.disableRed = object.disableRed ?? false;
1324
+ message.encryption = object.encryption ?? 0;
1250
1325
  return message;
1251
1326
  },
1252
1327
  };
@@ -1550,6 +1625,74 @@ export const JoinResponse = {
1550
1625
  },
1551
1626
  };
1552
1627
 
1628
+ function createBaseReconnectResponse(): ReconnectResponse {
1629
+ return { iceServers: [], clientConfiguration: undefined };
1630
+ }
1631
+
1632
+ export const ReconnectResponse = {
1633
+ encode(message: ReconnectResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
1634
+ for (const v of message.iceServers) {
1635
+ ICEServer.encode(v!, writer.uint32(10).fork()).ldelim();
1636
+ }
1637
+ if (message.clientConfiguration !== undefined) {
1638
+ ClientConfiguration.encode(message.clientConfiguration, writer.uint32(18).fork()).ldelim();
1639
+ }
1640
+ return writer;
1641
+ },
1642
+
1643
+ decode(input: _m0.Reader | Uint8Array, length?: number): ReconnectResponse {
1644
+ const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
1645
+ let end = length === undefined ? reader.len : reader.pos + length;
1646
+ const message = createBaseReconnectResponse();
1647
+ while (reader.pos < end) {
1648
+ const tag = reader.uint32();
1649
+ switch (tag >>> 3) {
1650
+ case 1:
1651
+ message.iceServers.push(ICEServer.decode(reader, reader.uint32()));
1652
+ break;
1653
+ case 2:
1654
+ message.clientConfiguration = ClientConfiguration.decode(reader, reader.uint32());
1655
+ break;
1656
+ default:
1657
+ reader.skipType(tag & 7);
1658
+ break;
1659
+ }
1660
+ }
1661
+ return message;
1662
+ },
1663
+
1664
+ fromJSON(object: any): ReconnectResponse {
1665
+ return {
1666
+ iceServers: Array.isArray(object?.iceServers) ? object.iceServers.map((e: any) => ICEServer.fromJSON(e)) : [],
1667
+ clientConfiguration: isSet(object.clientConfiguration)
1668
+ ? ClientConfiguration.fromJSON(object.clientConfiguration)
1669
+ : undefined,
1670
+ };
1671
+ },
1672
+
1673
+ toJSON(message: ReconnectResponse): unknown {
1674
+ const obj: any = {};
1675
+ if (message.iceServers) {
1676
+ obj.iceServers = message.iceServers.map((e) => e ? ICEServer.toJSON(e) : undefined);
1677
+ } else {
1678
+ obj.iceServers = [];
1679
+ }
1680
+ message.clientConfiguration !== undefined && (obj.clientConfiguration = message.clientConfiguration
1681
+ ? ClientConfiguration.toJSON(message.clientConfiguration)
1682
+ : undefined);
1683
+ return obj;
1684
+ },
1685
+
1686
+ fromPartial<I extends Exact<DeepPartial<ReconnectResponse>, I>>(object: I): ReconnectResponse {
1687
+ const message = createBaseReconnectResponse();
1688
+ message.iceServers = object.iceServers?.map((e) => ICEServer.fromPartial(e)) || [];
1689
+ message.clientConfiguration = (object.clientConfiguration !== undefined && object.clientConfiguration !== null)
1690
+ ? ClientConfiguration.fromPartial(object.clientConfiguration)
1691
+ : undefined;
1692
+ return message;
1693
+ },
1694
+ };
1695
+
1553
1696
  function createBaseTrackPublishedResponse(): TrackPublishedResponse {
1554
1697
  return { cid: "", track: undefined };
1555
1698
  }
@@ -1845,7 +1988,7 @@ export const UpdateSubscription = {
1845
1988
  };
1846
1989
 
1847
1990
  function createBaseUpdateTrackSettings(): UpdateTrackSettings {
1848
- return { trackSids: [], disabled: false, quality: 0, width: 0, height: 0, fps: 0 };
1991
+ return { trackSids: [], disabled: false, quality: 0, width: 0, height: 0, fps: 0, priority: 0 };
1849
1992
  }
1850
1993
 
1851
1994
  export const UpdateTrackSettings = {
@@ -1868,6 +2011,9 @@ export const UpdateTrackSettings = {
1868
2011
  if (message.fps !== 0) {
1869
2012
  writer.uint32(56).uint32(message.fps);
1870
2013
  }
2014
+ if (message.priority !== 0) {
2015
+ writer.uint32(64).uint32(message.priority);
2016
+ }
1871
2017
  return writer;
1872
2018
  },
1873
2019
 
@@ -1896,6 +2042,9 @@ export const UpdateTrackSettings = {
1896
2042
  case 7:
1897
2043
  message.fps = reader.uint32();
1898
2044
  break;
2045
+ case 8:
2046
+ message.priority = reader.uint32();
2047
+ break;
1899
2048
  default:
1900
2049
  reader.skipType(tag & 7);
1901
2050
  break;
@@ -1912,6 +2061,7 @@ export const UpdateTrackSettings = {
1912
2061
  width: isSet(object.width) ? Number(object.width) : 0,
1913
2062
  height: isSet(object.height) ? Number(object.height) : 0,
1914
2063
  fps: isSet(object.fps) ? Number(object.fps) : 0,
2064
+ priority: isSet(object.priority) ? Number(object.priority) : 0,
1915
2065
  };
1916
2066
  },
1917
2067
 
@@ -1927,6 +2077,7 @@ export const UpdateTrackSettings = {
1927
2077
  message.width !== undefined && (obj.width = Math.round(message.width));
1928
2078
  message.height !== undefined && (obj.height = Math.round(message.height));
1929
2079
  message.fps !== undefined && (obj.fps = Math.round(message.fps));
2080
+ message.priority !== undefined && (obj.priority = Math.round(message.priority));
1930
2081
  return obj;
1931
2082
  },
1932
2083
 
@@ -1938,6 +2089,7 @@ export const UpdateTrackSettings = {
1938
2089
  message.width = object.width ?? 0;
1939
2090
  message.height = object.height ?? 0;
1940
2091
  message.fps = object.fps ?? 0;
2092
+ message.priority = object.priority ?? 0;
1941
2093
  return message;
1942
2094
  },
1943
2095
  };
@@ -2062,6 +2214,53 @@ export const UpdateVideoLayers = {
2062
2214
  },
2063
2215
  };
2064
2216
 
2217
+ function createBaseUpdateParticipantMetadata(): UpdateParticipantMetadata {
2218
+ return { metadata: "" };
2219
+ }
2220
+
2221
+ export const UpdateParticipantMetadata = {
2222
+ encode(message: UpdateParticipantMetadata, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
2223
+ if (message.metadata !== "") {
2224
+ writer.uint32(10).string(message.metadata);
2225
+ }
2226
+ return writer;
2227
+ },
2228
+
2229
+ decode(input: _m0.Reader | Uint8Array, length?: number): UpdateParticipantMetadata {
2230
+ const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
2231
+ let end = length === undefined ? reader.len : reader.pos + length;
2232
+ const message = createBaseUpdateParticipantMetadata();
2233
+ while (reader.pos < end) {
2234
+ const tag = reader.uint32();
2235
+ switch (tag >>> 3) {
2236
+ case 1:
2237
+ message.metadata = reader.string();
2238
+ break;
2239
+ default:
2240
+ reader.skipType(tag & 7);
2241
+ break;
2242
+ }
2243
+ }
2244
+ return message;
2245
+ },
2246
+
2247
+ fromJSON(object: any): UpdateParticipantMetadata {
2248
+ return { metadata: isSet(object.metadata) ? String(object.metadata) : "" };
2249
+ },
2250
+
2251
+ toJSON(message: UpdateParticipantMetadata): unknown {
2252
+ const obj: any = {};
2253
+ message.metadata !== undefined && (obj.metadata = message.metadata);
2254
+ return obj;
2255
+ },
2256
+
2257
+ fromPartial<I extends Exact<DeepPartial<UpdateParticipantMetadata>, I>>(object: I): UpdateParticipantMetadata {
2258
+ const message = createBaseUpdateParticipantMetadata();
2259
+ message.metadata = object.metadata ?? "";
2260
+ return message;
2261
+ },
2262
+ };
2263
+
2065
2264
  function createBaseICEServer(): ICEServer {
2066
2265
  return { urls: [], username: "", credential: "" };
2067
2266
  }
@@ -3192,7 +3391,7 @@ export const SimulateScenario = {
3192
3391
  declare var self: any | undefined;
3193
3392
  declare var window: any | undefined;
3194
3393
  declare var global: any | undefined;
3195
- var globalThis: any = (() => {
3394
+ var tsProtoGlobalThis: any = (() => {
3196
3395
  if (typeof globalThis !== "undefined") {
3197
3396
  return globalThis;
3198
3397
  }
@@ -3222,7 +3421,7 @@ export type Exact<P, I extends P> = P extends Builtin ? P
3222
3421
 
3223
3422
  function longToNumber(long: Long): number {
3224
3423
  if (long.gt(Number.MAX_SAFE_INTEGER)) {
3225
- throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
3424
+ throw new tsProtoGlobalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
3226
3425
  }
3227
3426
  return long.toNumber();
3228
3427
  }
@@ -30,6 +30,8 @@ export default class PCTransport extends EventEmitter {
30
30
 
31
31
  remoteStereoMids: string[] = [];
32
32
 
33
+ remoteNackMids: string[] = [];
34
+
33
35
  onOffer?: (offer: RTCSessionDescriptionInit) => void;
34
36
 
35
37
  constructor(config?: RTCConfiguration) {
@@ -50,7 +52,9 @@ export default class PCTransport extends EventEmitter {
50
52
 
51
53
  async setRemoteDescription(sd: RTCSessionDescriptionInit): Promise<void> {
52
54
  if (sd.type === 'offer') {
53
- this.remoteStereoMids = extractStereoTracksFromOffer(sd);
55
+ let { stereoMids, nackMids } = extractStereoAndNackAudioFromOffer(sd);
56
+ this.remoteStereoMids = stereoMids;
57
+ this.remoteNackMids = nackMids;
54
58
  }
55
59
  await this.pc.setRemoteDescription(sd);
56
60
 
@@ -116,7 +120,7 @@ export default class PCTransport extends EventEmitter {
116
120
  const sdpParsed = parse(offer.sdp ?? '');
117
121
  sdpParsed.media.forEach((media) => {
118
122
  if (media.type === 'audio') {
119
- ensureAudioNackAndStereo(media, []);
123
+ ensureAudioNackAndStereo(media, [], []);
120
124
  } else if (media.type === 'video') {
121
125
  // mung sdp for codec bitrate setting that can't apply by sendEncoding
122
126
  this.trackBitrates.some((trackbr): boolean => {
@@ -169,7 +173,7 @@ export default class PCTransport extends EventEmitter {
169
173
  const sdpParsed = parse(answer.sdp ?? '');
170
174
  sdpParsed.media.forEach((media) => {
171
175
  if (media.type === 'audio') {
172
- ensureAudioNackAndStereo(media, this.remoteStereoMids);
176
+ ensureAudioNackAndStereo(media, this.remoteStereoMids, this.remoteNackMids);
173
177
  }
174
178
  });
175
179
  await this.setMungedLocalDescription(answer, write(sdpParsed));
@@ -226,6 +230,7 @@ function ensureAudioNackAndStereo(
226
230
  payloads?: string | undefined;
227
231
  } & MediaDescription,
228
232
  stereoMids: string[],
233
+ nackMids: string[],
229
234
  ) {
230
235
  // found opus codec to add nack fb
231
236
  let opusPayload = 0;
@@ -243,7 +248,10 @@ function ensureAudioNackAndStereo(
243
248
  media.rtcpFb = [];
244
249
  }
245
250
 
246
- if (!media.rtcpFb.some((fb) => fb.payload === opusPayload && fb.type === 'nack')) {
251
+ if (
252
+ nackMids.includes(media.mid!) &&
253
+ !media.rtcpFb.some((fb) => fb.payload === opusPayload && fb.type === 'nack')
254
+ ) {
247
255
  media.rtcpFb.push({
248
256
  payload: opusPayload,
249
257
  type: 'nack',
@@ -264,8 +272,12 @@ function ensureAudioNackAndStereo(
264
272
  }
265
273
  }
266
274
 
267
- function extractStereoTracksFromOffer(offer: RTCSessionDescriptionInit): string[] {
275
+ function extractStereoAndNackAudioFromOffer(offer: RTCSessionDescriptionInit): {
276
+ stereoMids: string[];
277
+ nackMids: string[];
278
+ } {
268
279
  const stereoMids: string[] = [];
280
+ const nackMids: string[] = [];
269
281
  const sdpParsed = parse(offer.sdp ?? '');
270
282
  let opusPayload = 0;
271
283
  sdpParsed.media.forEach((media) => {
@@ -278,6 +290,10 @@ function extractStereoTracksFromOffer(offer: RTCSessionDescriptionInit): string[
278
290
  return false;
279
291
  });
280
292
 
293
+ if (media.rtcpFb?.some((fb) => fb.payload === opusPayload && fb.type === 'nack')) {
294
+ nackMids.push(media.mid!);
295
+ }
296
+
281
297
  media.fmtp.some((fmtp): boolean => {
282
298
  if (fmtp.payload === opusPayload) {
283
299
  if (fmtp.config.includes('sprop-stereo=1')) {
@@ -289,5 +305,5 @@ function extractStereoTracksFromOffer(offer: RTCSessionDescriptionInit): string[
289
305
  });
290
306
  }
291
307
  });
292
- return stereoMids;
308
+ return { stereoMids, nackMids };
293
309
  }
@@ -17,6 +17,7 @@ import {
17
17
  AddTrackRequest,
18
18
  JoinResponse,
19
19
  LeaveRequest,
20
+ ReconnectResponse,
20
21
  SignalTarget,
21
22
  TrackPublishedResponse,
22
23
  } from '../proto/livekit_rtc';
@@ -31,6 +32,7 @@ import {
31
32
  import { EngineEvent } from './events';
32
33
  import PCTransport, { PCEvents } from './PCTransport';
33
34
  import type { ReconnectContext, ReconnectPolicy } from './ReconnectPolicy';
35
+ import CriticalTimers from './timers';
34
36
  import type LocalTrack from './track/LocalTrack';
35
37
  import type LocalVideoTrack from './track/LocalVideoTrack';
36
38
  import type { SimulcastTrackInfo } from './track/LocalVideoTrack';
@@ -279,35 +281,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
279
281
 
280
282
  this.participantSid = joinResponse.participant?.sid;
281
283
 
282
- const rtcConfig = { ...this.rtcConfig };
283
-
284
- // update ICE servers before creating PeerConnection
285
- if (joinResponse.iceServers && !rtcConfig.iceServers) {
286
- const rtcIceServers: RTCIceServer[] = [];
287
- joinResponse.iceServers.forEach((iceServer) => {
288
- const rtcIceServer: RTCIceServer = {
289
- urls: iceServer.urls,
290
- };
291
- if (iceServer.username) rtcIceServer.username = iceServer.username;
292
- if (iceServer.credential) {
293
- rtcIceServer.credential = iceServer.credential;
294
- }
295
- rtcIceServers.push(rtcIceServer);
296
- });
297
- rtcConfig.iceServers = rtcIceServers;
298
- }
299
-
300
- if (
301
- joinResponse.clientConfiguration &&
302
- joinResponse.clientConfiguration.forceRelay === ClientConfigSetting.ENABLED
303
- ) {
304
- rtcConfig.iceTransportPolicy = 'relay';
305
- }
306
-
307
- // @ts-ignore
308
- rtcConfig.sdpSemantics = 'unified-plan';
309
- // @ts-ignore
310
- rtcConfig.continualGatheringPolicy = 'gather_continually';
284
+ const rtcConfig = this.makeRTCConfiguration(joinResponse);
311
285
 
312
286
  this.publisher = new PCTransport(rtcConfig);
313
287
  this.subscriber = new PCTransport(rtcConfig);
@@ -448,6 +422,40 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
448
422
  };
449
423
  }
450
424
 
425
+ private makeRTCConfiguration(serverResponse: JoinResponse | ReconnectResponse): RTCConfiguration {
426
+ const rtcConfig = { ...this.rtcConfig };
427
+
428
+ // update ICE servers before creating PeerConnection
429
+ if (serverResponse.iceServers && !rtcConfig.iceServers) {
430
+ const rtcIceServers: RTCIceServer[] = [];
431
+ serverResponse.iceServers.forEach((iceServer) => {
432
+ const rtcIceServer: RTCIceServer = {
433
+ urls: iceServer.urls,
434
+ };
435
+ if (iceServer.username) rtcIceServer.username = iceServer.username;
436
+ if (iceServer.credential) {
437
+ rtcIceServer.credential = iceServer.credential;
438
+ }
439
+ rtcIceServers.push(rtcIceServer);
440
+ });
441
+ rtcConfig.iceServers = rtcIceServers;
442
+ }
443
+
444
+ if (
445
+ serverResponse.clientConfiguration &&
446
+ serverResponse.clientConfiguration.forceRelay === ClientConfigSetting.ENABLED
447
+ ) {
448
+ rtcConfig.iceTransportPolicy = 'relay';
449
+ }
450
+
451
+ // @ts-ignore
452
+ rtcConfig.sdpSemantics = 'unified-plan';
453
+ // @ts-ignore
454
+ rtcConfig.continualGatheringPolicy = 'gather_continually';
455
+
456
+ return rtcConfig;
457
+ }
458
+
451
459
  private createDataChannels() {
452
460
  if (!this.publisher) {
453
461
  return;
@@ -673,14 +681,14 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
673
681
  return;
674
682
  }
675
683
 
676
- log.debug(`${connection} disconnected`);
684
+ log.warn(`${connection} disconnected`);
677
685
  if (this.reconnectAttempts === 0) {
678
686
  // only reset start time on the first try
679
687
  this.reconnectStart = Date.now();
680
688
  }
681
689
 
682
690
  const disconnect = (duration: number) => {
683
- log.info(
691
+ log.warn(
684
692
  `could not recover connection after ${this.reconnectAttempts} attempts, ${duration}ms. giving up`,
685
693
  );
686
694
  this.emit(EngineEvent.Disconnected);
@@ -703,10 +711,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
703
711
 
704
712
  log.debug(`reconnecting in ${delay}ms`);
705
713
 
706
- if (this.reconnectTimeout) {
707
- clearTimeout(this.reconnectTimeout);
708
- }
709
- this.reconnectTimeout = setTimeout(() => this.attemptReconnect(signalEvents), delay);
714
+ this.clearReconnectTimeout();
715
+ this.reconnectTimeout = CriticalTimers.setTimeout(
716
+ () => this.attemptReconnect(signalEvents),
717
+ delay,
718
+ );
710
719
  };
711
720
 
712
721
  private async attemptReconnect(signalEvents: boolean = false) {
@@ -733,11 +742,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
733
742
  } else {
734
743
  await this.resumeConnection(signalEvents);
735
744
  }
736
- this.reconnectAttempts = 0;
745
+ this.clearPendingReconnect();
737
746
  this.fullReconnectOnNext = false;
738
- if (this.reconnectTimeout) {
739
- clearTimeout(this.reconnectTimeout);
740
- }
741
747
  } catch (e) {
742
748
  this.reconnectAttempts += 1;
743
749
  let reconnectRequired = false;
@@ -841,7 +847,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
841
847
  }
842
848
 
843
849
  try {
844
- await this.client.reconnect(this.url, this.token, this.participantSid);
850
+ const res = await this.client.reconnect(this.url, this.token, this.participantSid);
851
+ if (res) {
852
+ const rtcConfig = this.makeRTCConfiguration(res);
853
+ this.publisher.pc.setConfiguration(rtcConfig);
854
+ this.subscriber.pc.setConfiguration(rtcConfig);
855
+ }
845
856
  } catch (e) {
846
857
  let message = '';
847
858
  if (e instanceof Error) {
@@ -1034,19 +1045,21 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1034
1045
  }
1035
1046
  }
1036
1047
 
1037
- private clearPendingReconnect() {
1048
+ private clearReconnectTimeout() {
1038
1049
  if (this.reconnectTimeout) {
1039
- clearTimeout(this.reconnectTimeout);
1050
+ CriticalTimers.clearTimeout(this.reconnectTimeout);
1040
1051
  }
1052
+ }
1053
+
1054
+ private clearPendingReconnect() {
1055
+ this.clearReconnectTimeout();
1041
1056
  this.reconnectAttempts = 0;
1042
1057
  }
1043
1058
 
1044
1059
  private handleBrowserOnLine = () => {
1045
1060
  // in case the engine is currently reconnecting, attempt a reconnect immediately after the browser state has changed to 'onLine'
1046
1061
  if (this.client.isReconnecting) {
1047
- if (this.reconnectTimeout) {
1048
- clearTimeout(this.reconnectTimeout);
1049
- }
1062
+ this.clearReconnectTimeout();
1050
1063
  this.attemptReconnect(true);
1051
1064
  }
1052
1065
  };