diff options
| author | Luke Hoersten <[email protected]> | 2026-06-15 09:08:06 -0500 |
|---|---|---|
| committer | Luke Hoersten <[email protected]> | 2026-06-15 09:08:06 -0500 |
| commit | 2d79d1bcbfb971a70bc45541c3d2eb6dafe1e2ba (patch) | |
| tree | 3cbfee0b5b924f9183c06b54d06b8dc4bb7652cd | |
| parent | 7a5216e6a13c015ae47d2c5d486e2d85f23f7e13 (diff) | |
scrypted: judge stream health by delivered fps not raw drop count
Previous threshold was "log if drops > 25% of target rate". At 500ms
interval (2 fps target) that fired at 0.5+ dropped fps — but a
displayed rate of 1.5 fps is fine, the panel still updates every
~666ms. The warning told the user to "raise frame_interval_ms" when
nothing was actually wrong.
Track sentFrames separately and only warn when delivered rate falls
under 75% of target. Drop rate is now informational context in the
log line, not the trigger.
| -rw-r--r-- | scrypted/scrypted-viewport.ts | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/scrypted/scrypted-viewport.ts b/scrypted/scrypted-viewport.ts index f9dc38e..2e46ab3 100644 --- a/scrypted/scrypted-viewport.ts +++ b/scrypted/scrypted-viewport.ts @@ -685,6 +685,7 @@ class ScryptedViewportProvider extends ScryptedDeviceBase // drop the spare frames silently — natural rate-limiter. let inFlight = false; let droppedFrames = 0; + let sentFrames = 0; let lastLogUs = Date.now(); let workBuf: Buffer = Buffer.alloc(0); @@ -738,6 +739,7 @@ class ScryptedViewportProvider extends ScryptedDeviceBase if (inFlight) { droppedFrames++; continue; } inFlight = true; + sentFrames++; this.pushStreamFrame(v, frame, abort) .catch(e => { if (abort.signal.aborted) return; @@ -783,22 +785,24 @@ class ScryptedViewportProvider extends ScryptedDeviceBase try { currentProc?.kill("SIGTERM"); } catch {} }); - // Periodic skip-rate log so the operator sees the effective fps - // and can decide whether to bump frame_interval_ms up or down. - // Only log if drops exceed 25% of the configured rate — below - // that it's just ffmpeg's fps filter emitting timestamp-clumped - // pairs that our single-flight guard correctly drops without - // any actual playback impact. + // Periodic skip-rate log. The metric that matters is *delivered* + // fps vs. requested rate, not raw drop count — at low intervals + // ffmpeg's fps filter emits timestamp-clumped pairs and our + // single-flight guard correctly skips the second, but the + // first still painted on time. Only warn if delivered fps falls + // below 75% of target. const skipLogger = setInterval(() => { const now = Date.now(); const window = (now - lastLogUs) / 1000; - if (droppedFrames > 0 && window > 0) { - const dropRate = droppedFrames / window; + if (window > 0 && (sentFrames > 0 || droppedFrames > 0)) { + const sentRate = sentFrames / window; const targetRate = 1000 / v.frameIntervalMs; - if (dropRate > targetRate * 0.25) { - this.console.log(`"${v.name}": dropping ~${dropRate.toFixed(1)} fps over the last ${window.toFixed(1)}s (in-flight HTTP POST hadn't returned when ffmpeg emitted the next frame; raise frame_interval_ms slightly to flatten this)`); + if (sentRate < targetRate * 0.75) { + const dropRate = droppedFrames / window; + this.console.log(`"${v.name}": delivered ~${sentRate.toFixed(1)} fps vs target ${targetRate.toFixed(1)} fps over the last ${window.toFixed(1)}s (dropped ~${dropRate.toFixed(1)} fps — in-flight HTTP POST hadn't returned when ffmpeg emitted the next frame; raise frame_interval_ms slightly to flatten this)`); } droppedFrames = 0; + sentFrames = 0; lastLogUs = now; } }, 10_000); |
