chore: v0.3.1 — go2rtc auto-start, live wall snapshots, MSE focus player
This commit is contained in:
parent
9de8536bdf
commit
1a017999fe
2 changed files with 29 additions and 5 deletions
17
main.go
17
main.go
|
|
@ -45,9 +45,20 @@ func main() {
|
||||||
sigCh := make(chan os.Signal, 1)
|
sigCh := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
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).
|
// Start the HTTP server (blocks).
|
||||||
errCh := make(chan error, 1)
|
errCh := make(chan error, 1)
|
||||||
app := &App{Config: cfg, ConfigPath: configPath}
|
|
||||||
go func() {
|
go func() {
|
||||||
errCh <- app.StartServer()
|
errCh <- app.StartServer()
|
||||||
}()
|
}()
|
||||||
|
|
@ -92,6 +103,7 @@ type App struct {
|
||||||
Config Config
|
Config Config
|
||||||
ConfigPath string
|
ConfigPath string
|
||||||
server *Server
|
server *Server
|
||||||
|
go2rtc *Go2RTCManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartServer initializes and starts the HTTP server.
|
// StartServer initializes and starts the HTTP server.
|
||||||
|
|
@ -106,6 +118,9 @@ func (a *App) StartServer() error {
|
||||||
|
|
||||||
// Shutdown performs a graceful shutdown of all services.
|
// Shutdown performs a graceful shutdown of all services.
|
||||||
func (a *App) Shutdown() {
|
func (a *App) Shutdown() {
|
||||||
|
if a.go2rtc != nil {
|
||||||
|
a.go2rtc.Stop()
|
||||||
|
}
|
||||||
if a.server != nil {
|
if a.server != nil {
|
||||||
a.server.Close()
|
a.server.Close()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,20 @@ function renderLiveGrid() {
|
||||||
tile.className = 'grid-tile' + (cam && cam.enabled ? '' : ' offline');
|
tile.className = 'grid-tile' + (cam && cam.enabled ? '' : ' offline');
|
||||||
tile.dataset.camId = cam ? cam.id : '';
|
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 = `
|
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-status ${cam.online ? 'online' : 'offline'}"></span>
|
||||||
<span class="tile-label">${cam.name}</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));
|
tile.addEventListener('click', () => openFocus(cam));
|
||||||
} else {
|
} else {
|
||||||
tile.innerHTML = '<span class="tile-placeholder">No Camera</span>';
|
tile.innerHTML = '<span class="tile-placeholder">No Camera</span>';
|
||||||
|
|
@ -97,10 +106,10 @@ function updateFocus() {
|
||||||
const cam = cameras[focusIdx];
|
const cam = cameras[focusIdx];
|
||||||
document.getElementById('focus-title').textContent = cam.name;
|
document.getElementById('focus-title').textContent = cam.name;
|
||||||
document.getElementById('focus-time').textContent = new Date().toLocaleTimeString() + ' live';
|
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');
|
const vid = document.getElementById('focus-video');
|
||||||
vid.src = '';
|
vid.src = `http://${location.hostname}:1984/api/stream.m3u8?src=${cam.id}_main`;
|
||||||
vid.poster = ''; // placeholder until go2rtc is wired up
|
vid.play().catch(() => {});
|
||||||
}
|
}
|
||||||
function renderThumbs() {
|
function renderThumbs() {
|
||||||
const strip = document.getElementById('focus-thumbs');
|
const strip = document.getElementById('focus-thumbs');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue