livedesk 0.1.141 → 0.1.143
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/hub/src/remote-hub.js +29 -42
- package/hub/src/server.js +18 -6
- package/package.json +2 -2
- package/web/dist/assets/index-DD0Reo74.js +10 -0
- package/web/dist/index.html +1 -1
- package/web/dist/assets/index-DjcV4qaG.js +0 -10
package/hub/src/remote-hub.js
CHANGED
|
@@ -124,7 +124,7 @@ const DEFAULT_PUBLIC_IP_TIMEOUT_MS = 1800;
|
|
|
124
124
|
const DUPLICATE_DEVICE_ACTIVE_REJECT_MS = 15000;
|
|
125
125
|
const DUPLICATE_DEVICE_LOG_THROTTLE_MS = 60000;
|
|
126
126
|
const DUPLICATE_DEVICE_RETRY_AFTER_MS = 30000;
|
|
127
|
-
const AGENT_BINARY_INGRESS_QUEUE_PACKETS =
|
|
127
|
+
const AGENT_BINARY_INGRESS_QUEUE_PACKETS = 64;
|
|
128
128
|
const AGENT_BINARY_INGRESS_DRAIN_BUDGET_PACKETS = 64;
|
|
129
129
|
const SYNTHETIC_FRAME_DATA_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAADElEQVR42mP8z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC';
|
|
130
130
|
const SYNTHETIC_FRAME_PAYLOAD = Buffer.from(SYNTHETIC_FRAME_DATA_URL.split(',')[1], 'base64');
|
|
@@ -1348,9 +1348,7 @@ export function createRemoteHub(options = {}) {
|
|
|
1348
1348
|
const audioSockets = new Map();
|
|
1349
1349
|
const fileSockets = new Map();
|
|
1350
1350
|
const allSockets = new Set();
|
|
1351
|
-
const agentBinaryIngressLanes = [];
|
|
1352
1351
|
const duplicateDeviceLogAt = new Map();
|
|
1353
|
-
let agentBinaryIngressDraining = false;
|
|
1354
1352
|
let server = null;
|
|
1355
1353
|
let started = false;
|
|
1356
1354
|
let boundPort = requestedPort;
|
|
@@ -3239,6 +3237,7 @@ export function createRemoteHub(options = {}) {
|
|
|
3239
3237
|
device.latestLiveFrame = {
|
|
3240
3238
|
streamId,
|
|
3241
3239
|
frameSeq,
|
|
3240
|
+
streamFrameSeq: Number.isFinite(Number(message.streamFrameSeq)) ? Number(message.streamFrameSeq) : frameSeq,
|
|
3242
3241
|
commandId,
|
|
3243
3242
|
width: Number.isFinite(Number(message.width)) ? Number(message.width) : 0,
|
|
3244
3243
|
height: Number.isFinite(Number(message.height)) ? Number(message.height) : 0,
|
|
@@ -3266,6 +3265,7 @@ export function createRemoteHub(options = {}) {
|
|
|
3266
3265
|
agentSendDurationFrameSeq: Number.isFinite(Number(message.agentSendDurationFrameSeq)) ? Number(message.agentSendDurationFrameSeq) : 0,
|
|
3267
3266
|
agentPaceMs: Number.isFinite(Number(message.agentPaceMs)) ? Number(message.agentPaceMs) : 0,
|
|
3268
3267
|
droppedByAgent: Number.isFinite(Number(message.droppedByAgent)) ? Number(message.droppedByAgent) : 0,
|
|
3268
|
+
hubIngressDropped: Number.isFinite(Number(message.hubIngressDropped)) ? Number(message.hubIngressDropped) : 0,
|
|
3269
3269
|
hardwareEncoder: safeString(message.hardwareEncoder, 80),
|
|
3270
3270
|
platformProfile: safeString(message.platformProfile, 80),
|
|
3271
3271
|
monitorIndex: Number.isFinite(Number(message.monitorIndex)) ? normalizeMonitorIndex(message.monitorIndex) : Number(device.activeLiveStream.monitorIndex || 0),
|
|
@@ -3429,7 +3429,10 @@ export function createRemoteHub(options = {}) {
|
|
|
3429
3429
|
}
|
|
3430
3430
|
|
|
3431
3431
|
if (frameKind === 'stream' || frameKind === 'live' || header.type === 'stream.binary') {
|
|
3432
|
-
applyLiveFrame(device,
|
|
3432
|
+
applyLiveFrame(device, {
|
|
3433
|
+
...header,
|
|
3434
|
+
hubIngressDropped: Number(state.binaryQueueDrops || 0)
|
|
3435
|
+
}, framePayload, 'binary');
|
|
3433
3436
|
return;
|
|
3434
3437
|
}
|
|
3435
3438
|
|
|
@@ -3467,52 +3470,36 @@ export function createRemoteHub(options = {}) {
|
|
|
3467
3470
|
}
|
|
3468
3471
|
|
|
3469
3472
|
state.binaryQueueSocket = socket;
|
|
3470
|
-
if (state.binaryQueueScheduled
|
|
3471
|
-
|
|
3472
|
-
agentBinaryIngressLanes.push(state);
|
|
3473
|
+
if (state.binaryQueueScheduled === true) {
|
|
3474
|
+
return;
|
|
3473
3475
|
}
|
|
3474
|
-
|
|
3476
|
+
state.binaryQueueScheduled = true;
|
|
3477
|
+
setImmediate(() => drainAgentBinaryIngressLane(state));
|
|
3475
3478
|
}
|
|
3476
3479
|
|
|
3477
|
-
function
|
|
3478
|
-
|
|
3480
|
+
function drainAgentBinaryIngressLane(state) {
|
|
3481
|
+
state.binaryQueueScheduled = false;
|
|
3482
|
+
const socket = state.binaryQueueSocket;
|
|
3483
|
+
if (state.closed || !socket || socket.destroyed) {
|
|
3484
|
+
if (Array.isArray(state.binaryQueue)) {
|
|
3485
|
+
state.binaryQueue.length = 0;
|
|
3486
|
+
}
|
|
3479
3487
|
return;
|
|
3480
3488
|
}
|
|
3481
|
-
agentBinaryIngressDraining = true;
|
|
3482
|
-
setImmediate(() => {
|
|
3483
|
-
agentBinaryIngressDraining = false;
|
|
3484
|
-
let processed = 0;
|
|
3485
|
-
while (agentBinaryIngressLanes.length > 0 && processed < AGENT_BINARY_INGRESS_DRAIN_BUDGET_PACKETS) {
|
|
3486
|
-
const state = agentBinaryIngressLanes.shift();
|
|
3487
|
-
if (!state) {
|
|
3488
|
-
continue;
|
|
3489
|
-
}
|
|
3490
|
-
|
|
3491
|
-
state.binaryQueueScheduled = false;
|
|
3492
|
-
const socket = state.binaryQueueSocket;
|
|
3493
|
-
if (state.closed || !socket || socket.destroyed) {
|
|
3494
|
-
if (Array.isArray(state.binaryQueue)) {
|
|
3495
|
-
state.binaryQueue.length = 0;
|
|
3496
|
-
}
|
|
3497
|
-
continue;
|
|
3498
|
-
}
|
|
3499
3489
|
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
if (state.binaryQueue.length > 0 && !state.closed && !socket.destroyed) {
|
|
3507
|
-
state.binaryQueueScheduled = true;
|
|
3508
|
-
agentBinaryIngressLanes.push(state);
|
|
3509
|
-
}
|
|
3490
|
+
let processed = 0;
|
|
3491
|
+
while (state.binaryQueue.length > 0 && processed < AGENT_BINARY_INGRESS_DRAIN_BUDGET_PACKETS) {
|
|
3492
|
+
const item = state.binaryQueue.shift();
|
|
3493
|
+
if (!item) {
|
|
3494
|
+
continue;
|
|
3510
3495
|
}
|
|
3496
|
+
handleAgentBinaryFrame(socket, state, item.header, item.payload);
|
|
3497
|
+
processed += 1;
|
|
3498
|
+
}
|
|
3511
3499
|
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
});
|
|
3500
|
+
if (state.binaryQueue.length > 0 && !state.closed && !socket.destroyed) {
|
|
3501
|
+
scheduleAgentBinaryIngress(socket, state);
|
|
3502
|
+
}
|
|
3516
3503
|
}
|
|
3517
3504
|
|
|
3518
3505
|
function enqueueAgentBinaryFrame(socket, state, header, payload) {
|
package/hub/src/server.js
CHANGED
|
@@ -21,7 +21,7 @@ const packageInfo = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.js
|
|
|
21
21
|
const httpHost = process.env.LIVEDESK_HUB_HTTP_HOST || '127.0.0.1';
|
|
22
22
|
const httpPort = Number(process.env.LIVEDESK_HUB_HTTP_PORT || process.env.PORT || 5179);
|
|
23
23
|
const frameBackpressureBytes = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_BACKPRESSURE_BYTES', 16 * 1024 * 1024);
|
|
24
|
-
const frameClientQueuePackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_QUEUE_PACKETS',
|
|
24
|
+
const frameClientQueuePackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_QUEUE_PACKETS', 64);
|
|
25
25
|
const frameClientDrainBudgetPackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_DRAIN_BUDGET_PACKETS', 8);
|
|
26
26
|
const frameClients = new Set();
|
|
27
27
|
const frameClientsByDeviceId = new Map();
|
|
@@ -572,6 +572,10 @@ function enqueueFramePacketForClient(ws, packet, meta) {
|
|
|
572
572
|
}
|
|
573
573
|
if (ws.bufferedAmount > frameBackpressureBytes) {
|
|
574
574
|
ws.liveDeskFrameBackpressured = true;
|
|
575
|
+
lane.dropped += 1;
|
|
576
|
+
if (meta.isH264 && meta.deviceId) {
|
|
577
|
+
lane.awaitingKeyFrames.add(meta.deviceId);
|
|
578
|
+
}
|
|
575
579
|
ws.liveDeskFrameBackpressureDrops = Number(ws.liveDeskFrameBackpressureDrops || 0) + 1;
|
|
576
580
|
return false;
|
|
577
581
|
}
|
|
@@ -709,7 +713,7 @@ function updateAudioSubscription(ws, payload = {}) {
|
|
|
709
713
|
});
|
|
710
714
|
}
|
|
711
715
|
|
|
712
|
-
function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
716
|
+
function buildRemoteFrameBinaryPacket(frameEvent, diagnostics = {}) {
|
|
713
717
|
const payload = frameEvent?.payload;
|
|
714
718
|
if (!Buffer.isBuffer(payload) || payload.length === 0) {
|
|
715
719
|
return null;
|
|
@@ -722,6 +726,7 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
722
726
|
kind: frameEvent.kind || 'live',
|
|
723
727
|
deviceId: frameEvent.deviceId || frame.deviceId || '',
|
|
724
728
|
frameSeq: Number(frame.frameSeq || 0) || 0,
|
|
729
|
+
streamFrameSeq: Number(frame.streamFrameSeq || 0) || 0,
|
|
725
730
|
streamId: frame.streamId || '',
|
|
726
731
|
commandId: frame.commandId || '',
|
|
727
732
|
width: Number(frame.width || 0) || 0,
|
|
@@ -749,6 +754,8 @@ function buildRemoteFrameBinaryPacket(frameEvent) {
|
|
|
749
754
|
agentSendDurationFrameSeq: Number(frame.agentSendDurationFrameSeq || 0) || 0,
|
|
750
755
|
agentPaceMs: Number(frame.agentPaceMs || 0) || 0,
|
|
751
756
|
droppedByAgent: Number(frame.droppedByAgent || 0) || 0,
|
|
757
|
+
hubIngressDropped: Number(frame.hubIngressDropped || 0) || 0,
|
|
758
|
+
hubClientDropped: Number(diagnostics.hubClientDropped || 0) || 0,
|
|
752
759
|
hardwareEncoder: frame.hardwareEncoder || '',
|
|
753
760
|
platformProfile: frame.platformProfile || '',
|
|
754
761
|
fps: Number(frame.fps || 0) || 0,
|
|
@@ -810,19 +817,24 @@ function broadcastRemoteBinaryFrame(frameEvent) {
|
|
|
810
817
|
const isH264 = String(frame.codec || frame.mimeType || frame.format || '').toLowerCase().includes('h264')
|
|
811
818
|
|| String(frame.frameMode || frame.mode || '').toLowerCase() === 'mode3-h264-hw';
|
|
812
819
|
const isKeyFrame = frame.isKeyFrame === true || String(frame.chunkType || '').toLowerCase() === 'key';
|
|
813
|
-
const packet = buildRemoteFrameBinaryPacket(frameEvent);
|
|
814
|
-
if (!packet) {
|
|
815
|
-
return;
|
|
816
|
-
}
|
|
817
820
|
const frameSeq = Number(frame.frameSeq || 0) || 0;
|
|
818
821
|
for (const client of targetClients) {
|
|
819
822
|
if (client.readyState !== client.OPEN) {
|
|
820
823
|
continue;
|
|
821
824
|
}
|
|
825
|
+
const lane = ensureFrameClientSendLane(client);
|
|
822
826
|
if (client.liveDeskFrameBackpressured && isH264 && !isKeyFrame) {
|
|
827
|
+
lane.dropped += 1;
|
|
828
|
+
lane.awaitingKeyFrames.add(deviceId);
|
|
823
829
|
client.liveDeskFrameBackpressureDrops = Number(client.liveDeskFrameBackpressureDrops || 0) + 1;
|
|
824
830
|
continue;
|
|
825
831
|
}
|
|
832
|
+
const packet = buildRemoteFrameBinaryPacket(frameEvent, {
|
|
833
|
+
hubClientDropped: lane.dropped
|
|
834
|
+
});
|
|
835
|
+
if (!packet) {
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
826
838
|
enqueueFramePacketForClient(client, packet, { deviceId, frameSeq, isH264, isKeyFrame });
|
|
827
839
|
}
|
|
828
840
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livedesk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.143",
|
|
4
4
|
"description": "LiveDesk Hub and client launcher",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"node": ">=20"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@livedesk/client": "0.1.
|
|
33
|
+
"@livedesk/client": "0.1.97",
|
|
34
34
|
"cors": "^2.8.5",
|
|
35
35
|
"express": "^4.21.2",
|
|
36
36
|
"path-to-regexp": "0.1.13",
|