fix: 优化移动端朗读语音加载与语言匹配

This commit is contained in:
guoqingshan
2026-08-02 11:56:29 +08:00
parent 75fc9cc7a4
commit ab427d2fdc
+58 -18
View File
@@ -1,32 +1,72 @@
function initSpeech() { var speechVoices = [];
var speechVoicesLoaded = false;
function refreshSpeechVoices() {
if (!window.speechSynthesis) return; if (!window.speechSynthesis) return;
var voices = window.speechSynthesis.getVoices(); var voices = window.speechSynthesis.getVoices();
if (voices.length > 0) return; if (voices && voices.length) {
window.speechSynthesis.onvoiceschanged = function() {}; speechVoices = voices;
speechVoicesLoaded = true;
}
return speechVoices;
} }
function speakText(text, lang) { function pickSpeechVoice(lang) {
if (!text) return; refreshSpeechVoices();
if (!window.speechSynthesis) { return; } var target = lang.toLowerCase();
if (window.speechSynthesis.getVoices().length === 0) { var exact = speechVoices.find(function(voice) {
window.speechSynthesis.onvoiceschanged = function() { return String(voice.lang || '').toLowerCase() === target;
doSpeak(text, lang); });
window.speechSynthesis.onvoiceschanged = null; if (exact) return exact;
}; var prefix = target.split('-')[0];
window.speechSynthesis.getVoices(); return speechVoices.find(function(voice) {
return; return String(voice.lang || '').toLowerCase().split('-')[0] === prefix;
} }) || null;
doSpeak(text, lang);
} }
function doSpeak(text, lang) { function buildSpeechUtterance(text, lang) {
window.speechSynthesis.cancel();
var utterance = new SpeechSynthesisUtterance(text); var utterance = new SpeechSynthesisUtterance(text);
var langMap = { 'es': 'es-ES', 'en': 'en-US', 'zh': 'zh-CN' }; var langMap = { 'es': 'es-ES', 'en': 'en-US', 'zh': 'zh-CN' };
utterance.lang = langMap[lang] || lang; utterance.lang = langMap[lang] || lang;
var voice = pickSpeechVoice(utterance.lang);
if (voice) utterance.voice = voice;
utterance.rate = 0.9; utterance.rate = 0.9;
utterance.pitch = 1; utterance.pitch = 1;
window.speechSynthesis.speak(utterance); 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(); if (document.readyState === 'complete') initSpeech();