Add server-side native German TTS endpoint with MP3 disk caching

This commit is contained in:
chrisf committed 2026-10-21 04:38:19 +00:00
1 parent ffe25e782a
commit e8aef17029
2 files changed
+121 -5

No files matched your search

+35 -5
View File
@@ -287,21 +287,51 @@ class WortKraftApp {
if (tooltip) tooltip.classList.remove("visible");
}
// === AUDIO PRONUNCIATION (Web Speech API de-DE) ===
speak(text, rate = 0.92) {
// === AUDIO PRONUNCIATION (Server Native German Neural TTS + Browser Fallback) ===
speak(text, rate = 0.96) {
if (!text) return;
// Stop any currently playing audio
if (this.currentAudio) {
try {
this.currentAudio.pause();
this.currentAudio.currentTime = 0;
} catch (_e) {}
this.currentAudio = null;
}
if ("speechSynthesis" in window) {
window.speechSynthesis.cancel();
}
// Primary: Stream authentic native German (de-DE) audio from backend /api/tts
if (window.location.protocol.startsWith("http")) {
const audio = new Audio(`/api/tts?text=${encodeURIComponent(text)}`);
audio.playbackRate = rate;
if ("preservesPitch" in audio) audio.preservesPitch = true;
this.currentAudio = audio;
audio.play().catch(err => {
console.warn("Server TTS playback error, falling back to browser TTS:", err);
this.speakBrowserFallback(text, rate);
});
return;
}
this.speakBrowserFallback(text, rate);
}
speakBrowserFallback(text, rate = 0.92) {
if (!("speechSynthesis" in window)) {
this.showToast("Audio wird von diesem Browser leider nicht unterstützt.");
return;
}
window.speechSynthesis.cancel();
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = "de-DE";
utterance.rate = rate;
const voices = window.speechSynthesis.getVoices();
const germanVoice =
voices.find(v => v.lang.startsWith("de") && (v.name.includes("Natural") || v.name.includes("Google") || v.name.includes("Anna") || v.name.includes("Katja"))) ||
voices.find(v => v.lang.startsWith("de"));
voices.find(v => v.lang.toLowerCase().startsWith("de") && (v.name.includes("Natural") || v.name.includes("Google") || v.name.includes("Anna") || v.name.includes("Katja") || v.name.includes("Hedda") || v.name.includes("Stefan"))) ||
voices.find(v => v.lang.toLowerCase().startsWith("de"));
if (germanVoice) {
utterance.voice = germanVoice;
}