livekit-client 2.21.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/README.md +10 -10
- 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 +189 -2
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +2243 -270
- 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 +189 -2
- 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 +51 -3
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +27 -3
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +10 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +1 -1
- package/dist/src/room/participant/LocalParticipant.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/TokenSource.d.ts +19 -10
- package/dist/src/room/token-source/TokenSource.d.ts.map +1 -1
- 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/LocalVideoTrack.d.ts +12 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteTrack.d.ts +3 -0
- package/dist/src/room/track/RemoteTrack.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/room/utils.d.ts +15 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/test/promiseState.d.ts +12 -0
- package/dist/src/test/promiseState.d.ts.map +1 -0
- package/dist/src/test/signalToken.d.ts.map +1 -1
- package/dist/src/utils/AsyncQueue.d.ts +3 -3
- package/dist/src/utils/AsyncQueue.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 +51 -3
- package/dist/ts4.2/room/RTCEngine.d.ts +27 -3
- package/dist/ts4.2/room/Room.d.ts +10 -1
- package/dist/ts4.2/room/events.d.ts +1 -1
- package/dist/ts4.2/room/participant/LocalParticipant.d.ts +1 -1
- package/dist/ts4.2/room/statsSummary.d.ts +13 -0
- package/dist/ts4.2/room/token-source/TokenSource.d.ts +17 -8
- package/dist/ts4.2/room/track/LocalVideoTrack.d.ts +12 -1
- package/dist/ts4.2/room/track/RemoteTrack.d.ts +3 -0
- package/dist/ts4.2/room/track/Track.d.ts +10 -0
- package/dist/ts4.2/room/utils.d.ts +15 -0
- package/dist/ts4.2/test/promiseState.d.ts +12 -0
- package/dist/ts4.2/utils/AsyncQueue.d.ts +3 -3
- package/dist/ts4.2/utils/machineInspector.d.ts +54 -0
- package/package.json +19 -12
- package/src/api/SignalClient.e2e.test.ts +16 -9
- 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/e2ee/utils.ts +1 -1
- package/src/index.ts +5 -0
- package/src/logger.ts +1 -0
- package/src/options.ts +24 -0
- package/src/room/PCTransport.test.ts +243 -1
- package/src/room/PCTransport.ts +183 -81
- package/src/room/RTCEngine.test.ts +339 -2
- package/src/room/RTCEngine.ts +168 -18
- package/src/room/Room.test.ts +134 -3
- package/src/room/Room.ts +122 -22
- package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +1 -1
- package/src/room/data-stream/incoming/StreamReader.ts +1 -1
- package/src/room/errors.ts +1 -2
- package/src/room/events.ts +1 -1
- package/src/room/statsSummary.ts +187 -0
- package/src/room/token-source/TokenSource.ts +25 -12
- 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/LocalVideoTrack.test.ts +105 -2
- package/src/room/track/LocalVideoTrack.ts +36 -10
- package/src/room/track/RemoteTrack.test.ts +144 -0
- package/src/room/track/RemoteTrack.ts +39 -12
- package/src/room/track/Track.ts +29 -1
- package/src/room/utils.test.ts +94 -2
- package/src/room/utils.ts +53 -1
- package/src/test/promiseState.ts +23 -0
- package/src/test/signalServerSetup.ts +2 -1
- package/src/test/signalToken.ts +17 -13
- package/src/type-polyfills/header-extensions.d.ts +13 -0
- package/src/utils/AsyncQueue.ts +3 -3
- package/src/utils/machineInspector.ts +90 -0
|
@@ -4383,6 +4383,7 @@ var LoggerNames;
|
|
|
4383
4383
|
LoggerNames["DataTracks"] = "livekit-data-tracks";
|
|
4384
4384
|
LoggerNames["Region"] = "livekit-region";
|
|
4385
4385
|
LoggerNames["ICE"] = "livekit-ice";
|
|
4386
|
+
LoggerNames["Stats"] = "livekit-stats";
|
|
4386
4387
|
})(LoggerNames || (LoggerNames = {}));
|
|
4387
4388
|
let livekitLogger = loglevelExports.getLogger(LoggerNames.Default);
|
|
4388
4389
|
Object.values(LoggerNames).map(name => loglevelExports.getLogger(name));
|
|
@@ -4499,7 +4500,7 @@ var RoomEvent;
|
|
|
4499
4500
|
* When a [[RemoteParticipant]] leaves *after* the local
|
|
4500
4501
|
* participant has joined.
|
|
4501
4502
|
*
|
|
4502
|
-
* args: ([[RemoteParticipant]])
|
|
4503
|
+
* args: ([[RemoteParticipant]], [[DisconnectReason]] | undefined)
|
|
4503
4504
|
*/
|
|
4504
4505
|
RoomEvent["ParticipantDisconnected"] = "participantDisconnected";
|
|
4505
4506
|
/**
|
|
@@ -5069,6 +5070,172 @@ var TrackEvent;
|
|
|
5069
5070
|
TrackEvent["PreConnectBufferFlushed"] = "preConnectBufferFlushed";
|
|
5070
5071
|
})(TrackEvent || (TrackEvent = {}));
|
|
5071
5072
|
|
|
5073
|
+
function compact(summary) {
|
|
5074
|
+
const compacted = {};
|
|
5075
|
+
for (const _ref of Object.entries(summary)) {
|
|
5076
|
+
var _ref2 = _slicedToArray(_ref, 2);
|
|
5077
|
+
const key = _ref2[0];
|
|
5078
|
+
const value = _ref2[1];
|
|
5079
|
+
if (value !== undefined) {
|
|
5080
|
+
compacted[key] = value;
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
5083
|
+
return compacted;
|
|
5084
|
+
}
|
|
5085
|
+
function resolution(width, height) {
|
|
5086
|
+
return width && height ? "".concat(width, "x").concat(height) : undefined;
|
|
5087
|
+
}
|
|
5088
|
+
/** keeps the derived durations readable; reported values are logged as they are */
|
|
5089
|
+
function round(seconds) {
|
|
5090
|
+
return Math.round(seconds * 10000) / 10000;
|
|
5091
|
+
}
|
|
5092
|
+
/**
|
|
5093
|
+
* Average time media spent in the jitter buffer, in s. Both counters are
|
|
5094
|
+
* cumulative, so this is the average over the lifetime of the stream.
|
|
5095
|
+
*/
|
|
5096
|
+
function jitterBuffer(stat) {
|
|
5097
|
+
const delay = stat.jitterBufferDelay;
|
|
5098
|
+
const emitted = stat.jitterBufferEmittedCount;
|
|
5099
|
+
return delay !== undefined && emitted ? round(delay / emitted) : undefined;
|
|
5100
|
+
}
|
|
5101
|
+
/**
|
|
5102
|
+
* Playout delay in s. Video receive reports it directly, the audio path keeps it
|
|
5103
|
+
* in the linked `media-playout` stats summed over the samples played out. Pairs
|
|
5104
|
+
* with `RemoteTrack.setPlayoutDelay`.
|
|
5105
|
+
*/
|
|
5106
|
+
function playoutDelay(stat, playout) {
|
|
5107
|
+
if (stat.playoutDelay !== undefined) {
|
|
5108
|
+
return round(stat.playoutDelay);
|
|
5109
|
+
}
|
|
5110
|
+
const total = playout === null || playout === void 0 ? void 0 : playout.totalPlayoutDelay;
|
|
5111
|
+
const samples = playout === null || playout === void 0 ? void 0 : playout.totalSamplesCount;
|
|
5112
|
+
return total !== undefined && samples ? round(total / samples) : undefined;
|
|
5113
|
+
}
|
|
5114
|
+
/**
|
|
5115
|
+
* Picks the interesting fields out of a `getStats()` report and groups them by
|
|
5116
|
+
* RTP stream, so a stats dump can be read without unfolding the raw report.
|
|
5117
|
+
*/
|
|
5118
|
+
function summarizeStatsReport(report) {
|
|
5119
|
+
var _a, _b;
|
|
5120
|
+
const byId = new Map();
|
|
5121
|
+
const candidatePairs = [];
|
|
5122
|
+
const inbound = [];
|
|
5123
|
+
const outbound = [];
|
|
5124
|
+
let transport;
|
|
5125
|
+
report.forEach(stat => byId.set(stat.id, stat));
|
|
5126
|
+
const codecOf = stat => {
|
|
5127
|
+
var _a;
|
|
5128
|
+
return stat.codecId ? (_a = byId.get(stat.codecId)) === null || _a === void 0 ? void 0 : _a.mimeType : undefined;
|
|
5129
|
+
};
|
|
5130
|
+
const relatedOf = (stat, key) => stat[key] ? byId.get(stat[key]) : undefined;
|
|
5131
|
+
report.forEach(stat => {
|
|
5132
|
+
switch (stat.type) {
|
|
5133
|
+
case 'inbound-rtp':
|
|
5134
|
+
{
|
|
5135
|
+
const playout = relatedOf(stat, 'playoutId');
|
|
5136
|
+
inbound.push(compact({
|
|
5137
|
+
kind: stat.kind,
|
|
5138
|
+
ssrc: stat.ssrc,
|
|
5139
|
+
mid: stat.mid,
|
|
5140
|
+
// matches `streamTrackID` in the track's own log context
|
|
5141
|
+
trackId: stat.trackIdentifier,
|
|
5142
|
+
codec: codecOf(stat),
|
|
5143
|
+
decoder: stat.decoderImplementation,
|
|
5144
|
+
resolution: resolution(stat.frameWidth, stat.frameHeight),
|
|
5145
|
+
fps: stat.framesPerSecond,
|
|
5146
|
+
bytesReceived: stat.bytesReceived,
|
|
5147
|
+
packetsReceived: stat.packetsReceived,
|
|
5148
|
+
packetsLost: stat.packetsLost,
|
|
5149
|
+
packetsDiscarded: stat.packetsDiscarded,
|
|
5150
|
+
// frames received without frames decoded is a decode failure
|
|
5151
|
+
framesReceived: stat.framesReceived,
|
|
5152
|
+
framesDecoded: stat.framesDecoded,
|
|
5153
|
+
framesDropped: stat.framesDropped,
|
|
5154
|
+
keyFramesDecoded: stat.keyFramesDecoded,
|
|
5155
|
+
freezeCount: stat.freezeCount,
|
|
5156
|
+
totalFreezesDuration: stat.totalFreezesDuration,
|
|
5157
|
+
pauseCount: stat.pauseCount,
|
|
5158
|
+
nackCount: stat.nackCount,
|
|
5159
|
+
pliCount: stat.pliCount,
|
|
5160
|
+
firCount: stat.firCount,
|
|
5161
|
+
jitter: stat.jitter,
|
|
5162
|
+
jitterBuffer: jitterBuffer(stat),
|
|
5163
|
+
playoutDelay: playoutDelay(stat, playout),
|
|
5164
|
+
audioLevel: stat.audioLevel,
|
|
5165
|
+
totalSamplesReceived: stat.totalSamplesReceived,
|
|
5166
|
+
concealedSamples: stat.concealedSamples
|
|
5167
|
+
}));
|
|
5168
|
+
break;
|
|
5169
|
+
}
|
|
5170
|
+
case 'outbound-rtp':
|
|
5171
|
+
{
|
|
5172
|
+
const remote = relatedOf(stat, 'remoteId');
|
|
5173
|
+
const source = relatedOf(stat, 'mediaSourceId');
|
|
5174
|
+
outbound.push(compact({
|
|
5175
|
+
kind: stat.kind,
|
|
5176
|
+
ssrc: stat.ssrc,
|
|
5177
|
+
mid: stat.mid,
|
|
5178
|
+
rid: stat.rid,
|
|
5179
|
+
trackId: source === null || source === void 0 ? void 0 : source.trackIdentifier,
|
|
5180
|
+
active: stat.active,
|
|
5181
|
+
codec: codecOf(stat),
|
|
5182
|
+
encoder: stat.encoderImplementation,
|
|
5183
|
+
resolution: resolution(stat.frameWidth, stat.frameHeight),
|
|
5184
|
+
fps: stat.framesPerSecond,
|
|
5185
|
+
// what the source produces, to tell a stalled capture from a stalled encoder
|
|
5186
|
+
captureResolution: resolution(source === null || source === void 0 ? void 0 : source.width, source === null || source === void 0 ? void 0 : source.height),
|
|
5187
|
+
captureFps: source === null || source === void 0 ? void 0 : source.framesPerSecond,
|
|
5188
|
+
audioLevel: source === null || source === void 0 ? void 0 : source.audioLevel,
|
|
5189
|
+
targetBitrate: stat.targetBitrate,
|
|
5190
|
+
bytesSent: stat.bytesSent,
|
|
5191
|
+
packetsSent: stat.packetsSent,
|
|
5192
|
+
retransmittedPacketsSent: stat.retransmittedPacketsSent,
|
|
5193
|
+
framesEncoded: stat.framesEncoded,
|
|
5194
|
+
keyFramesEncoded: stat.keyFramesEncoded,
|
|
5195
|
+
limitedBy: stat.qualityLimitationReason === 'none' ? undefined : stat.qualityLimitationReason,
|
|
5196
|
+
nackCount: stat.nackCount,
|
|
5197
|
+
pliCount: stat.pliCount,
|
|
5198
|
+
firCount: stat.firCount,
|
|
5199
|
+
// loss, jitter and RTT are only known from what the remote reports
|
|
5200
|
+
remotePacketsLost: remote === null || remote === void 0 ? void 0 : remote.packetsLost,
|
|
5201
|
+
remoteFractionLost: remote === null || remote === void 0 ? void 0 : remote.fractionLost,
|
|
5202
|
+
remoteJitter: remote === null || remote === void 0 ? void 0 : remote.jitter,
|
|
5203
|
+
remoteRoundTripTime: remote === null || remote === void 0 ? void 0 : remote.roundTripTime
|
|
5204
|
+
}));
|
|
5205
|
+
break;
|
|
5206
|
+
}
|
|
5207
|
+
case 'transport':
|
|
5208
|
+
transport = stat;
|
|
5209
|
+
break;
|
|
5210
|
+
case 'candidate-pair':
|
|
5211
|
+
candidatePairs.push(stat);
|
|
5212
|
+
break;
|
|
5213
|
+
}
|
|
5214
|
+
});
|
|
5215
|
+
const selectedPairId = transport === null || transport === void 0 ? void 0 : transport.selectedCandidatePairId;
|
|
5216
|
+
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);
|
|
5217
|
+
const local = (pair === null || pair === void 0 ? void 0 : pair.localCandidateId) ? byId.get(pair.localCandidateId) : undefined;
|
|
5218
|
+
const remote = (pair === null || pair === void 0 ? void 0 : pair.remoteCandidateId) ? byId.get(pair.remoteCandidateId) : undefined;
|
|
5219
|
+
const connection = compact({
|
|
5220
|
+
ice: transport === null || transport === void 0 ? void 0 : transport.iceState,
|
|
5221
|
+
dtls: transport === null || transport === void 0 ? void 0 : transport.dtlsState,
|
|
5222
|
+
route: local && remote ? "".concat(local.candidateType, "/").concat(local.protocol, " -> ").concat(remote.candidateType) : undefined,
|
|
5223
|
+
network: local === null || local === void 0 ? void 0 : local.networkType,
|
|
5224
|
+
currentRoundTripTime: pair === null || pair === void 0 ? void 0 : pair.currentRoundTripTime,
|
|
5225
|
+
// the send bandwidth estimate; no RTP stream reports it
|
|
5226
|
+
availableOutgoingBitrate: pair === null || pair === void 0 ? void 0 : pair.availableOutgoingBitrate,
|
|
5227
|
+
availableIncomingBitrate: pair === null || pair === void 0 ? void 0 : pair.availableIncomingBitrate,
|
|
5228
|
+
bytesSent: pair === null || pair === void 0 ? void 0 : pair.bytesSent,
|
|
5229
|
+
bytesReceived: pair === null || pair === void 0 ? void 0 : pair.bytesReceived,
|
|
5230
|
+
candidatePairChanges: transport === null || transport === void 0 ? void 0 : transport.selectedCandidatePairChanges
|
|
5231
|
+
});
|
|
5232
|
+
return {
|
|
5233
|
+
connection: Object.keys(connection).length > 0 ? connection : undefined,
|
|
5234
|
+
outbound: outbound.length > 0 ? outbound : undefined,
|
|
5235
|
+
inbound: inbound.length > 0 ? inbound : undefined
|
|
5236
|
+
};
|
|
5237
|
+
}
|
|
5238
|
+
|
|
5072
5239
|
class VideoPreset {
|
|
5073
5240
|
constructor(widthOrOptions, height, maxBitrate, maxFramerate, priority) {
|
|
5074
5241
|
if (typeof widthOrOptions === 'object') {
|
|
@@ -5233,6 +5400,7 @@ class Track extends eventsExports.EventEmitter {
|
|
|
5233
5400
|
this._streamState = Track.StreamState.Active;
|
|
5234
5401
|
this.isInBackground = false;
|
|
5235
5402
|
this._currentBitrate = 0;
|
|
5403
|
+
this.finalStatsLogged = false;
|
|
5236
5404
|
this.log = livekitLogger;
|
|
5237
5405
|
this.appVisibilityChangedListener = () => {
|
|
5238
5406
|
if (this.backgroundTimeout) {
|
|
@@ -5377,9 +5545,28 @@ class Track extends eventsExports.EventEmitter {
|
|
|
5377
5545
|
if (this.monitorInterval) {
|
|
5378
5546
|
clearInterval(this.monitorInterval);
|
|
5379
5547
|
}
|
|
5380
|
-
if (this.timeSyncHandle) {
|
|
5548
|
+
if (this.timeSyncHandle !== undefined) {
|
|
5381
5549
|
cancelAnimationFrame(this.timeSyncHandle);
|
|
5550
|
+
this.timeSyncHandle = undefined;
|
|
5382
5551
|
}
|
|
5552
|
+
this.logFinalStats();
|
|
5553
|
+
}
|
|
5554
|
+
/**
|
|
5555
|
+
* Dumps the raw stats of the track as it ends, once: a track that stops
|
|
5556
|
+
* between two of the room's stats dumps is gone by the time the next one runs.
|
|
5557
|
+
*/
|
|
5558
|
+
logFinalStats() {
|
|
5559
|
+
if (this.finalStatsLogged) {
|
|
5560
|
+
return;
|
|
5561
|
+
}
|
|
5562
|
+
this.finalStatsLogged = true;
|
|
5563
|
+
this.getRTCStatsReport().then(report => {
|
|
5564
|
+
if (report) {
|
|
5565
|
+
this.log.info('final track stats', summarizeStatsReport(report));
|
|
5566
|
+
}
|
|
5567
|
+
}).catch(error => this.log.debug('could not collect final track stats', {
|
|
5568
|
+
error
|
|
5569
|
+
}));
|
|
5383
5570
|
}
|
|
5384
5571
|
/** @internal */
|
|
5385
5572
|
updateLoggerOptions(loggerOptions) {
|