From 634d6490691c7d612719b63cf64c2df3283ef82f Mon Sep 17 00:00:00 2001 From: dsutanto Date: Mon, 10 Aug 2026 15:41:06 +0700 Subject: [PATCH] Fix STREAM toggle: auto-on preview only once per session, manual OFF persists --- SPEC.md | 3 ++- templates/recounting.html | 6 +++++- templates/recounting_lamborghini.html | 6 +++++- templates/recounting_upload.html | 7 ++++++- templates/recounting_upload_lamborghini.html | 7 ++++++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/SPEC.md b/SPEC.md index 1658a30..57d52ba 100644 --- a/SPEC.md +++ b/SPEC.md @@ -160,7 +160,7 @@ V18: .env missing → scripts fail at import (os.getenv falls back to defaults, V19: stream reconnect → reset motion detection state (prev_gray = None) V20: reset → delete STATE_FILE + touch {SHM_DIR}/.reset; batch_store._check_reset_signal() watches marker & clears in-memory state before next crossing V21: upload filename batch_XX_YYYYMMDD_HHmmSS.mp4 → batch# + date parsed; batch-result queries /api/day-detail/ on live API -V22: preview auto-on when recount running — enablePreview() on START RECOUNT + applyState streaming branch; manual toggle overrides; img.onerror retries cache-busted src while streaming +V22: preview auto-on once per streaming session — enablePreview() on START RECOUNT + applyState streaming branch guarded by previewAutoOn flag; manual toggle persists until next session (flag reset only on stop); img.onerror retries cache-busted src while streaming V23: .continue marker flow — LOAD MP4 spawns RECOUNT_CMD paused; START RECOUNT touches {SHM_DIR}/.continue; C++ process consumes marker to begin counting; dashboard never clears it (LOAD alone does not count) V24: STOP → killpg tracked group then host-wide /proc sweep of RECOUNT_CMD binary (basename of first token); sweep runs under _recount_lock, TERM→_SWEEP_GRACE_SEC→KILL, bounded retries; returns {success, killed, remaining} with remaining==0 in normal path; survivors (D-state) logged, never force-hang ``` @@ -195,5 +195,6 @@ T19|x|hard-kill STOP — sweep all RECOUNT_CMD-binary processes via /proc, verif ``` id|date|cause|fix B1|2026-07-29|prev_gray not reset on stream reconnect → cv2.absdiff crash or false motion|V19 +B2|2026-08-10|applyState re-ran enablePreview() every 1s poll, overriding manual STREAM toggle (OFF flipped back to ON)|V22 ``` diff --git a/templates/recounting.html b/templates/recounting.html index 22bbad4..a6091e1 100644 --- a/templates/recounting.html +++ b/templates/recounting.html @@ -449,6 +449,7 @@ let selectedFile = null; let streaming = false; let streamUrl = ''; +let previewAutoOn = false; document.addEventListener('DOMContentLoaded', () => { loadRecountProgress(); @@ -483,10 +484,11 @@ function applyState(data) { document.getElementById('video-status').innerHTML = ' streaming ' + (data.file_name || ''); document.getElementById('video-status').className = 'video-status connected'; - enablePreview(); + if (!previewAutoOn) enablePreview(); loadBatchResult(data.file); } else if (data.file && selectedFile === data.file) { + previewAutoOn = false; loadBatchResult(data.file); } } @@ -688,6 +690,7 @@ async function stopRecount() { streaming = false; streamUrl = ''; selectedFile = null; + previewAutoOn = false; batchResultLoaded = false; const img = document.getElementById('stream-img'); @@ -754,6 +757,7 @@ function enablePreview() { const img = document.getElementById('stream-img'); const placeholder = document.getElementById('video-placeholder'); if (!streamUrl) return; + previewAutoOn = true; img.onerror = function() { if (streaming && streamUrl) { img.src = streamUrl + '?' + Date.now(); diff --git a/templates/recounting_lamborghini.html b/templates/recounting_lamborghini.html index fa3058f..0053aa6 100644 --- a/templates/recounting_lamborghini.html +++ b/templates/recounting_lamborghini.html @@ -371,6 +371,7 @@ let selectedFile = null; let streaming = false; let streamUrl = ''; +let previewAutoOn = false; document.addEventListener('DOMContentLoaded', () => { loadRecountProgress(); @@ -405,10 +406,11 @@ function applyState(data) { document.getElementById('video-status').innerHTML = ' streaming ' + (data.file_name || ''); document.getElementById('video-status').className = 'video-status connected'; - enablePreview(); + if (!previewAutoOn) enablePreview(); loadBatchResult(data.file); } else if (data.file && selectedFile === data.file) { + previewAutoOn = false; loadBatchResult(data.file); } } @@ -611,6 +613,7 @@ async function stopRecount() { streaming = false; streamUrl = ''; selectedFile = null; + previewAutoOn = false; batchResultLoaded = false; const img = document.getElementById('stream-img'); @@ -677,6 +680,7 @@ function enablePreview() { const img = document.getElementById('stream-img'); const placeholder = document.getElementById('video-placeholder'); if (!streamUrl) return; + previewAutoOn = true; img.onerror = function() { if (streaming && streamUrl) { img.src = streamUrl + '?' + Date.now(); diff --git a/templates/recounting_upload.html b/templates/recounting_upload.html index 92589b6..a869f7c 100644 --- a/templates/recounting_upload.html +++ b/templates/recounting_upload.html @@ -551,6 +551,7 @@ let selectedFile = null; let streaming = false; let streamUrl = ''; +let previewAutoOn = false; let loaded = false; let started = false; let pendingUploadFile = null; @@ -856,6 +857,7 @@ async function stopRecount() { streaming = false; streamUrl = ''; selectedFile = null; + previewAutoOn = false; loaded = false; started = false; batchResultLoaded = false; @@ -916,6 +918,7 @@ function enablePreview() { var img = document.getElementById('stream-img'); var placeholder = document.getElementById('video-placeholder'); if (!streamUrl) return; + previewAutoOn = true; img.onerror = function() { if (streaming && streamUrl) { img.src = streamUrl + '?' + Date.now(); @@ -948,15 +951,17 @@ function applyState(data) { document.getElementById('video-status').innerHTML = ' streaming ' + (data.file_name || ''); document.getElementById('video-status').className = 'video-status connected'; - enablePreview(); + if (!previewAutoOn) enablePreview(); loadBatchResult(data.file); } else if (data.file && selectedFile === data.file) { + previewAutoOn = false; loaded = false; started = false; renderButtons(); loadBatchResult(data.file); } else if (!data.streaming) { + previewAutoOn = false; loaded = false; started = false; renderButtons(); diff --git a/templates/recounting_upload_lamborghini.html b/templates/recounting_upload_lamborghini.html index 92624d4..b1bf6f9 100644 --- a/templates/recounting_upload_lamborghini.html +++ b/templates/recounting_upload_lamborghini.html @@ -430,6 +430,7 @@ let selectedFile = null; let streaming = false; let streamUrl = ''; +let previewAutoOn = false; let loaded = false; let started = false; let pendingUploadFile = null; @@ -735,6 +736,7 @@ async function stopRecount() { streaming = false; streamUrl = ''; selectedFile = null; + previewAutoOn = false; loaded = false; started = false; batchResultLoaded = false; @@ -795,6 +797,7 @@ function enablePreview() { var img = document.getElementById('stream-img'); var placeholder = document.getElementById('video-placeholder'); if (!streamUrl) return; + previewAutoOn = true; img.onerror = function() { if (streaming && streamUrl) { img.src = streamUrl + '?' + Date.now(); @@ -827,15 +830,17 @@ function applyState(data) { document.getElementById('video-status').innerHTML = ' streaming ' + (data.file_name || ''); document.getElementById('video-status').className = 'video-status connected'; - enablePreview(); + if (!previewAutoOn) enablePreview(); loadBatchResult(data.file); } else if (data.file && selectedFile === data.file) { + previewAutoOn = false; loaded = false; started = false; renderButtons(); loadBatchResult(data.file); } else if (!data.streaming) { + previewAutoOn = false; loaded = false; started = false; renderButtons();