From f62d7e62c530b1e5718fb3fe3e0c9dbe28a53529 Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 21 Sep 2025 19:36:17 +0200 Subject: [PATCH] bugfix-4 --- web/static/js/stream.js | 81 +++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/web/static/js/stream.js b/web/static/js/stream.js index ad5b950..a7e169e 100644 --- a/web/static/js/stream.js +++ b/web/static/js/stream.js @@ -1,4 +1,4 @@ -(function(){ +(function () { const name = document.documentElement.dataset.stream; const v = document.getElementById('v'); const liveEl = document.getElementById('live'); @@ -7,72 +7,73 @@ const manifest = '/hls/' + encodeURIComponent(name) + '/index.m3u8'; - function setLive(l){ - liveEl.className = 'pill ' + (l ? 'live' : 'off'); - liveEl.textContent = l ? 'LIVE' : 'Offline'; + function setLive(on){ + liveEl.className = 'pill ' + (on ? 'live' : 'off'); + liveEl.textContent = on ? 'LIVE' : 'Offline'; } - async function head(url){ - try { - const r = await fetch(url, { method: 'HEAD', cache:'no-store' }); - return r.ok; - } catch (_) { return false; } + async function head(u){ + try { const r = await fetch(u, {method:'HEAD', cache:'no-store'}); return r.ok; } + catch { return false; } } - async function tryInitPlayer(){ - // 1) Manifest erreichbar? - const ok = await head(manifest); + async function initPlayer() { srcEl.textContent = manifest; + const ok = await head(manifest); setLive(ok); if (!ok) return false; - // 2) Player initialisieren - try { - if (window.Hls && Hls.isSupported()) { - if (!window._hls) { - window._hls = new Hls({ maxLiveSyncPlaybackRate: 1.0 }); - window._hls.on(Hls.Events.ERROR, (_, data)=>console.warn('hls.js error', data)); - window._hls.attachMedia(v); - } - window._hls.loadSource(manifest); - } else if (v.canPlayType('application/vnd.apple.mpegurl')) { - v.src = manifest; // Safari / iOS - } else { - console.warn('HLS nicht unterstützt'); - return false; + // Autoplay-Chance verbessern + try { v.muted = true; } catch(_) {} + try { v.playsInline = true; } catch(_) {} + + if (window.Hls && Hls.isSupported()) { + if (!window._hls) { + window._hls = new Hls({ liveDurationInfinity: true }); + window._hls.on(Hls.Events.MANIFEST_PARSED, (_e, data) => { + console.log('HLS manifest parsed. levels=', data.levels?.length); + }); + window._hls.on(Hls.Events.ERROR, (_e, data) => { + console.warn('hls.js error', data); + }); + window._hls.attachMedia(v); } - return true; - } catch (e) { - console.warn('Player init fail', e); + window._hls.loadSource(manifest); + } else if (v.canPlayType('application/vnd.apple.mpegurl')) { + v.src = manifest; // Safari / iOS + } else { + console.warn('HLS nicht unterstützt'); return false; } + + // Autoplay versuchen (wird bei Desktop-Browsern oft blockiert; Controls bleiben) + try { await v.play(); } catch(e) { console.log('autoplay blockiert (ok):', e?.name||e); } + + return true; } async function refreshMeta(){ - // UI-Infos (viewer count etc.) optional, darf nie Player blockieren try { - const r = await fetch('/api/streams', { cache:'no-store' }); + const r = await fetch('/api/streams', {cache:'no-store'}); if (!r.ok) return; const d = await r.json(); - const it = d.items.find(x=>x.name===name); + const it = d.items.find(x => x.name === name); if (it) { setLive(!!it.live); viewersEl.textContent = 'Zuschauer: ' + it.viewers; } - } catch (_) {} + } catch {} } - // Video-Fehler sichtbar loggen - v.addEventListener('error', (e)=>console.warn('video error', e)); - v.addEventListener('loadedmetadata', ()=>console.log('metadata loaded')); - v.addEventListener('playing', ()=>console.log('playing')); + v.addEventListener('error', e => console.warn('video error', e)); + v.addEventListener('loadedmetadata', () => console.log('loadedmetadata')); + v.addEventListener('playing', () => console.log('playing')); - // Boot-Sequenz mit Retries (async function boot(){ for (let i=0; i<10; i++) { - const ok = await tryInitPlayer(); + const ok = await initPlayer(); if (ok) break; - await new Promise(r=>setTimeout(r, 1500)); // kurz warten, bis HLS bereit ist + await new Promise(r => setTimeout(r, 1500)); } refreshMeta(); setInterval(refreshMeta, 2500);