src.nth.io/

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Hoersten <[email protected]>2026-06-20 12:11:54 -0500
committerLuke Hoersten <[email protected]>2026-06-20 12:11:54 -0500
commit439dadb24c4e07eb11f1aa9804cf7a973518e539 (patch)
tree000492fb7928d1ae0c7e42769080f8c5043fd9f6
parenta7fbd013f2bfabcb7a18a7878a959c24ed838110 (diff)
scrypted: log node_buf in stream window — confirms script-side buffering
Adds two values to the unified stream log line: node_buf=NKB≈Mms node_buf bytes is sock.writableLength — bytes that socket.write() accepted from us but the kernel send buffer hasn't pulled yet, so they sit in Node's internal queue. These have NOT been sent over the wire; the firmware can't have them. Dividing by the current send rate (bytes/sec computed from the same window's bytesSent) gives the buffer depth in milliseconds: how many seconds of already-extracted-from-ffmpeg frames are stalled at the script. When g2g shows 7s steady state and node_buf shows e.g. 5000-6000KB ≈ 6500ms, the conclusion is obvious — the buffering isn't in the firmware or on the wire, it's in Scrypted's Node process. No behavior change; pure diagnostic.
-rw-r--r--scrypted/scrypted-viewport.ts17
1 files changed, 15 insertions, 2 deletions
diff --git a/scrypted/scrypted-viewport.ts b/scrypted/scrypted-viewport.ts
index 747d3c0..7cf5faa 100644
--- a/scrypted/scrypted-viewport.ts
+++ b/scrypted/scrypted-viewport.ts
@@ -6,7 +6,7 @@
// short git hash of the commit that added this constant — if the
// hash in the log doesn't match the HEAD this file came from, the
// Scrypted Script editor is still on stale code.
-const SCRIPT_VERSION = "28f39bf";
+const SCRIPT_VERSION = "pending";
//
// Architecture
// ------------
@@ -1022,11 +1022,24 @@ class ScryptedViewportProvider extends ScryptedDeviceBase
} catch { /* keep the local stats; firmware-side just shows ? */ }
const skipped = paintedNum >= 0 ? Math.max(0, sentRate - paintedNum).toFixed(1) : "?";
+ // node_buf = bytes Scrypted has handed to socket.write but
+ // the kernel send buffer hasn't accepted yet — they sit in
+ // Node's internal queue, NOT on the wire. Divide by the
+ // current send rate to estimate how many seconds of
+ // already-emitted frames are waiting at the source. This
+ // is the load-bearing piece of the g2g "buffer depth"
+ // story: when this is large, the firmware can't possibly
+ // be showing the freshest bytes because we haven't even
+ // sent them yet.
+ const nodeBufBytes = sock?.writableLength ?? 0;
+ const sentBps = mbPerSec * 1024 * 1024;
+ const nodeBufMs = sentBps > 0 ? (nodeBufBytes / sentBps * 1000).toFixed(0) : "?";
this.console.log(
`stream "${v.name}": sent=${sentRate.toFixed(1)}fps painted=${painted}fps ` +
`(fw-skipped=${skipped}fps, drops=${droppedFrames}) ` +
`${mbPerSec.toFixed(2)}MB/s sent / ${paintedMb}MB/s painted | ` +
- `socket.write p50=${p50}ms p95=${p95}ms max=${max}ms backpressured=${socketBackpressured} | ` +
+ `socket.write p50=${p50}ms p95=${p95}ms max=${max}ms backpressured=${socketBackpressured} ` +
+ `node_buf=${(nodeBufBytes / 1024).toFixed(0)}KB≈${nodeBufMs}ms | ` +
`recv=${recvStr}us dec=${decStr}us paint=${paintStr}us idle=${idleStr}us | g2g=${g2g}`);
droppedFrames = 0;