From 1a017999fe11c16933a7cc0438eabf2dffce9fb4 Mon Sep 17 00:00:00 2001 From: cclohmar Date: Wed, 5 Aug 2026 12:13:33 +0100 Subject: [PATCH] =?UTF-8?q?chore:=20v0.3.1=20=E2=80=94=20go2rtc=20auto-sta?= =?UTF-8?q?rt,=20live=20wall=20snapshots,=20MSE=20focus=20player?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 17 ++++++++++++++++- public/app.js | 17 +++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index 4c6119b..b7d4fb3 100644 --- a/main.go +++ b/main.go @@ -45,9 +45,20 @@ func main() { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + // Initialize application. + app := &App{Config: cfg, ConfigPath: configPath} + + // Start go2rtc if enabled. + if cfg.Go2RTC.Enabled { + go2rtc := NewGo2RTCManager(cfg.Go2RTC) + if err := go2rtc.Start(cfg.Cameras); err != nil { + log.Printf("go2rtc: start failed: %v", err) + } + app.go2rtc = go2rtc + } + // Start the HTTP server (blocks). errCh := make(chan error, 1) - app := &App{Config: cfg, ConfigPath: configPath} go func() { errCh <- app.StartServer() }() @@ -92,6 +103,7 @@ type App struct { Config Config ConfigPath string server *Server + go2rtc *Go2RTCManager } // StartServer initializes and starts the HTTP server. @@ -106,6 +118,9 @@ func (a *App) StartServer() error { // Shutdown performs a graceful shutdown of all services. func (a *App) Shutdown() { + if a.go2rtc != nil { + a.go2rtc.Stop() + } if a.server != nil { a.server.Close() } diff --git a/public/app.js b/public/app.js index 919e8d1..0483931 100644 --- a/public/app.js +++ b/public/app.js @@ -70,11 +70,20 @@ function renderLiveGrid() { tile.className = 'grid-tile' + (cam && cam.enabled ? '' : ' offline'); tile.dataset.camId = cam ? cam.id : ''; - if (cam) { + if (cam && cam.enabled) { + // go2rtc snapshot endpoint — refresh every 2 seconds for live preview. + const snapshotURL = `http://${location.hostname}:1984/api/frame.jpeg?src=${cam.id}_sub`; tile.innerHTML = ` + ${cam.name} ${cam.name} `; + // Auto-refresh snapshot. + setInterval(() => { + const img = tile.querySelector('img'); + if (img) img.src = snapshotURL + '&t=' + Date.now(); + }, 2000); tile.addEventListener('click', () => openFocus(cam)); } else { tile.innerHTML = 'No Camera'; @@ -97,10 +106,10 @@ function updateFocus() { const cam = cameras[focusIdx]; document.getElementById('focus-title').textContent = cam.name; document.getElementById('focus-time').textContent = new Date().toLocaleTimeString() + ' live'; - // TODO: M3 — connect to go2rtc WebRTC stream + // go2rtc MSE stream for full-quality playback. const vid = document.getElementById('focus-video'); - vid.src = ''; - vid.poster = ''; // placeholder until go2rtc is wired up + vid.src = `http://${location.hostname}:1984/api/stream.m3u8?src=${cam.id}_main`; + vid.play().catch(() => {}); } function renderThumbs() { const strip = document.getElementById('focus-thumbs');