livedesk 0.1.166 → 0.1.168

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.
@@ -31,6 +31,7 @@ let encoder = null;
31
31
  let encoderCandidateIndex = 0;
32
32
  let encoderCandidates = [];
33
33
  let encoderOutputSeen = false;
34
+ let encoderGeneration = 0;
34
35
  let encoderRestartTimer = null;
35
36
  let encoderStartupTimer = null;
36
37
  let inputWaitTimer = null;
@@ -119,6 +120,7 @@ function startEncoder() {
119
120
  return;
120
121
  }
121
122
  const candidate = encoderCandidates[encoderCandidateIndex++];
123
+ encoderGeneration += 1;
122
124
  const args = [
123
125
  '-hide_banner', '-loglevel', 'warning',
124
126
  '-f', 'rawvideo', '-pixel_format', 'rgb24',
@@ -226,6 +228,7 @@ function emitEncodedUnit(payload) {
226
228
  isKeyFrame,
227
229
  chunkType: isKeyFrame ? 'key' : 'delta',
228
230
  hardwareEncoder: encoder?.candidate?.name || '',
231
+ encoderGeneration,
229
232
  layoutVersion,
230
233
  composeMs: lastComposeMs,
231
234
  poolStarved,
@@ -16,11 +16,13 @@ export class Mode4AtlasSession {
16
16
  this.restartTimer = null;
17
17
  this.pendingFrames = new Map();
18
18
  this.frameSendsInFlight = new Set();
19
+ this.workerGeneration = 0;
19
20
  this.startWorker();
20
21
  }
21
22
 
22
23
  startWorker() {
23
24
  if (this.closed || this.worker) return;
25
+ const workerGeneration = ++this.workerGeneration;
24
26
  const worker = fork(workerPath, [], {
25
27
  env: { ...process.env },
26
28
  stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
@@ -30,7 +32,10 @@ export class Mode4AtlasSession {
30
32
  this.worker = worker;
31
33
  worker.on('message', message => {
32
34
  if (message?.type === 'frame' && message.metadata && message.payload) {
33
- this.onFrame({ metadata: message.metadata, payload: Buffer.from(message.payload) });
35
+ this.onFrame({
36
+ metadata: { ...message.metadata, workerGeneration },
37
+ payload: Buffer.from(message.payload)
38
+ });
34
39
  } else if (message?.type === 'layout') {
35
40
  this.onLayout(message);
36
41
  } else if (message?.type === 'status' || message?.type === 'log') {
@@ -8,7 +8,7 @@ const DEFAULT_HEARTBEAT_MS = 5000;
8
8
  const DEFAULT_AGENT_TASK_TIMEOUT_MS = 120000;
9
9
  const MAX_LINE_CHARS = 4 * 1024 * 1024;
10
10
  const MAX_THUMBNAIL_BASE64_CHARS = 3 * 1024 * 1024;
11
- const MAX_STREAM_BASE64_CHARS = 3 * 1024 * 1024;
11
+ const MAX_STREAM_BASE64_CHARS = Math.ceil(8 * 1024 * 1024 * 4 / 3);
12
12
  const MAX_THUMBNAIL_BINARY_BYTES = Math.floor(MAX_THUMBNAIL_BASE64_CHARS * 3 / 4);
13
13
  const MAX_STREAM_BINARY_BYTES = Math.floor(MAX_STREAM_BASE64_CHARS * 3 / 4);
14
14
  const MAX_AUDIO_BASE64_CHARS = 1024 * 1024;
@@ -21,7 +21,7 @@ const RECENT_FRAME_CACHE_TTL_MS = 4000;
21
21
  const RECENT_THUMBNAIL_FRAME_CACHE_LIMIT = 2;
22
22
  const RECENT_LIVE_FRAME_CACHE_LIMIT = 1;
23
23
  const RECENT_THUMBNAIL_FRAME_CACHE_MAX_BYTES = 2 * 1024 * 1024;
24
- const RECENT_LIVE_FRAME_CACHE_MAX_BYTES = 3 * 1024 * 1024;
24
+ const RECENT_LIVE_FRAME_CACHE_MAX_BYTES = 8 * 1024 * 1024;
25
25
  const LIVE_STREAM_PENDING_REUSE_MS = 5000;
26
26
  const LIVE_STREAM_MIN_FRESH_MS = 3000;
27
27
  const LIVE_STREAM_MAX_FRESH_MS = 12000;
@@ -77,6 +77,17 @@ const REMOTE_FRAME_MODE_PROFILES = Object.freeze({
77
77
  profile: 'mode3-h264-hardware-v1',
78
78
  modeVersion: 3,
79
79
  implemented: true
80
+ }),
81
+ 'mode5-lzo-delta': Object.freeze({
82
+ mode: 'mode5-lzo-delta',
83
+ label: 'Mode 5 - RGB565 Tile Delta LZO',
84
+ transport: 'ws-binary',
85
+ encoding: 'image-delta',
86
+ codec: 'rgb565-delta',
87
+ compression: 'lzo1x',
88
+ profile: 'mode5-lzo-rgb565-delta-v1',
89
+ modeVersion: 5,
90
+ implemented: true
80
91
  })
81
92
  });
82
93
  const REMOTE_FRAME_MODE_ALIASES = new Map([
@@ -117,6 +128,14 @@ const REMOTE_FRAME_MODE_ALIASES = new Map([
117
128
  ['h264-hw', 'mode3-h264-hw'],
118
129
  ['hardware', 'mode3-h264-hw'],
119
130
  ['hardware-h264', 'mode3-h264-hw'],
131
+ ['5', 'mode5-lzo-delta'],
132
+ ['mode5', 'mode5-lzo-delta'],
133
+ ['mode-5', 'mode5-lzo-delta'],
134
+ ['mode5-lzo', 'mode5-lzo-delta'],
135
+ ['mode5-lzo-delta', 'mode5-lzo-delta'],
136
+ ['lzo-delta', 'mode5-lzo-delta'],
137
+ ['tile-delta', 'mode5-lzo-delta'],
138
+ ['control-lzo', 'mode5-lzo-delta'],
120
139
  ['thumb', 'thumbnail'],
121
140
  ['thumbnail', 'thumbnail'],
122
141
  ['video', 'mode3-h264-hw'],
@@ -3111,6 +3130,9 @@ export function createRemoteHub(options = {}) {
3111
3130
  captureStageMs: readFrameStageMs(message, 'captureStageMs'),
3112
3131
  convertMs: readFrameStageMs(message, 'convertMs'),
3113
3132
  compressMs: readFrameStageMs(message, 'compressMs'),
3133
+ deltaTileSize: Number.isFinite(Number(message.deltaTileSize)) ? Number(message.deltaTileSize) : 0,
3134
+ deltaTileCount: Number.isFinite(Number(message.deltaTileCount)) ? Number(message.deltaTileCount) : 0,
3135
+ deltaTotalTiles: Number.isFinite(Number(message.deltaTotalTiles)) ? Number(message.deltaTotalTiles) : 0,
3114
3136
  sameContentStreak,
3115
3137
  payload,
3116
3138
  accessToken: createFrameAccessToken()
@@ -3306,6 +3328,9 @@ export function createRemoteHub(options = {}) {
3306
3328
  captureStageMs: readFrameStageMs(message, 'captureStageMs'),
3307
3329
  convertMs: readFrameStageMs(message, 'convertMs'),
3308
3330
  compressMs: readFrameStageMs(message, 'compressMs'),
3331
+ deltaTileSize: Number.isFinite(Number(message.deltaTileSize)) ? Number(message.deltaTileSize) : 0,
3332
+ deltaTileCount: Number.isFinite(Number(message.deltaTileCount)) ? Number(message.deltaTileCount) : 0,
3333
+ deltaTotalTiles: Number.isFinite(Number(message.deltaTotalTiles)) ? Number(message.deltaTotalTiles) : 0,
3309
3334
  sameContentStreak,
3310
3335
  payload,
3311
3336
  accessToken: createFrameAccessToken()
package/hub/src/server.js CHANGED
@@ -793,6 +793,9 @@ function buildRemoteFrameBinaryPacket(frameEvent, diagnostics = {}) {
793
793
  captureStageMs: Number(frame.captureStageMs || 0) || 0,
794
794
  convertMs: Number(frame.convertMs || 0) || 0,
795
795
  compressMs: Number(frame.compressMs || 0) || 0,
796
+ deltaTileSize: Number(frame.deltaTileSize || 0) || 0,
797
+ deltaTileCount: Number(frame.deltaTileCount || 0) || 0,
798
+ deltaTotalTiles: Number(frame.deltaTotalTiles || 0) || 0,
796
799
  sameContentStreak: Number(frame.sameContentStreak || 0) || 0,
797
800
  layoutVersion: Number(frame.layoutVersion || 0) || 0,
798
801
  atlasComposeMs: Number(frame.atlasComposeMs || 0) || 0,
@@ -911,6 +914,9 @@ function sendMode4AtlasFrame(ws, output) {
911
914
  const metadata = output.metadata || {};
912
915
  const frameSeq = Number(metadata.frameSeq || 0) || 0;
913
916
  const isKeyFrame = metadata.isKeyFrame === true;
917
+ const workerGeneration = Math.max(1, Number(metadata.workerGeneration || 1) || 1);
918
+ const encoderGeneration = Math.max(1, Number(metadata.encoderGeneration || 1) || 1);
919
+ const streamId = `${ws.liveDeskAtlasStreamId}-w${workerGeneration}-e${encoderGeneration}`;
914
920
  const frameEvent = {
915
921
  kind: 'live',
916
922
  deviceId: '__livedesk_mode4_atlas__',
@@ -921,8 +927,8 @@ function sendMode4AtlasFrame(ws, output) {
921
927
  deviceId: '__livedesk_mode4_atlas__',
922
928
  frameSeq,
923
929
  streamFrameSeq: Number(metadata.streamFrameSeq || frameSeq) || frameSeq,
924
- streamId: ws.liveDeskAtlasStreamId,
925
- commandId: ws.liveDeskAtlasStreamId,
930
+ streamId,
931
+ commandId: streamId,
926
932
  width: Number(metadata.width || 1920),
927
933
  height: Number(metadata.height || 1080),
928
934
  sourceWidth: Number(metadata.width || 1920),
@@ -944,6 +950,8 @@ function sendMode4AtlasFrame(ws, output) {
944
950
  receivedAt: new Date().toISOString(),
945
951
  hardwareEncoder: String(metadata.hardwareEncoder || ''),
946
952
  platformProfile: 'mode4-hub-atlas-worker',
953
+ workerGeneration,
954
+ encoderGeneration,
947
955
  layoutVersion: Number(metadata.layoutVersion || 0),
948
956
  atlasComposeMs: Number(metadata.composeMs || 0),
949
957
  atlasPoolStarved: Number(metadata.poolStarved || 0),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livedesk",
3
- "version": "0.1.166",
3
+ "version": "0.1.168",
4
4
  "description": "LiveDesk Hub and client launcher",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,7 +15,7 @@
15
15
  "scripts": {
16
16
  "check": "node --check bin/livedesk.js && node --check scripts/sync-web-dist.js",
17
17
  "build": "node scripts/sync-web-dist.js",
18
- "prepack": "npm run build",
18
+ "prepack": "node scripts/sync-web-dist.js",
19
19
  "pack:dry": "npm pack --dry-run"
20
20
  },
21
21
  "keywords": [
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
34
- "@livedesk/client": "0.1.107",
34
+ "@livedesk/client": "0.1.108",
35
35
  "cors": "^2.8.5",
36
36
  "express": "^4.21.2",
37
37
  "ffmpeg-static": "^5.3.0",