diff --git a/app/templates/live.html b/app/templates/live.html index 42e8589..1e2896a 100644 --- a/app/templates/live.html +++ b/app/templates/live.html @@ -206,21 +206,35 @@ btn.textContent = "🔇 Ton an"; audioOn = false; } else { + btn.textContent = "⏳ Verbinde…"; startAudio(); - btn.textContent = "🔊 Ton aus"; audioOn = true; } } function startAudio() { audioCtx = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: SAMPLE_RATE }); - nextPlayTime = audioCtx.currentTime; - const wsUrl = `ws://${location.host}/audio-ws`; + // Android/Chrome suspendiert AudioContext standardmäßig → explizit resumem + audioCtx.resume().then(() => { + nextPlayTime = audioCtx.currentTime; + connectWs(); + }); + } + + function connectWs() { + // ws:// oder wss:// je nach Seitenprotokoll + const proto = location.protocol === "https:" ? "wss" : "ws"; + const wsUrl = `${proto}://${location.host}/audio-ws`; audioWs = new WebSocket(wsUrl); audioWs.binaryType = "arraybuffer"; + audioWs.onopen = () => { + document.getElementById("audio-btn").textContent = "🔊 Ton aus"; + }; + audioWs.onmessage = (event) => { + if (!audioCtx) return; const pcm16 = new Int16Array(event.data); const buffer = audioCtx.createBuffer(1, pcm16.length, SAMPLE_RATE); const data = buffer.getChannelData(0); @@ -231,13 +245,16 @@ source.buffer = buffer; source.connect(audioCtx.destination); const now = audioCtx.currentTime; - // Kleine Puffer-Queue (~40ms) damit keine Lücken entstehen if (nextPlayTime < now) nextPlayTime = now + 0.04; source.start(nextPlayTime); nextPlayTime += buffer.duration; }; audioWs.onerror = () => stopAudio(); + audioWs.onclose = () => { + if (audioOn) stopAudio(); + document.getElementById("audio-btn").textContent = "🔇 Ton an"; + }; } function stopAudio() {