直接用 window.speechsynthesis 就能实现,但必须满足用户点击触发、https 环境、显式设置 lang(如 'zh-cn')三大硬条件,否则静音或报错 domexception;还需监听 voiceschanged 确保语音就绪、每次 speak() 前调用 cancel() 防堆叠。

直接用 window.speechSynthesis 就能实现,但不满足三个硬条件——用户点击触发、HTTPS 环境、显式设置 lang——大概率静音或报错 DOMException: The user gesture requirement is not met。
为什么 click 里调用 speak() 还是没声音?
最常见原因是:首次调用 speechSynthesis.speak() 前没经过真实用户手势(click/touchend),或者用了伪事件(如 setTimeout 模拟点击、dispatchEvent 主动派发、长按/双击/伪元素触发)。
- Safari 移动端尤其严格,
<div onclick="speak()"> 或带 <code>role="button"的非原生按钮可能被忽略,优先用<button></button> - 页面加载完就自动调
getVoices(),返回空数组——必须等第一次用户点击后才能拿到可用语音列表 - Chrome/Firefox 在非 HTTPS 页面会静默禁用 API,本地开发用
http://localhost是例外,但http://127.0.0.1或文件协议file://不行 - 必须写完整 BCP 47 标准值,如
'zh-CN',不能写'zh'、'zh-ch'、'Chinese' - 中英混排文本不要塞进同一个
SpeechSynthesisUtterance,拆成多个实例分别设lang后依次speak() - 不用手动匹配语音名(如
"com.apple.ttsbundle.MeiJia-compact"),lang设对浏览器会自动选 - 每次播放前加一句
speechSynthesis.cancel();,哪怕只是防呆 -
pause()和resume()也得在用户手势上下文中调用(比如同一按钮二次点击),否则无效 - 监听
onend或onerror事件时别忘了清理状态,避免currentUtterance滞留内存
lang 参数写错或不写会怎样?
中文基本念成拼音,甚至单字顿读。Firefox 不设 lang: 'zh-CN' 几乎必失败;Chrome 可能 fallback 到英文引擎,把“你好”读成 “ni hao”。
重复点击后声音堆叠、卡死、后续无响应?
因为没在每次 speak() 前调 speechSynthesis.cancel(),导致内部队列积压,甚至满溢后拒绝新请求。
真正容易被忽略的点是:语音列表异步加载 + 用户手势依赖 + 多次调用 cancel 的配合,三者缺一不可。光写对语法但没串起这个执行链路,照样播不出声。











