livekit-client 2.15.9 → 2.15.11
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.
- package/dist/livekit-client.esm.mjs +125 -17
- 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 +7 -3
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/api/utils.d.ts +1 -0
- package/dist/src/api/utils.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts +1 -0
- package/dist/src/room/PCTransportManager.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/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/rpc.d.ts +6 -1
- package/dist/src/room/rpc.d.ts.map +1 -1
- package/dist/ts4.2/api/SignalClient.d.ts +7 -3
- package/dist/ts4.2/api/utils.d.ts +1 -0
- package/dist/ts4.2/room/PCTransportManager.d.ts +1 -0
- package/dist/ts4.2/room/RTCEngine.d.ts +2 -0
- package/dist/ts4.2/room/rpc.d.ts +6 -1
- package/package.json +2 -2
- package/src/api/SignalClient.test.ts +93 -12
- package/src/api/SignalClient.ts +36 -12
- package/src/api/utils.ts +18 -0
- package/src/room/PCTransportManager.ts +10 -0
- package/src/room/RTCEngine.ts +22 -3
- package/src/room/Room.ts +34 -0
- package/src/room/participant/LocalParticipant.ts +5 -9
- package/src/room/rpc.ts +6 -1
package/src/room/RTCEngine.ts
CHANGED
|
@@ -202,6 +202,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
202
202
|
|
|
203
203
|
private reliableReceivedState: TTLMap<string, number> = new TTLMap(reliabeReceiveStateTTL);
|
|
204
204
|
|
|
205
|
+
private midToTrackId: { [key: string]: string } = {};
|
|
206
|
+
|
|
205
207
|
constructor(private options: InternalRoomOptions) {
|
|
206
208
|
super();
|
|
207
209
|
this.log = getLogger(options.loggerName ?? LoggerNames.Engine);
|
|
@@ -499,11 +501,17 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
499
501
|
|
|
500
502
|
private setupSignalClientCallbacks() {
|
|
501
503
|
// configure signaling client
|
|
502
|
-
this.client.onAnswer = async (sd, offerId) => {
|
|
504
|
+
this.client.onAnswer = async (sd, offerId, midToTrackId) => {
|
|
503
505
|
if (!this.pcManager) {
|
|
504
506
|
return;
|
|
505
507
|
}
|
|
506
|
-
this.log.debug('received server answer', {
|
|
508
|
+
this.log.debug('received server answer', {
|
|
509
|
+
...this.logContext,
|
|
510
|
+
RTCSdpType: sd.type,
|
|
511
|
+
sdp: sd.sdp,
|
|
512
|
+
midToTrackId,
|
|
513
|
+
});
|
|
514
|
+
this.midToTrackId = midToTrackId;
|
|
507
515
|
await this.pcManager.setPublisherAnswer(sd, offerId);
|
|
508
516
|
};
|
|
509
517
|
|
|
@@ -517,11 +525,12 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
517
525
|
};
|
|
518
526
|
|
|
519
527
|
// when server creates an offer for the client
|
|
520
|
-
this.client.onOffer = async (sd, offerId) => {
|
|
528
|
+
this.client.onOffer = async (sd, offerId, midToTrackId) => {
|
|
521
529
|
this.latestRemoteOfferId = offerId;
|
|
522
530
|
if (!this.pcManager) {
|
|
523
531
|
return;
|
|
524
532
|
}
|
|
533
|
+
this.midToTrackId = midToTrackId;
|
|
525
534
|
const answer = await this.pcManager.createSubscriberAnswerFromOffer(sd, offerId);
|
|
526
535
|
if (answer) {
|
|
527
536
|
this.client.sendAnswer(answer, offerId);
|
|
@@ -1625,6 +1634,16 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
|
|
|
1625
1634
|
window.removeEventListener('online', this.handleBrowserOnLine);
|
|
1626
1635
|
}
|
|
1627
1636
|
}
|
|
1637
|
+
|
|
1638
|
+
getTrackIdForReceiver(receiver: RTCRtpReceiver): string | undefined {
|
|
1639
|
+
const mid = this.pcManager?.getMidForReceiver(receiver);
|
|
1640
|
+
if (mid) {
|
|
1641
|
+
const match = Object.entries(this.midToTrackId).find(([key]) => key === mid);
|
|
1642
|
+
if (match) {
|
|
1643
|
+
return match[1];
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1628
1647
|
}
|
|
1629
1648
|
|
|
1630
1649
|
class SignalReconnectError extends Error {}
|
package/src/room/Room.ts
CHANGED
|
@@ -1370,6 +1370,11 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
|
1370
1370
|
// We'll defer these events until when the room is connected or eventually disconnected.
|
|
1371
1371
|
if (this.state === ConnectionState.Connecting || this.state === ConnectionState.Reconnecting) {
|
|
1372
1372
|
const reconnectedHandler = () => {
|
|
1373
|
+
this.log.debug('deferring on track for later', {
|
|
1374
|
+
mediaTrackId: mediaTrack.id,
|
|
1375
|
+
mediaStreamId: stream.id,
|
|
1376
|
+
tracksInStream: stream.getTracks().map((track) => track.id),
|
|
1377
|
+
});
|
|
1373
1378
|
this.onTrackAdded(mediaTrack, stream, receiver);
|
|
1374
1379
|
cleanup();
|
|
1375
1380
|
};
|
|
@@ -1416,6 +1421,28 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
|
1416
1421
|
return;
|
|
1417
1422
|
}
|
|
1418
1423
|
|
|
1424
|
+
// in single peer connection case, the trackID is locally generated,
|
|
1425
|
+
// not the TR_ prefixed one generated by the server,
|
|
1426
|
+
// use `mid` to find the appropriate track.
|
|
1427
|
+
if (!trackId.startsWith('TR')) {
|
|
1428
|
+
const id = this.engine.getTrackIdForReceiver(receiver);
|
|
1429
|
+
if (!id) {
|
|
1430
|
+
this.log.error(
|
|
1431
|
+
`Tried to add a track whose 'sid' could not be found for a participant, that's not present. Sid: ${participantSid}`,
|
|
1432
|
+
this.logContext,
|
|
1433
|
+
);
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
trackId = id;
|
|
1438
|
+
}
|
|
1439
|
+
if (!trackId.startsWith('TR')) {
|
|
1440
|
+
this.log.warn(
|
|
1441
|
+
`Tried to add a track whose 'sid' could not be determined for a participant, that's not present. Sid: ${participantSid}, streamId: ${streamId}, trackId: ${trackId}`,
|
|
1442
|
+
{ ...this.logContext, rpID: participantSid, streamId, trackId },
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1419
1446
|
let adaptiveStreamSettings: AdaptiveStreamSettings | undefined;
|
|
1420
1447
|
if (this.options.adaptiveStream) {
|
|
1421
1448
|
if (typeof this.options.adaptiveStream === 'object') {
|
|
@@ -2541,6 +2568,13 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
|
|
|
2541
2568
|
if (event !== RoomEvent.ActiveSpeakersChanged && event !== RoomEvent.TranscriptionReceived) {
|
|
2542
2569
|
// only extract logContext from arguments in order to avoid logging the whole object tree
|
|
2543
2570
|
const minimizedArgs = mapArgs(args).filter((arg: unknown) => arg !== undefined);
|
|
2571
|
+
if (event === RoomEvent.TrackSubscribed || event === RoomEvent.TrackUnsubscribed) {
|
|
2572
|
+
this.log.trace(`subscribe trace: ${event}`, {
|
|
2573
|
+
...this.logContext,
|
|
2574
|
+
event,
|
|
2575
|
+
args: minimizedArgs,
|
|
2576
|
+
});
|
|
2577
|
+
}
|
|
2544
2578
|
this.log.debug(`room event ${event}`, { ...this.logContext, event, args: minimizedArgs });
|
|
2545
2579
|
}
|
|
2546
2580
|
return super.emit(event, ...args);
|
|
@@ -1771,9 +1771,10 @@ export default class LocalParticipant extends Participant {
|
|
|
1771
1771
|
destinationIdentity,
|
|
1772
1772
|
method,
|
|
1773
1773
|
payload,
|
|
1774
|
-
responseTimeout =
|
|
1774
|
+
responseTimeout = 15000,
|
|
1775
1775
|
}: PerformRpcParams): Promise<string> {
|
|
1776
|
-
const maxRoundTripLatency =
|
|
1776
|
+
const maxRoundTripLatency = 7000;
|
|
1777
|
+
const minEffectiveTimeout = maxRoundTripLatency + 1000;
|
|
1777
1778
|
|
|
1778
1779
|
return new Promise(async (resolve, reject) => {
|
|
1779
1780
|
if (byteLength(payload) > MAX_PAYLOAD_BYTES) {
|
|
@@ -1789,14 +1790,9 @@ export default class LocalParticipant extends Participant {
|
|
|
1789
1790
|
return;
|
|
1790
1791
|
}
|
|
1791
1792
|
|
|
1793
|
+
const effectiveTimeout = Math.max(responseTimeout, minEffectiveTimeout);
|
|
1792
1794
|
const id = crypto.randomUUID();
|
|
1793
|
-
await this.publishRpcRequest(
|
|
1794
|
-
destinationIdentity,
|
|
1795
|
-
id,
|
|
1796
|
-
method,
|
|
1797
|
-
payload,
|
|
1798
|
-
responseTimeout - maxRoundTripLatency,
|
|
1799
|
-
);
|
|
1795
|
+
await this.publishRpcRequest(destinationIdentity, id, method, payload, effectiveTimeout);
|
|
1800
1796
|
|
|
1801
1797
|
const ackTimeoutId = setTimeout(() => {
|
|
1802
1798
|
this.pendingAcks.delete(id);
|
package/src/room/rpc.ts
CHANGED
|
@@ -11,7 +11,12 @@ export interface PerformRpcParams {
|
|
|
11
11
|
method: string;
|
|
12
12
|
/** The method payload */
|
|
13
13
|
payload: string;
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Timeout for receiving a response after the initial connection (milliseconds).
|
|
16
|
+
* If a value less than 8000ms is provided, it will be automatically clamped to 8000ms
|
|
17
|
+
* to ensure sufficient time for round-trip latency buffering.
|
|
18
|
+
* Default: 15000ms.
|
|
19
|
+
*/
|
|
15
20
|
responseTimeout?: number;
|
|
16
21
|
}
|
|
17
22
|
|