max words
This commit is contained in:
@@ -323,7 +323,7 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transcript-box.interim { color: var(--text-dim); }
|
.transcript-box[contenteditable="true"] { outline: none; cursor: text; border-color: var(--accent); }
|
||||||
|
|
||||||
/* ── Actions ── */
|
/* ── Actions ── */
|
||||||
.actions {
|
.actions {
|
||||||
@@ -830,6 +830,7 @@ function loadQuestion() {
|
|||||||
|
|
||||||
function resetPracticeUI() {
|
function resetPracticeUI() {
|
||||||
state.transcript = '';
|
state.transcript = '';
|
||||||
|
transcriptBox.contentEditable = 'false';
|
||||||
updateTranscriptBox('', false);
|
updateTranscriptBox('', false);
|
||||||
feedbackBox.classList.remove('visible');
|
feedbackBox.classList.remove('visible');
|
||||||
feedbackContent.innerHTML = '';
|
feedbackContent.innerHTML = '';
|
||||||
@@ -866,8 +867,8 @@ speakBtn.addEventListener('click', () => {
|
|||||||
|
|
||||||
// ── Speech recognition ────────────────────────────────────────────────────────
|
// ── Speech recognition ────────────────────────────────────────────────────────
|
||||||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||||
const MAX_RECORD_SECONDS = 10;
|
const MAX_RECORD_SECONDS = 20;
|
||||||
const MAX_RECORD_WORDS = 30;
|
const MAX_RECORD_WORDS = 60;
|
||||||
|
|
||||||
function initRecognition() {
|
function initRecognition() {
|
||||||
if (!SpeechRecognition) return null;
|
if (!SpeechRecognition) return null;
|
||||||
@@ -875,7 +876,7 @@ function initRecognition() {
|
|||||||
const r = new SpeechRecognition();
|
const r = new SpeechRecognition();
|
||||||
r.lang = 'de-DE';
|
r.lang = 'de-DE';
|
||||||
r.continuous = true;
|
r.continuous = true;
|
||||||
r.interimResults = true;
|
r.interimResults = false;
|
||||||
r.maxAlternatives = 1;
|
r.maxAlternatives = 1;
|
||||||
|
|
||||||
let finalText = '';
|
let finalText = '';
|
||||||
@@ -888,32 +889,22 @@ function initRecognition() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
r.onresult = (e) => {
|
r.onresult = (e) => {
|
||||||
let interim = '';
|
|
||||||
for (let i = e.resultIndex; i < e.results.length; i++) {
|
for (let i = e.resultIndex; i < e.results.length; i++) {
|
||||||
const t = e.results[i][0].transcript;
|
|
||||||
if (e.results[i].isFinal) {
|
if (e.results[i].isFinal) {
|
||||||
finalText += (finalText ? ' ' : '') + t;
|
finalText += (finalText ? ' ' : '') + e.results[i][0].transcript;
|
||||||
} else {
|
|
||||||
interim = t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (finalText.trim().split(/\s+/).length >= MAX_RECORD_WORDS) {
|
if (finalText.trim().split(/\s+/).length >= MAX_RECORD_WORDS) {
|
||||||
stopRecording();
|
stopRecording();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const display = finalText + (interim ? ' ' + interim : '');
|
updateTranscriptBox(finalText, false);
|
||||||
updateTranscriptBox(display, !!interim);
|
|
||||||
state.transcript = finalText;
|
state.transcript = finalText;
|
||||||
checkBtn.disabled = !finalText.trim();
|
checkBtn.disabled = !finalText.trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
r.onend = () => {
|
r.onend = () => {
|
||||||
if (state.isRecording) {
|
if (state.isRecording) stopRecording();
|
||||||
// create a fresh instance to avoid duplicate results on restart
|
|
||||||
const fresh = initRecognition();
|
|
||||||
recognition = fresh;
|
|
||||||
try { fresh.start(); } catch (_) {}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
r.onerror = (e) => {
|
r.onerror = (e) => {
|
||||||
@@ -933,6 +924,7 @@ function startRecording() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stopAudio();
|
stopAudio();
|
||||||
|
transcriptBox.contentEditable = 'false';
|
||||||
recognition = initRecognition();
|
recognition = initRecognition();
|
||||||
state.isRecording = true;
|
state.isRecording = true;
|
||||||
try { recognition.start(); } catch (_) {}
|
try { recognition.start(); } catch (_) {}
|
||||||
@@ -950,6 +942,10 @@ function stopRecording() {
|
|||||||
}
|
}
|
||||||
recordBtn.classList.remove('recording');
|
recordBtn.classList.remove('recording');
|
||||||
recordHint.textContent = 'Tippen zum Aufnehmen';
|
recordHint.textContent = 'Tippen zum Aufnehmen';
|
||||||
|
if (state.transcript) {
|
||||||
|
transcriptBox.contentEditable = 'true';
|
||||||
|
transcriptBox.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recordBtn.addEventListener('click', () => {
|
recordBtn.addEventListener('click', () => {
|
||||||
@@ -972,10 +968,16 @@ function updateTranscriptBox(text, isInterim) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transcriptBox.addEventListener('input', () => {
|
||||||
|
state.transcript = transcriptBox.textContent.trim();
|
||||||
|
checkBtn.disabled = !state.transcript;
|
||||||
|
});
|
||||||
|
|
||||||
// ── Clear ─────────────────────────────────────────────────────────────────────
|
// ── Clear ─────────────────────────────────────────────────────────────────────
|
||||||
clearBtn.addEventListener('click', () => {
|
clearBtn.addEventListener('click', () => {
|
||||||
stopRecording();
|
stopRecording();
|
||||||
state.transcript = '';
|
state.transcript = '';
|
||||||
|
transcriptBox.contentEditable = 'false';
|
||||||
updateTranscriptBox('', false);
|
updateTranscriptBox('', false);
|
||||||
checkBtn.disabled = true;
|
checkBtn.disabled = true;
|
||||||
feedbackBox.classList.remove('visible');
|
feedbackBox.classList.remove('visible');
|
||||||
|
|||||||
Reference in New Issue
Block a user