chore: v0.3.1 — go2rtc auto-start, live wall snapshots, MSE focus player

This commit is contained in:
Claus Lohmar 2026-08-05 12:13:33 +01:00
parent 9de8536bdf
commit 1a017999fe
2 changed files with 29 additions and 5 deletions

17
main.go
View file

@ -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()
}

View file

@ -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 = `
<img src="${snapshotURL}" class="grid-snap" onerror="this.style.display='none'"
style="width:100%;height:100%;object-fit:cover;position:absolute;inset:0" alt="${cam.name}">
<span class="tile-status ${cam.online ? 'online' : 'offline'}"></span>
<span class="tile-label">${cam.name}</span>
`;
// 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 = '<span class="tile-placeholder">No Camera</span>';
@ -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');