Files
spanish-diary/speech.js
T

74 lines
1.9 KiB
JavaScript

var speechVoices = [];
var speechVoicesLoaded = false;
function refreshSpeechVoices() {
if (!window.speechSynthesis) return;
var voices = window.speechSynthesis.getVoices();
if (voices && voices.length) {
speechVoices = voices;
speechVoicesLoaded = true;
}
return speechVoices;
}
function pickSpeechVoice(lang) {
refreshSpeechVoices();
var target = lang.toLowerCase();
var exact = speechVoices.find(function(voice) {
return String(voice.lang || '').toLowerCase() === target;
});
if (exact) return exact;
var prefix = target.split('-')[0];
return speechVoices.find(function(voice) {
return String(voice.lang || '').toLowerCase().split('-')[0] === prefix;
}) || null;
}
function buildSpeechUtterance(text, lang) {
var utterance = new SpeechSynthesisUtterance(text);
var langMap = { 'es': 'es-ES', 'en': 'en-US', 'zh': 'zh-CN' };
utterance.lang = langMap[lang] || lang;
var voice = pickSpeechVoice(utterance.lang);
if (voice) utterance.voice = voice;
utterance.rate = 0.9;
utterance.pitch = 1;
return utterance;
}
function doSpeak(text, lang) {
if (!window.speechSynthesis || !text) return;
window.speechSynthesis.cancel();
window.speechSynthesis.speak(buildSpeechUtterance(text, lang));
}
function speakText(text, lang) {
if (!text || !window.speechSynthesis) return;
refreshSpeechVoices();
if (speechVoicesLoaded) {
doSpeak(text, lang);
return;
}
var attempts = 0;
var timer = setInterval(function() {
attempts++;
refreshSpeechVoices();
if (speechVoicesLoaded || attempts >= 8) {
clearInterval(timer);
doSpeak(text, lang);
}
}, 80);
window.speechSynthesis.getVoices();
}
function initSpeech() {
if (!window.speechSynthesis) return;
refreshSpeechVoices();
window.speechSynthesis.onvoiceschanged = function() {
refreshSpeechVoices();
};
}
if (document.readyState === 'complete') initSpeech();
else document.addEventListener('DOMContentLoaded', initSpeech);