diff --git a/public/app.js b/public/app.js index 9538113..8735625 100644 --- a/public/app.js +++ b/public/app.js @@ -94,24 +94,27 @@ 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'); - refreshFocus(); - renderThumbs(); - // Fast JPEG refresh — 200ms = ~5fps, smooth enough for monitoring. - focusTimer = setInterval(refreshFocus, 200); -} -function refreshFocus() { - if (focusIdx < 0 || focusIdx >= cameras.length) return; - const cam = cameras[focusIdx]; + // Remove any previous iframe. + const oldFrame = overlay.querySelector('iframe.go2rtc'); + if (oldFrame) oldFrame.remove(); + // Create go2rtc WebRTC player iframe — real live video. + const container = document.getElementById('focus-video').parentElement; + const iframe = document.createElement('iframe'); + iframe.className = 'go2rtc'; + iframe.allow = 'autoplay'; + iframe.style.cssText = 'width:100%;height:100%;border:none;flex:1'; + iframe.src = `http://${location.hostname}:1984/stream.html?src=${cam.id}_sub&mode=webrtc,mse,mp4`; + container.insertBefore(iframe, document.getElementById('focus-video')); + document.getElementById('focus-video').style.display = 'none'; document.getElementById('focus-title').textContent = cam.name; document.getElementById('focus-time').textContent = new Date().toLocaleTimeString() + ' live'; - const img = document.getElementById('focus-video'); - img.src = `/recordings/${cam.name || cam.id}/latest.jpg?t=${Date.now()}`; + renderThumbs(); } +function updateFocus() {} function renderThumbs() { const strip = document.getElementById('focus-thumbs'); strip.innerHTML = ''; @@ -125,23 +128,25 @@ function renderThumbs() { }); } document.getElementById('focus-close').addEventListener('click', () => { - document.getElementById('focus-overlay').classList.add('hidden'); - if (focusTimer) { clearInterval(focusTimer); focusTimer = null; } + const overlay = document.getElementById('focus-overlay'); + overlay.classList.add('hidden'); + const iframe = overlay.querySelector('iframe.go2rtc'); + if (iframe) iframe.remove(); + document.getElementById('focus-video').style.display = ''; }); document.getElementById('focus-prev').addEventListener('click', () => { - if (focusIdx > 0) { focusIdx--; refreshFocus(); renderThumbs(); } + if (focusIdx > 0) { focusIdx--; openFocus(cameras[focusIdx]); } }); document.getElementById('focus-next').addEventListener('click', () => { - if (focusIdx < cameras.length - 1) { focusIdx++; refreshFocus(); renderThumbs(); } + if (focusIdx < cameras.length - 1) { focusIdx++; openFocus(cameras[focusIdx]); } }); 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 (focusTimer) { clearInterval(focusTimer); focusTimer = null; } + document.getElementById('focus-close').click(); } - if (e.key === 'ArrowLeft' && focusIdx > 0) { focusIdx--; refreshFocus(); renderThumbs(); } - if (e.key === 'ArrowRight' && focusIdx < cameras.length - 1) { focusIdx++; refreshFocus(); renderThumbs(); } + if (e.key === 'ArrowLeft' && focusIdx > 0) { focusIdx--; openFocus(cameras[focusIdx]); } + if (e.key === 'ArrowRight' && focusIdx < cameras.length - 1) { focusIdx++; openFocus(cameras[focusIdx]); } }); // ── Playback ──