livekit-client 2.22.0 → 2.22.1
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.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +187 -1
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +1764 -121
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.fm.worker.js +1 -1
- package/dist/livekit-client.fm.worker.js.map +1 -1
- package/dist/livekit-client.fm.worker.mjs +187 -1
- package/dist/livekit-client.fm.worker.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 +25 -1
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/api/SignalClientStateMachine.d.ts +85 -0
- package/dist/src/api/SignalClientStateMachine.d.ts.map +1 -0
- package/dist/src/api/WebSocketStream.d.ts.map +1 -1
- package/dist/src/api/utils.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/logger.d.ts +2 -1
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/options.d.ts +22 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +2 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +7 -2
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +8 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +1 -1
- package/dist/src/room/statsSummary.d.ts +13 -0
- package/dist/src/room/statsSummary.d.ts.map +1 -0
- package/dist/src/room/token-source/utils.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +10 -0
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/utils/machineInspector.d.ts +54 -0
- package/dist/src/utils/machineInspector.d.ts.map +1 -0
- package/dist/ts4.2/api/SignalClient.d.ts +25 -1
- package/dist/ts4.2/api/SignalClientStateMachine.d.ts +85 -0
- package/dist/ts4.2/index.d.ts +3 -2
- package/dist/ts4.2/logger.d.ts +2 -1
- package/dist/ts4.2/options.d.ts +22 -0
- package/dist/ts4.2/room/PCTransport.d.ts +2 -1
- package/dist/ts4.2/room/RTCEngine.d.ts +7 -2
- package/dist/ts4.2/room/Room.d.ts +8 -1
- package/dist/ts4.2/room/events.d.ts +1 -1
- package/dist/ts4.2/room/statsSummary.d.ts +13 -0
- package/dist/ts4.2/room/track/Track.d.ts +10 -0
- package/dist/ts4.2/utils/machineInspector.d.ts +54 -0
- package/package.json +7 -1
- package/src/api/SignalClient.test.ts +320 -8
- package/src/api/SignalClient.ts +260 -82
- package/src/api/SignalClientStateMachine.test.ts +472 -0
- package/src/api/SignalClientStateMachine.ts +180 -0
- package/src/api/WebSocketStream.ts +19 -3
- package/src/api/utils.test.ts +20 -1
- package/src/api/utils.ts +5 -0
- package/src/index.ts +5 -0
- package/src/logger.ts +1 -0
- package/src/options.ts +24 -0
- package/src/room/PCTransport.ts +2 -1
- package/src/room/RTCEngine.ts +16 -7
- package/src/room/Room.ts +70 -5
- package/src/room/events.ts +1 -1
- package/src/room/statsSummary.ts +187 -0
- package/src/room/token-source/test-tokens.ts +20 -0
- package/src/room/token-source/utils.test.ts +27 -0
- package/src/room/token-source/utils.ts +12 -5
- package/src/room/track/LocalAudioTrack.ts +9 -3
- package/src/room/track/Track.ts +27 -0
- package/src/room/utils.test.ts +24 -1
- package/src/room/utils.ts +1 -1
- package/src/utils/machineInspector.ts +90 -0
|
@@ -381,6 +381,7 @@ var LoggerNames;
|
|
|
381
381
|
LoggerNames["DataTracks"] = "livekit-data-tracks";
|
|
382
382
|
LoggerNames["Region"] = "livekit-region";
|
|
383
383
|
LoggerNames["ICE"] = "livekit-ice";
|
|
384
|
+
LoggerNames["Stats"] = "livekit-stats";
|
|
384
385
|
})(LoggerNames || (LoggerNames = {}));
|
|
385
386
|
let livekitLogger = loglevelExports.getLogger(LoggerNames.Default);
|
|
386
387
|
Object.values(LoggerNames).map(name => loglevelExports.getLogger(name));
|
|
@@ -4866,7 +4867,7 @@ var RoomEvent;
|
|
|
4866
4867
|
* When a [[RemoteParticipant]] leaves *after* the local
|
|
4867
4868
|
* participant has joined.
|
|
4868
4869
|
*
|
|
4869
|
-
* args: ([[RemoteParticipant]])
|
|
4870
|
+
* args: ([[RemoteParticipant]], [[DisconnectReason]] | undefined)
|
|
4870
4871
|
*/
|
|
4871
4872
|
RoomEvent["ParticipantDisconnected"] = "participantDisconnected";
|
|
4872
4873
|
/**
|
|
@@ -5436,6 +5437,172 @@ var TrackEvent;
|
|
|
5436
5437
|
TrackEvent["PreConnectBufferFlushed"] = "preConnectBufferFlushed";
|
|
5437
5438
|
})(TrackEvent || (TrackEvent = {}));
|
|
5438
5439
|
|
|
5440
|
+
function compact(summary) {
|
|
5441
|
+
const compacted = {};
|
|
5442
|
+
for (const _ref of Object.entries(summary)) {
|
|
5443
|
+
var _ref2 = _slicedToArray(_ref, 2);
|
|
5444
|
+
const key = _ref2[0];
|
|
5445
|
+
const value = _ref2[1];
|
|
5446
|
+
if (value !== undefined) {
|
|
5447
|
+
compacted[key] = value;
|
|
5448
|
+
}
|
|
5449
|
+
}
|
|
5450
|
+
return compacted;
|
|
5451
|
+
}
|
|
5452
|
+
function resolution(width, height) {
|
|
5453
|
+
return width && height ? "".concat(width, "x").concat(height) : undefined;
|
|
5454
|
+
}
|
|
5455
|
+
/** keeps the derived durations readable; reported values are logged as they are */
|
|
5456
|
+
function round(seconds) {
|
|
5457
|
+
return Math.round(seconds * 10000) / 10000;
|
|
5458
|
+
}
|
|
5459
|
+
/**
|
|
5460
|
+
* Average time media spent in the jitter buffer, in s. Both counters are
|
|
5461
|
+
* cumulative, so this is the average over the lifetime of the stream.
|
|
5462
|
+
*/
|
|
5463
|
+
function jitterBuffer(stat) {
|
|
5464
|
+
const delay = stat.jitterBufferDelay;
|
|
5465
|
+
const emitted = stat.jitterBufferEmittedCount;
|
|
5466
|
+
return delay !== undefined && emitted ? round(delay / emitted) : undefined;
|
|
5467
|
+
}
|
|
5468
|
+
/**
|
|
5469
|
+
* Playout delay in s. Video receive reports it directly, the audio path keeps it
|
|
5470
|
+
* in the linked `media-playout` stats summed over the samples played out. Pairs
|
|
5471
|
+
* with `RemoteTrack.setPlayoutDelay`.
|
|
5472
|
+
*/
|
|
5473
|
+
function playoutDelay(stat, playout) {
|
|
5474
|
+
if (stat.playoutDelay !== undefined) {
|
|
5475
|
+
return round(stat.playoutDelay);
|
|
5476
|
+
}
|
|
5477
|
+
const total = playout === null || playout === void 0 ? void 0 : playout.totalPlayoutDelay;
|
|
5478
|
+
const samples = playout === null || playout === void 0 ? void 0 : playout.totalSamplesCount;
|
|
5479
|
+
return total !== undefined && samples ? round(total / samples) : undefined;
|
|
5480
|
+
}
|
|
5481
|
+
/**
|
|
5482
|
+
* Picks the interesting fields out of a `getStats()` report and groups them by
|
|
5483
|
+
* RTP stream, so a stats dump can be read without unfolding the raw report.
|
|
5484
|
+
*/
|
|
5485
|
+
function summarizeStatsReport(report) {
|
|
5486
|
+
var _a, _b;
|
|
5487
|
+
const byId = new Map();
|
|
5488
|
+
const candidatePairs = [];
|
|
5489
|
+
const inbound = [];
|
|
5490
|
+
const outbound = [];
|
|
5491
|
+
let transport;
|
|
5492
|
+
report.forEach(stat => byId.set(stat.id, stat));
|
|
5493
|
+
const codecOf = stat => {
|
|
5494
|
+
var _a;
|
|
5495
|
+
return stat.codecId ? (_a = byId.get(stat.codecId)) === null || _a === void 0 ? void 0 : _a.mimeType : undefined;
|
|
5496
|
+
};
|
|
5497
|
+
const relatedOf = (stat, key) => stat[key] ? byId.get(stat[key]) : undefined;
|
|
5498
|
+
report.forEach(stat => {
|
|
5499
|
+
switch (stat.type) {
|
|
5500
|
+
case 'inbound-rtp':
|
|
5501
|
+
{
|
|
5502
|
+
const playout = relatedOf(stat, 'playoutId');
|
|
5503
|
+
inbound.push(compact({
|
|
5504
|
+
kind: stat.kind,
|
|
5505
|
+
ssrc: stat.ssrc,
|
|
5506
|
+
mid: stat.mid,
|
|
5507
|
+
// matches `streamTrackID` in the track's own log context
|
|
5508
|
+
trackId: stat.trackIdentifier,
|
|
5509
|
+
codec: codecOf(stat),
|
|
5510
|
+
decoder: stat.decoderImplementation,
|
|
5511
|
+
resolution: resolution(stat.frameWidth, stat.frameHeight),
|
|
5512
|
+
fps: stat.framesPerSecond,
|
|
5513
|
+
bytesReceived: stat.bytesReceived,
|
|
5514
|
+
packetsReceived: stat.packetsReceived,
|
|
5515
|
+
packetsLost: stat.packetsLost,
|
|
5516
|
+
packetsDiscarded: stat.packetsDiscarded,
|
|
5517
|
+
// frames received without frames decoded is a decode failure
|
|
5518
|
+
framesReceived: stat.framesReceived,
|
|
5519
|
+
framesDecoded: stat.framesDecoded,
|
|
5520
|
+
framesDropped: stat.framesDropped,
|
|
5521
|
+
keyFramesDecoded: stat.keyFramesDecoded,
|
|
5522
|
+
freezeCount: stat.freezeCount,
|
|
5523
|
+
totalFreezesDuration: stat.totalFreezesDuration,
|
|
5524
|
+
pauseCount: stat.pauseCount,
|
|
5525
|
+
nackCount: stat.nackCount,
|
|
5526
|
+
pliCount: stat.pliCount,
|
|
5527
|
+
firCount: stat.firCount,
|
|
5528
|
+
jitter: stat.jitter,
|
|
5529
|
+
jitterBuffer: jitterBuffer(stat),
|
|
5530
|
+
playoutDelay: playoutDelay(stat, playout),
|
|
5531
|
+
audioLevel: stat.audioLevel,
|
|
5532
|
+
totalSamplesReceived: stat.totalSamplesReceived,
|
|
5533
|
+
concealedSamples: stat.concealedSamples
|
|
5534
|
+
}));
|
|
5535
|
+
break;
|
|
5536
|
+
}
|
|
5537
|
+
case 'outbound-rtp':
|
|
5538
|
+
{
|
|
5539
|
+
const remote = relatedOf(stat, 'remoteId');
|
|
5540
|
+
const source = relatedOf(stat, 'mediaSourceId');
|
|
5541
|
+
outbound.push(compact({
|
|
5542
|
+
kind: stat.kind,
|
|
5543
|
+
ssrc: stat.ssrc,
|
|
5544
|
+
mid: stat.mid,
|
|
5545
|
+
rid: stat.rid,
|
|
5546
|
+
trackId: source === null || source === void 0 ? void 0 : source.trackIdentifier,
|
|
5547
|
+
active: stat.active,
|
|
5548
|
+
codec: codecOf(stat),
|
|
5549
|
+
encoder: stat.encoderImplementation,
|
|
5550
|
+
resolution: resolution(stat.frameWidth, stat.frameHeight),
|
|
5551
|
+
fps: stat.framesPerSecond,
|
|
5552
|
+
// what the source produces, to tell a stalled capture from a stalled encoder
|
|
5553
|
+
captureResolution: resolution(source === null || source === void 0 ? void 0 : source.width, source === null || source === void 0 ? void 0 : source.height),
|
|
5554
|
+
captureFps: source === null || source === void 0 ? void 0 : source.framesPerSecond,
|
|
5555
|
+
audioLevel: source === null || source === void 0 ? void 0 : source.audioLevel,
|
|
5556
|
+
targetBitrate: stat.targetBitrate,
|
|
5557
|
+
bytesSent: stat.bytesSent,
|
|
5558
|
+
packetsSent: stat.packetsSent,
|
|
5559
|
+
retransmittedPacketsSent: stat.retransmittedPacketsSent,
|
|
5560
|
+
framesEncoded: stat.framesEncoded,
|
|
5561
|
+
keyFramesEncoded: stat.keyFramesEncoded,
|
|
5562
|
+
limitedBy: stat.qualityLimitationReason === 'none' ? undefined : stat.qualityLimitationReason,
|
|
5563
|
+
nackCount: stat.nackCount,
|
|
5564
|
+
pliCount: stat.pliCount,
|
|
5565
|
+
firCount: stat.firCount,
|
|
5566
|
+
// loss, jitter and RTT are only known from what the remote reports
|
|
5567
|
+
remotePacketsLost: remote === null || remote === void 0 ? void 0 : remote.packetsLost,
|
|
5568
|
+
remoteFractionLost: remote === null || remote === void 0 ? void 0 : remote.fractionLost,
|
|
5569
|
+
remoteJitter: remote === null || remote === void 0 ? void 0 : remote.jitter,
|
|
5570
|
+
remoteRoundTripTime: remote === null || remote === void 0 ? void 0 : remote.roundTripTime
|
|
5571
|
+
}));
|
|
5572
|
+
break;
|
|
5573
|
+
}
|
|
5574
|
+
case 'transport':
|
|
5575
|
+
transport = stat;
|
|
5576
|
+
break;
|
|
5577
|
+
case 'candidate-pair':
|
|
5578
|
+
candidatePairs.push(stat);
|
|
5579
|
+
break;
|
|
5580
|
+
}
|
|
5581
|
+
});
|
|
5582
|
+
const selectedPairId = transport === null || transport === void 0 ? void 0 : transport.selectedCandidatePairId;
|
|
5583
|
+
const pair = (_b = (_a = selectedPairId ? byId.get(selectedPairId) : undefined) !== null && _a !== void 0 ? _a : candidatePairs.find(candidate => candidate.selected)) !== null && _b !== void 0 ? _b : candidatePairs.find(candidate => candidate.nominated);
|
|
5584
|
+
const local = (pair === null || pair === void 0 ? void 0 : pair.localCandidateId) ? byId.get(pair.localCandidateId) : undefined;
|
|
5585
|
+
const remote = (pair === null || pair === void 0 ? void 0 : pair.remoteCandidateId) ? byId.get(pair.remoteCandidateId) : undefined;
|
|
5586
|
+
const connection = compact({
|
|
5587
|
+
ice: transport === null || transport === void 0 ? void 0 : transport.iceState,
|
|
5588
|
+
dtls: transport === null || transport === void 0 ? void 0 : transport.dtlsState,
|
|
5589
|
+
route: local && remote ? "".concat(local.candidateType, "/").concat(local.protocol, " -> ").concat(remote.candidateType) : undefined,
|
|
5590
|
+
network: local === null || local === void 0 ? void 0 : local.networkType,
|
|
5591
|
+
currentRoundTripTime: pair === null || pair === void 0 ? void 0 : pair.currentRoundTripTime,
|
|
5592
|
+
// the send bandwidth estimate; no RTP stream reports it
|
|
5593
|
+
availableOutgoingBitrate: pair === null || pair === void 0 ? void 0 : pair.availableOutgoingBitrate,
|
|
5594
|
+
availableIncomingBitrate: pair === null || pair === void 0 ? void 0 : pair.availableIncomingBitrate,
|
|
5595
|
+
bytesSent: pair === null || pair === void 0 ? void 0 : pair.bytesSent,
|
|
5596
|
+
bytesReceived: pair === null || pair === void 0 ? void 0 : pair.bytesReceived,
|
|
5597
|
+
candidatePairChanges: transport === null || transport === void 0 ? void 0 : transport.selectedCandidatePairChanges
|
|
5598
|
+
});
|
|
5599
|
+
return {
|
|
5600
|
+
connection: Object.keys(connection).length > 0 ? connection : undefined,
|
|
5601
|
+
outbound: outbound.length > 0 ? outbound : undefined,
|
|
5602
|
+
inbound: inbound.length > 0 ? inbound : undefined
|
|
5603
|
+
};
|
|
5604
|
+
}
|
|
5605
|
+
|
|
5439
5606
|
class VideoPreset {
|
|
5440
5607
|
constructor(widthOrOptions, height, maxBitrate, maxFramerate, priority) {
|
|
5441
5608
|
if (typeof widthOrOptions === 'object') {
|
|
@@ -5604,6 +5771,7 @@ class Track extends eventsExports.EventEmitter {
|
|
|
5604
5771
|
this._streamState = Track.StreamState.Active;
|
|
5605
5772
|
this.isInBackground = false;
|
|
5606
5773
|
this._currentBitrate = 0;
|
|
5774
|
+
this.finalStatsLogged = false;
|
|
5607
5775
|
this.log = livekitLogger;
|
|
5608
5776
|
this.appVisibilityChangedListener = () => {
|
|
5609
5777
|
if (this.backgroundTimeout) {
|
|
@@ -5752,6 +5920,24 @@ class Track extends eventsExports.EventEmitter {
|
|
|
5752
5920
|
cancelAnimationFrame(this.timeSyncHandle);
|
|
5753
5921
|
this.timeSyncHandle = undefined;
|
|
5754
5922
|
}
|
|
5923
|
+
this.logFinalStats();
|
|
5924
|
+
}
|
|
5925
|
+
/**
|
|
5926
|
+
* Dumps the raw stats of the track as it ends, once: a track that stops
|
|
5927
|
+
* between two of the room's stats dumps is gone by the time the next one runs.
|
|
5928
|
+
*/
|
|
5929
|
+
logFinalStats() {
|
|
5930
|
+
if (this.finalStatsLogged) {
|
|
5931
|
+
return;
|
|
5932
|
+
}
|
|
5933
|
+
this.finalStatsLogged = true;
|
|
5934
|
+
this.getRTCStatsReport().then(report => {
|
|
5935
|
+
if (report) {
|
|
5936
|
+
this.log.info('final track stats', summarizeStatsReport(report));
|
|
5937
|
+
}
|
|
5938
|
+
}).catch(error => this.log.debug('could not collect final track stats', {
|
|
5939
|
+
error
|
|
5940
|
+
}));
|
|
5755
5941
|
}
|
|
5756
5942
|
/** @internal */
|
|
5757
5943
|
updateLoggerOptions(loggerOptions) {
|