如何设置Speech Synthesis特定语音,解决默认语音干扰及首次点击失效问题
解决SpeechSynthesis首次点击语音不生效的问题
问题根源在于浏览器加载语音资源是异步的,首次调用getVoices()时,语音列表还没完全加载完成,导致你指定的voices[9]可能不存在,只能默认使用对应语言的兜底语音。第二次点击时语音列表已经加载完毕,所以能正确选中目标语音。
解决步骤:
- 监听
voiceschanged事件,等语音列表加载完成后缓存起来,避免每次点击临时获取 - 点击按钮时直接用缓存好的语音列表,确保首次点击就能拿到正确的语音
修改后的代码:
// 缓存加载完成的语音列表 let cachedVoices = []; // 监听语音列表加载完成事件 window.speechSynthesis.onvoiceschanged = () => { cachedVoices = window.speechSynthesis.getVoices(); }; function speakTTS() { // 先检查语音列表是否就绪 if (cachedVoices.length === 0) { // 手动触发一次获取,兼容部分浏览器的延迟加载逻辑 cachedVoices = window.speechSynthesis.getVoices(); if (cachedVoices.length === 0) { alert('语音资源还没加载好,请稍后再试'); return; } } const message = new SpeechSynthesisUtterance(); message.text = "Please get me a bottle of water, thank you."; message.volume = 1; message.rate = 1.1; // 使用缓存的语音列表 message.voice = cachedVoices[9]; message.lang = 'en-GB'; window.speechSynthesis.speak(message); }
<button onClick="speakTTS()">Speak</button>
额外优化建议:
不要直接用索引voices[9]指定语音,不同浏览器的语音列表顺序可能不一致,建议通过语音的lang或name属性精准匹配,比如:
// 精准查找en-GB的目标语音 const targetVoice = cachedVoices.find(voice => voice.lang === 'en-GB' && voice.name.includes('George')); if (targetVoice) { message.voice = targetVoice; }
内容的提问来源于stack exchange,提问作者rich
相关产品推荐
相关产品推荐

