From 0bc81b50872251df394edc710e66faa5eaca39d5 Mon Sep 17 00:00:00 2001 From: cclohmar Date: Wed, 5 Aug 2026 12:51:02 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20focus=20mode=20uses=20fast-refresh=20JPE?= =?UTF-8?q?G=20=E2=80=94=20no=20codec=20dependency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/app.js | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/public/app.js b/public/app.js index fa24f3f..3027942 100644 --- a/public/app.js +++ b/public/app.js @@ -94,35 +94,26 @@ function renderLiveGrid() { // ── Focus Overlay ── let focusIdx = -1; +let focusTimer = null; function openFocus(cam) { focusIdx = cameras.indexOf(cam); const overlay = document.getElementById('focus-overlay'); overlay.classList.remove('hidden'); updateFocus(); renderThumbs(); + // Refresh snapshot every 500ms for smooth near-live view. + focusTimer = setInterval(updateFocus, 500); } function updateFocus() { if (focusIdx < 0 || focusIdx >= cameras.length) return; const cam = cameras[focusIdx]; document.getElementById('focus-title').textContent = cam.name; - document.getElementById('focus-time').textContent = new Date().toLocaleTimeString() + ' live'; - - // go2rtc WebRTC player — works in all browsers. + document.getElementById('focus-time').textContent = new Date().toLocaleTimeString(); + // Use the latest.jpg directly — updated every 2s by snapshot engine. + // Fast 500ms refresh gives smooth enough monitoring. const vid = document.getElementById('focus-video'); - const streamURL = `http://${location.hostname}:1984/stream.html?src=${cam.id}_main&mode=webrtc`; - // Use iframe for proper WebRTC support. - const container = vid.parentElement; - // Replace video element with iframe for go2rtc's player. - let iframe = container.querySelector('iframe.go2rtc-player'); - if (!iframe) { - iframe = document.createElement('iframe'); - iframe.className = 'go2rtc-player'; - iframe.allow = 'autoplay; camera; microphone'; - iframe.style.cssText = 'width:100%;height:100%;border:none;position:absolute;inset:0'; - vid.style.display = 'none'; - container.appendChild(iframe); - } - iframe.src = streamURL; + vid.style.display = 'block'; + vid.poster = `/recordings/${cam.name || cam.id}/latest.jpg?t=${Date.now()}`; } function renderThumbs() { const strip = document.getElementById('focus-thumbs'); @@ -138,6 +129,7 @@ function renderThumbs() { } document.getElementById('focus-close').addEventListener('click', () => { document.getElementById('focus-overlay').classList.add('hidden'); + if (focusTimer) { clearInterval(focusTimer); focusTimer = null; } }); document.getElementById('focus-prev').addEventListener('click', () => { if (focusIdx > 0) { focusIdx--; updateFocus(); renderThumbs(); } @@ -147,7 +139,10 @@ document.getElementById('focus-next').addEventListener('click', () => { }); document.addEventListener('keydown', e => { if (document.getElementById('focus-overlay').classList.contains('hidden')) return; - if (e.key === 'Escape') document.getElementById('focus-overlay').classList.add('hidden'); + if (e.key === 'Escape') { + document.getElementById('focus-overlay').classList.add('hidden'); + if (focusTimer) { clearInterval(focusTimer); focusTimer = null; } + } if (e.key === 'ArrowLeft' && focusIdx > 0) { focusIdx--; updateFocus(); renderThumbs(); } if (e.key === 'ArrowRight' && focusIdx < cameras.length - 1) { focusIdx++; updateFocus(); renderThumbs(); } });