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}
`;
+ // 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');