diff --git a/app/web/app.js b/app/web/app.js index 1f25420..9590c64 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -201,21 +201,39 @@ let recChunks = []; async function startRecording() { if (busy) return; + const md = navigator.mediaDevices; + if (!md || !md.getUserMedia) { + addMessage("system", "Mikrofon nicht freigegeben: Bitte die Seite direkt in Safari öffnen (nicht im In-App-Browser) und keinen Privat-Modus verwenden."); + return; + } + if (typeof MediaRecorder === "undefined") { + addMessage("system", "Aufnahme nicht unterstützt (iOS < 14.3?). Bitte iOS aktualisieren."); + return; + } let stream; try { - stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + stream = await md.getUserMedia({ audio: true }); } catch (e) { - addMessage("system", "Mikrofon nicht verfuegbar (HTTPS noetig?). " + e.message); + addMessage("system", "Mikrofon-Zugriff fehlgeschlagen: " + (e.name || "") + + ". Tipp: iPhone → Einstellungen → Safari → Mikrofon = Erlauben/Fragen."); return; } recChunks = []; - mediaRecorder = new MediaRecorder(stream); + try { + mediaRecorder = new MediaRecorder(stream); + } catch (e) { + stream.getTracks().forEach((t) => t.stop()); + addMessage("system", "Aufnahme nicht möglich: " + (e.name || e.message)); + return; + } mediaRecorder.ondataavailable = (e) => { if (e.data.size) recChunks.push(e.data); }; mediaRecorder.onstop = async () => { stream.getTracks().forEach((t) => t.stop()); - const blob = new Blob(recChunks, { type: mediaRecorder.mimeType || "audio/webm" }); + const mime = mediaRecorder.mimeType || "audio/mp4"; + const blob = new Blob(recChunks, { type: mime }); const bytes = await blob.arrayBuffer(); - sendVoice(bytes); + // Safari -> audio/mp4, andere -> webm; der Server erkennt das Format am Inhalt. + sendVoice(bytes, mime.includes("mp4") || mime.includes("mpeg") ? "mp4" : "webm"); }; mediaRecorder.start(); micBtn.classList.remove("bg-emerald-600"); @@ -229,13 +247,13 @@ function stopRecording() { micBtn.classList.add("bg-emerald-600"); } -async function sendVoice(bytes) { +async function sendVoice(bytes, fmt = "webm") { if (busy) return; busy = true; await ensureSession(); statusEl.textContent = "verarbeite Sprache …"; await runTurn("/ws/voice", (ws) => { - ws.send(JSON.stringify({ type: "start", format: "webm", stream: true, audio_stream: true, ...overrides() })); + ws.send(JSON.stringify({ type: "start", format: fmt, stream: true, audio_stream: true, ...overrides() })); ws.send(bytes); ws.send(JSON.stringify({ type: "end" })); }); diff --git a/app/web/index.html b/app/web/index.html index e5c31a8..72af00c 100644 --- a/app/web/index.html +++ b/app/web/index.html @@ -60,6 +60,6 @@
- +