fix-11 - viewer-count
All checks were successful
release-tag / release-image (push) Successful in 1m58s

This commit is contained in:
2025-09-21 22:13:20 +02:00
parent 5c21131f97
commit 949f07d420
3 changed files with 159 additions and 63 deletions

View File

@@ -87,6 +87,41 @@ func eq(a, b []byte) bool {
return true
}
type mtxHLSPayload struct {
// v1.15.0 liefert einen Muxer mit Clients-Liste (Feldname kann "clients" heißen)
Item struct {
Name string `json:"name"`
Clients []interface{} `json:"clients"` // Anzahl = echte HLS-Zuschauer
} `json:"item"`
// manche Builds liefern flach:
Name string `json:"name"`
Clients []interface{} `json:"clients"`
}
func hlsViewers(ctx context.Context, base, user, pass, name string) (int, error) {
u := strings.TrimRight(base, "/") + "/v3/hlsmuxers/get/" + url.PathEscape(name)
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
if user != "" || pass != "" {
req.SetBasicAuth(user, pass)
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return 0, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return 0, fmt.Errorf("hlsmuxers/get %s: %s", name, res.Status)
}
var out mtxHLSPayload
if err := json.NewDecoder(res.Body).Decode(&out); err != nil {
return 0, err
}
if out.Item.Clients != nil {
return len(out.Item.Clients), nil
}
return len(out.Clients), nil
}
func init() {
_ = mime.AddExtensionType(".css", "text/css")
_ = mime.AddExtensionType(".js", "application/javascript")
@@ -270,22 +305,26 @@ func main() {
continue
}
viewers := 0
{
ctx2, cancel2 := context.WithTimeout(context.Background(), 2*time.Second)
v, err := fetchMTXViewers(ctx2, mtxAPI, os.Getenv("MTX_API_USER"), os.Getenv("MTX_API_PASS"), p.Name)
cancel2()
if err == nil {
// 1) Versuche echte HLS-Clients zu zählen
ctx2, cancel2 := context.WithTimeout(context.Background(), 2*time.Second)
if v, err := hlsViewers(ctx2, mtxAPI, os.Getenv("MTX_API_USER"), os.Getenv("MTX_API_PASS"), p.Name); err == nil {
viewers = v
}
cancel2()
// 2) Fallback: wenn HLS-API nicht greift (z.B. stream per RTSP/WebRTC gelesen),
// nimm Pfad-Reader (kann >0 bei Nicht-HLS sein, bei HLS meist 1 = Muxer)
if viewers == 0 {
if v := p.Viewers(); v > 0 {
viewers = v
} else {
// Fallback: falls API kurz zickt, nehme zur Not den alten Wert,
// aber brich das Live-UI nicht: viewers bleibt 0, Live bleibt p.Live()
// log.Printf("warn: mtx viewers %s: %v", p.Name, err)
}
}
out.Items = append(out.Items, item{
Name: p.Name,
Live: p.Live(), // deine bisherige Live-Logik bleibt erhalten
Viewers: viewers, // echte Leserzahl aus MediaMTX
Live: p.Live(),
Viewers: viewers,
})
}
@@ -397,22 +436,26 @@ func apiStreams(w http.ResponseWriter, r *http.Request) {
continue
}
viewers := 0
{
ctx2, cancel2 := context.WithTimeout(context.Background(), 2*time.Second)
v, err := fetchMTXViewers(ctx2, mtxAPI, os.Getenv("MTX_API_USER"), os.Getenv("MTX_API_PASS"), p.Name)
cancel2()
if err == nil {
// 1) Versuche echte HLS-Clients zu zählen
ctx2, cancel2 := context.WithTimeout(context.Background(), 2*time.Second)
if v, err := hlsViewers(ctx2, mtxAPI, os.Getenv("MTX_API_USER"), os.Getenv("MTX_API_PASS"), p.Name); err == nil {
viewers = v
}
cancel2()
// 2) Fallback: wenn HLS-API nicht greift (z.B. stream per RTSP/WebRTC gelesen),
// nimm Pfad-Reader (kann >0 bei Nicht-HLS sein, bei HLS meist 1 = Muxer)
if viewers == 0 {
if v := p.Viewers(); v > 0 {
viewers = v
} else {
// Fallback: falls API kurz zickt, nehme zur Not den alten Wert,
// aber brich das Live-UI nicht: viewers bleibt 0, Live bleibt p.Live()
// log.Printf("warn: mtx viewers %s: %v", p.Name, err)
}
}
out.Items = append(out.Items, item{
Name: p.Name,
Live: p.Live(), // deine bisherige Live-Logik bleibt erhalten
Viewers: viewers, // echte Leserzahl aus MediaMTX
Live: p.Live(),
Viewers: viewers,
})
}
w.Header().Set("Content-Type", "application/json")