livekit-client 1.6.2 → 1.6.3

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 (37) hide show
  1. package/dist/livekit-client.esm.mjs +312 -101
  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/index.d.ts +2 -1
  8. package/dist/src/index.d.ts.map +1 -1
  9. package/dist/src/proto/livekit_models.d.ts +43 -1
  10. package/dist/src/proto/livekit_models.d.ts.map +1 -1
  11. package/dist/src/proto/livekit_rtc.d.ts +473 -4
  12. package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
  13. package/dist/src/room/PCTransport.d.ts +1 -0
  14. package/dist/src/room/PCTransport.d.ts.map +1 -1
  15. package/dist/src/room/RTCEngine.d.ts +2 -0
  16. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  17. package/dist/src/room/Room.d.ts.map +1 -1
  18. package/dist/src/room/timers.d.ts +13 -0
  19. package/dist/src/room/timers.d.ts.map +1 -0
  20. package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
  21. package/dist/ts4.2/src/api/SignalClient.d.ts +3 -3
  22. package/dist/ts4.2/src/index.d.ts +2 -1
  23. package/dist/ts4.2/src/proto/livekit_models.d.ts +45 -1
  24. package/dist/ts4.2/src/proto/livekit_rtc.d.ts +514 -3
  25. package/dist/ts4.2/src/room/PCTransport.d.ts +1 -0
  26. package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -0
  27. package/dist/ts4.2/src/room/timers.d.ts +13 -0
  28. package/package.json +1 -1
  29. package/src/api/SignalClient.ts +28 -20
  30. package/src/index.ts +2 -0
  31. package/src/proto/livekit_models.ts +116 -1
  32. package/src/proto/livekit_rtc.ts +106 -2
  33. package/src/room/PCTransport.ts +22 -6
  34. package/src/room/RTCEngine.ts +56 -43
  35. package/src/room/Room.ts +4 -3
  36. package/src/room/timers.ts +16 -0
  37. package/src/room/track/RemoteVideoTrack.ts +2 -1
@@ -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;
@@ -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
  };
package/src/room/Room.ts CHANGED
@@ -44,6 +44,7 @@ import type Participant from './participant/Participant';
44
44
  import type { ConnectionQuality } from './participant/Participant';
45
45
  import RemoteParticipant from './participant/RemoteParticipant';
46
46
  import RTCEngine from './RTCEngine';
47
+ import CriticalTimers from './timers';
47
48
  import LocalAudioTrack from './track/LocalAudioTrack';
48
49
  import LocalTrackPublication from './track/LocalTrackPublication';
49
50
  import LocalVideoTrack from './track/LocalVideoTrack';
@@ -364,7 +365,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
364
365
  }
365
366
 
366
367
  // don't return until ICE connected
367
- const connectTimeout = setTimeout(() => {
368
+ const connectTimeout = CriticalTimers.setTimeout(() => {
368
369
  // timeout
369
370
  this.recreateEngine();
370
371
  this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
@@ -372,7 +373,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
372
373
  }, this.connOptions.peerConnectionTimeout);
373
374
  const abortHandler = () => {
374
375
  log.warn('closing engine');
375
- clearTimeout(connectTimeout);
376
+ CriticalTimers.clearTimeout(connectTimeout);
376
377
  this.recreateEngine();
377
378
  this.handleDisconnect(this.options.stopLocalTrackOnUnpublish);
378
379
  reject(new ConnectionError('room connection has been cancelled'));
@@ -383,7 +384,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
383
384
  this.abortController?.signal.addEventListener('abort', abortHandler);
384
385
 
385
386
  this.engine.once(EngineEvent.Connected, () => {
386
- clearTimeout(connectTimeout);
387
+ CriticalTimers.clearTimeout(connectTimeout);
387
388
  this.abortController?.signal.removeEventListener('abort', abortHandler);
388
389
  // also hook unload event
389
390
  if (isWeb()) {
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Timers that can be overridden with platform specific implementations
3
+ * that ensure that they are fired. These should be used when it is critical
4
+ * that the timer fires on time.
5
+ */
6
+ export default class CriticalTimers {
7
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
8
+ static setTimeout = (...args: Parameters<typeof setTimeout>) => setTimeout(...args);
9
+
10
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
11
+ static setInterval = (...args: Parameters<typeof setInterval>) => setInterval(...args);
12
+
13
+ static clearTimeout = (...args: Parameters<typeof clearTimeout>) => clearTimeout(...args);
14
+
15
+ static clearInterval = (...args: Parameters<typeof clearInterval>) => clearInterval(...args);
16
+ }
@@ -2,6 +2,7 @@ import { debounce } from 'ts-debounce';
2
2
  import log from '../../logger';
3
3
  import { TrackEvent } from '../events';
4
4
  import { computeBitrate, VideoReceiverStats } from '../stats';
5
+ import CriticalTimers from '../timers';
5
6
  import { getIntersectionObserver, getResizeObserver, ObservableMediaElement } from '../utils';
6
7
  import RemoteTrack from './RemoteTrack';
7
8
  import { attachToElement, detachTrack, Track } from './Track';
@@ -233,7 +234,7 @@ export default class RemoteVideoTrack extends RemoteTrack {
233
234
 
234
235
  if (!isVisible && Date.now() - lastVisibilityChange < REACTION_DELAY) {
235
236
  // delay hidden events
236
- setTimeout(() => {
237
+ CriticalTimers.setTimeout(() => {
237
238
  this.updateVisibility();
238
239
  }, REACTION_DELAY);
239
240
  return;