FFmpeg -> MediaMTX -> HLS relay with runtime-configurable modes: - PLAYBACK_MODE: standard (mpegts), fmp4 (HEVC), llhls - INGEST_MODE: rtmp, rtsp - INGEST_AUDIO_MODE: aac, copy - Hourly playlist auto-refresh from upstream URL - Fullscreen video UI with collapsible sidebar, upstream-down banner - Same-origin HLS proxy for HTTPS deployments Tagged as the last HLS-based version before the mpegts.js (v2) rework.
51 lines
1.3 KiB
Go
51 lines
1.3 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
const upstreamDownAfter = 10 * time.Second
|
|
|
|
// HandleStatus returns the current stream status as JSON.
|
|
// GET /api/status
|
|
func (a *App) HandleStatus(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
a.mu.RLock()
|
|
status := a.Status
|
|
a.mu.RUnlock()
|
|
|
|
// Attach live stream health metrics when FFmpeg is running
|
|
status.Health = a.FFmpeg.Health()
|
|
|
|
// Auto-clear transitioning once FFmpeg is producing health data.
|
|
// If no progress arrives for a while after a channel switch, flag upstream_down
|
|
// so all watchers see an "Upstream down?" warning via polling.
|
|
if status.Transitioning && status.Health != nil && status.Health.Speed != "" {
|
|
a.mu.Lock()
|
|
a.Status.Transitioning = false
|
|
a.Status.UpstreamDown = false
|
|
a.mu.Unlock()
|
|
status.Transitioning = false
|
|
status.UpstreamDown = false
|
|
} else if status.Transitioning {
|
|
a.mu.RLock()
|
|
switchStartedAt := a.SwitchStartedAt
|
|
a.mu.RUnlock()
|
|
if !switchStartedAt.IsZero() && time.Since(switchStartedAt) >= upstreamDownAfter {
|
|
a.mu.Lock()
|
|
a.Status.UpstreamDown = true
|
|
a.mu.Unlock()
|
|
status.UpstreamDown = true
|
|
}
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(status)
|
|
}
|