web speech api 实现语音播报需满足用户点击触发、https 环境、显式指定 lang(如 'zh-cn')三大条件;必须在 click/touchend 中调用 speak(),首次调用前需用户手势,且每次播放前应 cancel() 防止堆叠。

直接用 Web Speech API 就能实现,不需要引入任何第三方库,但必须满足用户点击触发、HTTPS 环境、语言显式指定这三个硬条件,否则大概率静音或报错 DOMException: The user gesture requirement is not met。
speechSynthesis.speak() 必须在用户点击事件里首次调用
这是最常踩的坑:把 synth.speak(utterance) 放在 window.onload、setTimeout 或页面初始化时自动执行,浏览器会直接拒绝——它只认真实鼠标/触摸点击(click、touchend),不认程序逻辑触发。
正确做法是绑定按钮点击后才构建并播放:
document.querySelector('button').addEventListener('click', () => {
const utterance = new SpeechSynthesisUtterance('你好,世界');
utterance.lang = 'zh-CN'; // 关键
window.speechSynthesis.speak(utterance);
});
- 哪怕只是做个“预加载语音列表”,也得先等一次点击之后再调
getVoices(),否则初始返回空数组 - 移动端 Safari 对点击要求更严,长按、双击、伪元素点击都可能不被识别,建议用原生
<button></button>或带role="button"的<div> <li>如果要做“暂停/继续”,得确保 <code>pause()和resume()也在用户手势上下文中调用(比如再次点击同一按钮) - 始终显式设置
utterance.lang = 'zh-CN',不要依赖自动检测 - 避免写
'zh'或'zh-ch'这类非标准值,浏览器可能忽略 - 如果需要多语言混排(如中英夹杂),可拆成多个
SpeechSynthesisUtterance分别设置lang后依次speak() - 部分系统(如 macOS)中文语音名是
"com.apple.ttsbundle.MeiJia-compact",但无需手动选,lang设对后浏览器会自动匹配
lang 参数不写或写错会导致中文念拼音
Chrome 默认引擎对中文支持不稳定,不设 lang 时可能 fallback 到英文语音引擎,把“你好”读成 “ni hao” 拼音,甚至每个字单字顿读。Firefox 更明显,不加 lang: 'zh-CN' 基本无法正常播中文。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
实操建议:
重复点击播报前必须 cancel(),否则声音堆叠或卡死
连续点两次“播放”,没做清理的话,第一次还没播完,第二次又塞进去,结果就是声音重叠、语速异常、甚至后续完全无响应——因为 speechSynthesis 内部队列满了或状态锁死。
安全写法是每次播放前先清空:
let currentUtterance = null;
function speak(text) {
if (currentUtterance) {
window.speechSynthesis.cancel(); // 必须有
}
currentUtterance = new SpeechSynthesisUtterance(text);
currentUtterance.lang = 'zh-CN';
window.speechSynthesis.speak(currentUtterance);
}
-
cancel()不仅清当前,还会清整个待播队列,所以放心调 - 不要只靠
end事件来清理,因为用户可能中途点停,事件未必触发 - 如果想支持“暂停”,注意
pause()后不能直接speak(),得先resume();而cancel()后必须新建Utterance
真正麻烦的不是写几行代码,而是浏览器策略和系统语音引擎的隐性耦合:HTTPS 是硬门槛,移动端要额外处理解锁音频上下文,某些 Linux 桌面环境甚至默认没装中文语音包——这些不会报错,只会静音。上线前务必在目标设备真机验证,别只信开发机 Chrome。










