diff --git a/cmd/dashboard/main.go b/cmd/dashboard/main.go
index 0ada20f..1871475 100644
--- a/cmd/dashboard/main.go
+++ b/cmd/dashboard/main.go
@@ -147,12 +147,16 @@ func main() {
func apiStreams(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
+
c := &mtx.Client{BaseURL: mtxAPI, User: os.Getenv("MTX_API_USER"), Pass: os.Getenv("MTX_API_PASS")}
pl, err := c.Paths(ctx)
if err != nil {
- http.Error(w, err.Error(), http.StatusBadGateway)
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusBadGateway)
+ _ = json.NewEncoder(w).Encode(map[string]any{"error": err.Error()})
return
}
+
allowed := map[string]bool{}
if streamsCSV != "" {
for _, s := range strings.Split(streamsCSV, ",") {
@@ -174,7 +178,7 @@ func apiStreams(w http.ResponseWriter, r *http.Request) {
out.Items = append(out.Items, item{Name: p.Name, Live: p.Live(), Viewers: p.Viewers()})
}
w.Header().Set("Content-Type", "application/json")
- json.NewEncoder(w).Encode(out)
+ _ = json.NewEncoder(w).Encode(out)
}
func pageIndex(w http.ResponseWriter, r *http.Request) {
diff --git a/web/static/js/index.js b/web/static/js/index.js
index c658af1..10e70b9 100644
--- a/web/static/js/index.js
+++ b/web/static/js/index.js
@@ -1,25 +1,35 @@
async function load(){
- const r = await fetch('/api/streams');
- const data = await r.json();
+ let data;
+ try {
+ const r = await fetch('/api/streams', { cache: 'no-store' });
+ if (!r.ok) throw new Error('api '+r.status);
+ data = await r.json();
+ } catch (e) {
+ console.warn('streams api error:', e);
+ // UI freundlich degradieren
+ document.getElementById('list').innerHTML =
+ '
';
+ return;
+ }
const q = (document.getElementById('filter').value||'').toLowerCase();
const list = document.getElementById('list');
list.innerHTML = '';
- data.items
- .filter(it => !q || it.name.toLowerCase().includes(q))
- .forEach(it => {
- const a = document.createElement('a');
- a.href = '/' + encodeURIComponent(it.name);
- a.className = 'card';
- a.innerHTML = `
-
-
-
${it.name}
-
Zuschauer: ${it.viewers}
-
-
${it.live ? 'LIVE' : 'Offline'}
-
`;
- list.appendChild(a);
- });
+ data.items.filter(it => !q || it.name.toLowerCase().includes(q)).forEach(it => {
+ const a = document.createElement('a');
+ a.href = '/' + encodeURIComponent(it.name);
+ a.className = 'card';
+ a.innerHTML = `
+
+
+
${it.name}
+
Zuschauer: ${it.viewers}
+
+
${it.live ? 'LIVE' : 'Offline'}
+
`;
+ list.appendChild(a);
+ });
}
document.getElementById('filter').addEventListener('input', load);
-load(); setInterval(load, 3000);
+document.getElementById('reload').addEventListener('click', load);
+load();
+setInterval(load, 3000);
diff --git a/web/static/js/stream.js b/web/static/js/stream.js
index 20711a3..696e8b2 100644
--- a/web/static/js/stream.js
+++ b/web/static/js/stream.js
@@ -11,6 +11,17 @@
}
async function refresh(){
+ let data;
+ try{
+ const r = await fetch('/api/streams', { cache: 'no-store' });
+ if (!r.ok) throw new Error('api '+r.status);
+ data = await r.json();
+ }catch(e){
+ console.warn('streams api error:', e);
+ setLive(false);
+ viewersEl.textContent = 'Zuschauer: –';
+ return;
+ }
const r = await fetch('/api/streams');
const d = await r.json();
const it = d.items.find(x=>x.name===name);
diff --git a/web/templates/index.html b/web/templates/index.html
index 0ae0bcc..67d4978 100644
--- a/web/templates/index.html
+++ b/web/templates/index.html
@@ -16,7 +16,7 @@
🎬 Streams
RTMP Ingest: rtmp://HOST/<name> · HLS: http(s)://HOST/hls/<name>