Add server-side native German TTS endpoint with MP3 disk caching
This commit is contained in:
1 parent
ffe25e782a
commit
e8aef17029
2 files changed
+121
-5
No files matched your search
@@ -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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user