diff --git a/src/public/js/app.js b/src/public/js/app.js index a248d88..e53e4f7 100644 --- a/src/public/js/app.js +++ b/src/public/js/app.js @@ -145,7 +145,7 @@ function initRecognition() { const r = new SpeechRecognition(); r.lang = 'de-DE'; r.continuous = true; - r.interimResults = false; + r.interimResults = true; r.maxAlternatives = 1; let finalText = ''; @@ -158,17 +158,22 @@ function initRecognition() { }; r.onresult = (e) => { + let interim = ''; for (let i = e.resultIndex; i < e.results.length; i++) { - if (e.results[i].isFinal) + if (e.results[i].isFinal) { finalText += (finalText ? ' ' : '') + e.results[i][0].transcript; + } else { + interim += e.results[i][0].transcript; + } } - if (finalText.trim().split(/\s+/).length >= MAX_RECORD_WORDS) { + const display = finalText + (interim ? (finalText ? ' ' : '') + interim : ''); + if (display.trim().split(/\s+/).length >= MAX_RECORD_WORDS) { stopRecording(); return; } - updateTranscriptBox(finalText); - state.transcript = finalText; - checkBtn.disabled = !finalText.trim(); + updateTranscriptBox(display); + state.transcript = display; + checkBtn.disabled = !display.trim(); }; r.onend = () => { if (state.isRecording) stopRecording(); }; @@ -193,6 +198,16 @@ async function startRecording() { audioChunks = []; downloadBtn.disabled = true; + // Start SpeechRecognition first — triggers mic permission dialog on Android + transcriptBox.contentEditable = 'false'; + recognition = initRecognition(); + state.isRecording = true; + try { recognition.start(); } catch (_) {} + + clearTimeout(recordingTimer); + recordingTimer = setTimeout(stopRecording, MAX_RECORD_SECONDS * 1000); + + // MediaRecorder for audio download — best-effort, after recognition starts try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const mimeType = MediaRecorder.isTypeSupported('audio/webm;codecs=opus') @@ -208,14 +223,6 @@ async function startRecording() { } catch (e) { console.warn('MediaRecorder unavailable:', e); } - - transcriptBox.contentEditable = 'false'; - recognition = initRecognition(); - state.isRecording = true; - try { recognition.start(); } catch (_) {} - - clearTimeout(recordingTimer); - recordingTimer = setTimeout(stopRecording, MAX_RECORD_SECONDS * 1000); } function stopRecording() {