livedesk 0.1.82 → 0.1.84
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 +59 -9
- package/hub/src/server.js +18 -3
- package/package.json +1 -1
package/hub/src/remote-hub.js
CHANGED
|
@@ -22,6 +22,9 @@ const RECENT_THUMBNAIL_FRAME_CACHE_LIMIT = 4;
|
|
|
22
22
|
const RECENT_LIVE_FRAME_CACHE_LIMIT = 80;
|
|
23
23
|
const RECENT_THUMBNAIL_FRAME_CACHE_MAX_BYTES = 3 * 1024 * 1024;
|
|
24
24
|
const RECENT_LIVE_FRAME_CACHE_MAX_BYTES = 24 * 1024 * 1024;
|
|
25
|
+
const LIVE_STREAM_PENDING_REUSE_MS = 5000;
|
|
26
|
+
const LIVE_STREAM_MIN_FRESH_MS = 3000;
|
|
27
|
+
const LIVE_STREAM_MAX_FRESH_MS = 12000;
|
|
25
28
|
const REMOTE_PROTOCOL_VERSION = 2;
|
|
26
29
|
const REMOTE_AGENT_PROTOCOL = 'mindexec.remote.agent';
|
|
27
30
|
const REMOTE_FRAME_PROTOCOL = 'mindexec.remote.frame.v2';
|
|
@@ -3872,7 +3875,37 @@ export function createRemoteHub(options = {}) {
|
|
|
3872
3875
|
return false;
|
|
3873
3876
|
}
|
|
3874
3877
|
const startedAt = Date.parse(activeLiveStream.startedAt || '');
|
|
3875
|
-
return Number.isFinite(startedAt) && Date.now() - startedAt <
|
|
3878
|
+
return Number.isFinite(startedAt) && Date.now() - startedAt < LIVE_STREAM_PENDING_REUSE_MS;
|
|
3879
|
+
}
|
|
3880
|
+
|
|
3881
|
+
function getLiveStreamFreshWindowMs(activeLiveStream) {
|
|
3882
|
+
const fps = Number(activeLiveStream?.fps || 0);
|
|
3883
|
+
const frameMs = Number.isFinite(fps) && fps > 0 ? 1000 / fps : 500;
|
|
3884
|
+
return Math.max(
|
|
3885
|
+
LIVE_STREAM_MIN_FRESH_MS,
|
|
3886
|
+
Math.min(LIVE_STREAM_MAX_FRESH_MS, Math.round(frameMs * 20))
|
|
3887
|
+
);
|
|
3888
|
+
}
|
|
3889
|
+
|
|
3890
|
+
function getLiveStreamIdleMs(activeLiveStream) {
|
|
3891
|
+
const lastFrameAt = Date.parse(activeLiveStream?.lastFrameAt || activeLiveStream?.openedAt || activeLiveStream?.startedAt || '');
|
|
3892
|
+
if (!Number.isFinite(lastFrameAt)) {
|
|
3893
|
+
return Infinity;
|
|
3894
|
+
}
|
|
3895
|
+
return Math.max(0, Date.now() - lastFrameAt);
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
function liveStreamIsReusable(activeLiveStream) {
|
|
3899
|
+
if (!activeLiveStream?.active) {
|
|
3900
|
+
return false;
|
|
3901
|
+
}
|
|
3902
|
+
if (liveStreamStartStillPending(activeLiveStream)) {
|
|
3903
|
+
return true;
|
|
3904
|
+
}
|
|
3905
|
+
if (activeLiveStream.open !== true) {
|
|
3906
|
+
return false;
|
|
3907
|
+
}
|
|
3908
|
+
return getLiveStreamIdleMs(activeLiveStream) <= getLiveStreamFreshWindowMs(activeLiveStream);
|
|
3876
3909
|
}
|
|
3877
3910
|
|
|
3878
3911
|
function liveStreamMatchesOptions(activeLiveStream, normalized) {
|
|
@@ -3976,14 +4009,16 @@ export function createRemoteHub(options = {}) {
|
|
|
3976
4009
|
const commandId = safeString(options.commandId, 128) || crypto.randomUUID();
|
|
3977
4010
|
if (device.activeLiveStream?.streamId === streamId
|
|
3978
4011
|
&& liveStreamMatchesOptions(device.activeLiveStream, normalized)
|
|
3979
|
-
&& (device.activeLiveStream
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
4012
|
+
&& liveStreamIsReusable(device.activeLiveStream)) {
|
|
4013
|
+
if (options.silentReuse !== true) {
|
|
4014
|
+
emitRemoteEvent('RemoteLiveStreamStartReused', device, {
|
|
4015
|
+
streamId,
|
|
4016
|
+
fps,
|
|
4017
|
+
mode: transfer.mode,
|
|
4018
|
+
frameMode: transfer.frameMode,
|
|
4019
|
+
monitorIndex
|
|
4020
|
+
});
|
|
4021
|
+
}
|
|
3987
4022
|
return {
|
|
3988
4023
|
ok: true,
|
|
3989
4024
|
commandId: device.activeLiveStream.commandId,
|
|
@@ -3995,6 +4030,21 @@ export function createRemoteHub(options = {}) {
|
|
|
3995
4030
|
reused: true
|
|
3996
4031
|
};
|
|
3997
4032
|
}
|
|
4033
|
+
if (device.activeLiveStream?.streamId === streamId
|
|
4034
|
+
&& liveStreamMatchesOptions(device.activeLiveStream, normalized)
|
|
4035
|
+
&& device.activeLiveStream.open === true
|
|
4036
|
+
&& !liveStreamIsReusable(device.activeLiveStream)) {
|
|
4037
|
+
emitRemoteEvent('RemoteLiveStreamStaleRestart', device, {
|
|
4038
|
+
streamId,
|
|
4039
|
+
fps,
|
|
4040
|
+
mode: transfer.mode,
|
|
4041
|
+
frameMode: transfer.frameMode,
|
|
4042
|
+
monitorIndex,
|
|
4043
|
+
idleMs: getLiveStreamIdleMs(device.activeLiveStream),
|
|
4044
|
+
staleAfterMs: getLiveStreamFreshWindowMs(device.activeLiveStream),
|
|
4045
|
+
lastFrameAt: device.activeLiveStream.lastFrameAt || ''
|
|
4046
|
+
});
|
|
4047
|
+
}
|
|
3998
4048
|
if (device.activeLiveStream?.active && device.activeLiveStream.streamId && device.activeLiveStream.streamId !== streamId) {
|
|
3999
4049
|
sendCommand(deviceId, {
|
|
4000
4050
|
command: 'stream.stop',
|
package/hub/src/server.js
CHANGED
|
@@ -27,6 +27,7 @@ const audioClients = new Set();
|
|
|
27
27
|
let frameClientSeq = 0;
|
|
28
28
|
let inputClientSeq = 0;
|
|
29
29
|
let audioClientSeq = 0;
|
|
30
|
+
const FRAME_LIVE_WATCHDOG_MS = 2500;
|
|
30
31
|
|
|
31
32
|
function handleRemoteHubEvent(type, event) {
|
|
32
33
|
if (type !== 'RemoteDeviceConnected') {
|
|
@@ -238,7 +239,8 @@ function startFrameSubscriptionLive(ws, reason = 'subscribe', onlyDeviceId = '')
|
|
|
238
239
|
: ws.liveDeskLiveOptions.monitorIndex;
|
|
239
240
|
const result = remoteHub.startLiveStream(deviceId, {
|
|
240
241
|
...ws.liveDeskLiveOptions,
|
|
241
|
-
monitorIndex
|
|
242
|
+
monitorIndex,
|
|
243
|
+
silentReuse: reason === 'watchdog'
|
|
242
244
|
});
|
|
243
245
|
if (result?.ok) {
|
|
244
246
|
started.push({ deviceId, streamId: result.streamId, fps: result.fps, reused: result.reused === true });
|
|
@@ -246,6 +248,9 @@ function startFrameSubscriptionLive(ws, reason = 'subscribe', onlyDeviceId = '')
|
|
|
246
248
|
skipped.push({ deviceId, reason: result?.error || 'start-failed' });
|
|
247
249
|
}
|
|
248
250
|
}
|
|
251
|
+
if (reason === 'watchdog' && !started.some(item => item.reused !== true)) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
249
254
|
sendJson(ws, {
|
|
250
255
|
type: 'RemoteFrameLiveAutoStart',
|
|
251
256
|
timestamp: new Date().toISOString(),
|
|
@@ -702,6 +707,16 @@ httpServer.on('upgrade', (req, socket, head) => {
|
|
|
702
707
|
frameWss.on('connection', (ws, req) => {
|
|
703
708
|
frameClients.add(ws);
|
|
704
709
|
ws.liveDeskFrameClientId = `rfws-${++frameClientSeq}`;
|
|
710
|
+
const liveWatchdog = setInterval(() => {
|
|
711
|
+
if (ws.readyState === 1) {
|
|
712
|
+
startFrameSubscriptionLive(ws, 'watchdog');
|
|
713
|
+
}
|
|
714
|
+
}, FRAME_LIVE_WATCHDOG_MS);
|
|
715
|
+
liveWatchdog.unref?.();
|
|
716
|
+
const cleanup = () => {
|
|
717
|
+
clearInterval(liveWatchdog);
|
|
718
|
+
frameClients.delete(ws);
|
|
719
|
+
};
|
|
705
720
|
try {
|
|
706
721
|
const parsed = new URL(req.url || '/', `http://${req.headers.host || '127.0.0.1'}`);
|
|
707
722
|
updateFrameSubscription(ws, { deviceIds: parsed.searchParams.get('devices') || '' });
|
|
@@ -718,8 +733,8 @@ frameWss.on('connection', (ws, req) => {
|
|
|
718
733
|
sendJson(ws, { type: 'RemoteFrameSubscriptionError', error: 'invalid-message' });
|
|
719
734
|
}
|
|
720
735
|
});
|
|
721
|
-
ws.on('close',
|
|
722
|
-
ws.on('error',
|
|
736
|
+
ws.on('close', cleanup);
|
|
737
|
+
ws.on('error', cleanup);
|
|
723
738
|
sendJson(ws, {
|
|
724
739
|
type: 'RemoteFrameSocketReady',
|
|
725
740
|
protocol: 'livedesk.remote.frames.binary.v1',
|