livekit-client 1.6.2 → 1.6.3
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/livekit-client.esm.mjs +312 -101
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/api/SignalClient.d.ts +3 -3
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/proto/livekit_models.d.ts +43 -1
- package/dist/src/proto/livekit_models.d.ts.map +1 -1
- package/dist/src/proto/livekit_rtc.d.ts +473 -4
- package/dist/src/proto/livekit_rtc.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +1 -0
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +2 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/timers.d.ts +13 -0
- package/dist/src/room/timers.d.ts.map +1 -0
- package/dist/src/room/track/RemoteVideoTrack.d.ts.map +1 -1
- package/dist/ts4.2/src/api/SignalClient.d.ts +3 -3
- package/dist/ts4.2/src/index.d.ts +2 -1
- package/dist/ts4.2/src/proto/livekit_models.d.ts +45 -1
- package/dist/ts4.2/src/proto/livekit_rtc.d.ts +514 -3
- package/dist/ts4.2/src/room/PCTransport.d.ts +1 -0
- package/dist/ts4.2/src/room/RTCEngine.d.ts +2 -0
- package/dist/ts4.2/src/room/timers.d.ts +13 -0
- package/package.json +1 -1
- package/src/api/SignalClient.ts +28 -20
- package/src/index.ts +2 -0
- package/src/proto/livekit_models.ts +116 -1
- package/src/proto/livekit_rtc.ts +106 -2
- package/src/room/PCTransport.ts +22 -6
- package/src/room/RTCEngine.ts +56 -43
- package/src/room/Room.ts +4 -3
- package/src/room/timers.ts +16 -0
- package/src/room/track/RemoteVideoTrack.ts +2 -1
package/src/room/RTCEngine.ts
CHANGED
@@ -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 =
|
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
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
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.
|
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
|
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
|
-
|
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;
|