This commit is contained in:
@@ -75,6 +75,7 @@ func main() {
|
|||||||
"font-src 'self'",
|
"font-src 'self'",
|
||||||
"script-src 'self'",
|
"script-src 'self'",
|
||||||
"connect-src 'self'",
|
"connect-src 'self'",
|
||||||
|
"media-src 'self'", // <- wichtig
|
||||||
}, "; "),
|
}, "; "),
|
||||||
)
|
)
|
||||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
|
|||||||
@@ -5,40 +5,76 @@
|
|||||||
const viewersEl = document.getElementById('viewers');
|
const viewersEl = document.getElementById('viewers');
|
||||||
const srcEl = document.getElementById('hlssrc');
|
const srcEl = document.getElementById('hlssrc');
|
||||||
|
|
||||||
function updateLive(live){
|
const manifest = '/hls/' + encodeURIComponent(name) + '/index.m3u8';
|
||||||
liveEl.className = 'pill ' + (live ? 'live' : 'off');
|
|
||||||
liveEl.textContent = live ? 'LIVE' : 'Offline';
|
function setLive(l){
|
||||||
|
liveEl.className = 'pill ' + (l ? 'live' : 'off');
|
||||||
|
liveEl.textContent = l ? 'LIVE' : 'Offline';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refresh(){
|
async function head(url){
|
||||||
let data;
|
try {
|
||||||
try{
|
const r = await fetch(url, { method: 'HEAD', cache:'no-store' });
|
||||||
const r = await fetch('/api/streams', { cache: 'no-store' });
|
return r.ok;
|
||||||
if (!r.ok) throw new Error('api '+r.status);
|
} catch (_) { return false; }
|
||||||
data = await r.json();
|
}
|
||||||
}catch(e){
|
|
||||||
console.warn('streams api error:', e);
|
async function tryInitPlayer(){
|
||||||
setLive(false);
|
// 1) Manifest erreichbar?
|
||||||
viewersEl.textContent = 'Zuschauer: -';
|
const ok = await head(manifest);
|
||||||
return;
|
srcEl.textContent = manifest;
|
||||||
}
|
setLive(ok);
|
||||||
const r = await fetch('/api/streams');
|
if (!ok) return false;
|
||||||
const d = await r.json();
|
|
||||||
const it = d.items.find(x=>x.name===name);
|
// 2) Player initialisieren
|
||||||
const live = !!(it && it.live);
|
try {
|
||||||
updateLive(live);
|
if (window.Hls && Hls.isSupported()) {
|
||||||
viewersEl.textContent = 'Zuschauer: ' + (it ? it.viewers : 0);
|
if (!window._hls) {
|
||||||
if(live){
|
window._hls = new Hls({ maxLiveSyncPlaybackRate: 1.0 });
|
||||||
const src = '/hls/'+encodeURIComponent(name);
|
window._hls.on(Hls.Events.ERROR, (_, data)=>console.warn('hls.js error', data));
|
||||||
srcEl.textContent = src;
|
window._hls.attachMedia(v);
|
||||||
if (window.Hls && Hls.isSupported()){
|
}
|
||||||
if(!window._hls){ window._hls = new Hls(); window._hls.attachMedia(v); }
|
window._hls.loadSource(manifest);
|
||||||
window._hls.loadSource(src);
|
|
||||||
} else if (v.canPlayType('application/vnd.apple.mpegurl')) {
|
} else if (v.canPlayType('application/vnd.apple.mpegurl')) {
|
||||||
v.src = src;
|
v.src = manifest; // Safari / iOS
|
||||||
|
} else {
|
||||||
|
console.warn('HLS nicht unterstützt');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Player init fail', e);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh(); setInterval(refresh, 2500);
|
async function refreshMeta(){
|
||||||
|
// UI-Infos (viewer count etc.) optional, darf nie Player blockieren
|
||||||
|
try {
|
||||||
|
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);
|
||||||
|
if (it) {
|
||||||
|
setLive(!!it.live);
|
||||||
|
viewersEl.textContent = 'Zuschauer: ' + it.viewers;
|
||||||
|
}
|
||||||
|
} 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'));
|
||||||
|
|
||||||
|
// Boot-Sequenz mit Retries
|
||||||
|
(async function boot(){
|
||||||
|
for (let i=0; i<10; i++) {
|
||||||
|
const ok = await tryInitPlayer();
|
||||||
|
if (ok) break;
|
||||||
|
await new Promise(r=>setTimeout(r, 1500)); // kurz warten, bis HLS bereit ist
|
||||||
|
}
|
||||||
|
refreshMeta();
|
||||||
|
setInterval(refreshMeta, 2500);
|
||||||
|
})();
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user