fix bug
This commit is contained in:
@@ -10,6 +10,7 @@ const state = {
|
|||||||
currentIndex: 0,
|
currentIndex: 0,
|
||||||
questionQueue: [],
|
questionQueue: [],
|
||||||
transcript: '',
|
transcript: '',
|
||||||
|
finalTranscript: '',
|
||||||
isRecording: false,
|
isRecording: false,
|
||||||
isChecking: false,
|
isChecking: false,
|
||||||
sessionHistory: [],
|
sessionHistory: [],
|
||||||
@@ -101,6 +102,7 @@ function loadQuestion() {
|
|||||||
|
|
||||||
function resetPracticeUI() {
|
function resetPracticeUI() {
|
||||||
state.transcript = '';
|
state.transcript = '';
|
||||||
|
state.finalTranscript = '';
|
||||||
transcriptBox.contentEditable = 'false';
|
transcriptBox.contentEditable = 'false';
|
||||||
updateTranscriptBox('');
|
updateTranscriptBox('');
|
||||||
feedbackBox.classList.remove('visible');
|
feedbackBox.classList.remove('visible');
|
||||||
@@ -140,18 +142,15 @@ speakBtn.addEventListener('click', () => {
|
|||||||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||||
let recognition = null;
|
let recognition = null;
|
||||||
|
|
||||||
function initRecognition() {
|
function createRecognition() {
|
||||||
if (!SpeechRecognition) return null;
|
if (!SpeechRecognition) return null;
|
||||||
const r = new SpeechRecognition();
|
const r = new SpeechRecognition();
|
||||||
r.lang = 'de-DE';
|
r.lang = 'de-DE';
|
||||||
r.continuous = true;
|
r.continuous = false; // false is more reliable on Android
|
||||||
r.interimResults = true;
|
r.interimResults = true;
|
||||||
r.maxAlternatives = 1;
|
r.maxAlternatives = 1;
|
||||||
|
|
||||||
let finalText = '';
|
|
||||||
|
|
||||||
r.onstart = () => {
|
r.onstart = () => {
|
||||||
finalText = state.transcript;
|
|
||||||
recordBtn.classList.add('recording');
|
recordBtn.classList.add('recording');
|
||||||
recordHint.textContent = 'Tippen zum Stoppen';
|
recordHint.textContent = 'Tippen zum Stoppen';
|
||||||
state.isRecording = true;
|
state.isRecording = true;
|
||||||
@@ -159,14 +158,18 @@ function initRecognition() {
|
|||||||
|
|
||||||
r.onresult = (e) => {
|
r.onresult = (e) => {
|
||||||
let interim = '';
|
let interim = '';
|
||||||
|
let finalChunk = '';
|
||||||
for (let i = e.resultIndex; i < e.results.length; i++) {
|
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;
|
finalChunk += (finalChunk ? ' ' : '') + e.results[i][0].transcript;
|
||||||
} else {
|
} else {
|
||||||
interim += e.results[i][0].transcript;
|
interim += e.results[i][0].transcript;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const display = finalText + (interim ? (finalText ? ' ' : '') + interim : '');
|
if (finalChunk) {
|
||||||
|
state.finalTranscript += (state.finalTranscript ? ' ' : '') + finalChunk;
|
||||||
|
}
|
||||||
|
const display = state.finalTranscript + (interim ? (state.finalTranscript ? ' ' : '') + interim : '');
|
||||||
if (display.trim().split(/\s+/).length >= MAX_RECORD_WORDS) {
|
if (display.trim().split(/\s+/).length >= MAX_RECORD_WORDS) {
|
||||||
stopRecording();
|
stopRecording();
|
||||||
return;
|
return;
|
||||||
@@ -177,12 +180,19 @@ function initRecognition() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
r.onend = () => {
|
r.onend = () => {
|
||||||
if (state.isRecording) {
|
if (!state.isRecording) return;
|
||||||
// Android stops recognition on its own after silence — restart it
|
// Android/Chrome ends session after each phrase — restart to keep listening
|
||||||
try { r.start(); } catch (_) {}
|
setTimeout(() => {
|
||||||
}
|
if (!state.isRecording) return;
|
||||||
|
recognition = createRecognition();
|
||||||
|
try { recognition.start(); } catch (_) { stopRecording(); }
|
||||||
|
}, 80);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 'aborted' fires during normal restart cycle — ignore it
|
||||||
|
r.onerror = (e) => {
|
||||||
|
if (e.error !== 'no-speech' && e.error !== 'aborted') stopRecording();
|
||||||
};
|
};
|
||||||
r.onerror = (e) => { if (e.error !== 'no-speech') stopRecording(); };
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -205,7 +215,7 @@ async function startRecording() {
|
|||||||
|
|
||||||
// Start SpeechRecognition first — triggers mic permission dialog on Android
|
// Start SpeechRecognition first — triggers mic permission dialog on Android
|
||||||
transcriptBox.contentEditable = 'false';
|
transcriptBox.contentEditable = 'false';
|
||||||
recognition = initRecognition();
|
recognition = createRecognition();
|
||||||
state.isRecording = true;
|
state.isRecording = true;
|
||||||
try { recognition.start(); } catch (_) {}
|
try { recognition.start(); } catch (_) {}
|
||||||
|
|
||||||
@@ -280,6 +290,7 @@ downloadBtn.addEventListener('click', () => {
|
|||||||
clearBtn.addEventListener('click', () => {
|
clearBtn.addEventListener('click', () => {
|
||||||
stopRecording();
|
stopRecording();
|
||||||
state.transcript = '';
|
state.transcript = '';
|
||||||
|
state.finalTranscript = '';
|
||||||
transcriptBox.contentEditable = 'false';
|
transcriptBox.contentEditable = 'false';
|
||||||
updateTranscriptBox('');
|
updateTranscriptBox('');
|
||||||
checkBtn.disabled = true;
|
checkBtn.disabled = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user