html 的 lang 属性仅指定语言种类,无法控制发音人、音色或语速;需用 web speech api 的 speechsynthesis.getvoices() 动态获取并切换系统已安装的语音引擎。

HTML 中用 lang 属性不能指定发音人,只能提示语言种类
很多人以为给 <p lang="zh-CN"></p> 加个属性就能让屏幕朗读器挑“女声”或“男声”,其实不行。lang 只影响语音引擎选哪个语言模型(比如中文普通话 vs 粤语),不控制具体合成音色、语速或发音人。操作系统或读屏软件(如 NVDA、VoiceOver)自己决定用哪个语音,网页无权指定“张三配音员”或“李四TTS引擎”。
常见错误现象:
– 页面写了 lang="zh-CN",但朗读还是英文口音
– 换了不同设备,同一段文字朗读声音差异很大
– 以为加个 voice="female" 就能生效(HTML 标准里根本没这个属性)
真正可控的语音切换:用 Web Speech API 的 speechSynthesis.getVoices()
想在网页里动态列出并切换发音人,必须靠 JavaScript 调用 Web Speech API。它暴露了系统已安装的 TTS 引擎列表,包括名称、语言、是否本地、是否默认等字段。
实操建议:
– 必须等 speechSynthesis.onvoiceschanged 触发后才能调用 getVoices(),否则返回空数组
– 不同浏览器返回的 voice 列表差异大:Chrome 通常返回系统级语音(如 Windows 的“微软晓晓”),Safari 只返回 macOS 内置语音(如 “Ting-Ting”)
– 语音名称(voice.name)不是标准字段,iOS Safari 甚至可能为空,得 fallback 到 voice.lang + voice.voiceURI 组合判断
const utterance = new SpeechSynthesisUtterance("你好");
utterance.voice = speechSynthesis.getVoices().find(v =>
v.lang === "zh-CN" && v.name.includes("XiaoXiao")
);
下拉菜单绑定语音选项时,为什么选中后不生效?
典型问题:渲染了 <select></select>,选项也填了 voice.name,但 onchange 后朗读还是默认音色。原因往往是:
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
– speechSynthesis.getVoices() 返回的是快照,后续新增语音(比如用户刚装了新 TTS 包)不会自动更新,需手动再调一次
– 把 voice 对象存成字符串(如 option.value = voice.name),再取出来时只是个名字,不是可赋值的 voice 实例
– 没清空旧的 utterance,重复调用 speechSynthesis.speak() 会排队,新设置没覆盖上
正确做法:
– 下拉菜单 change 事件里,用当前 value 去 getVoices() 里重新查找匹配的 voice 对象
– 每次 speak 前新建 SpeechSynthesisUtterance,别复用旧实例
– 加个 loading 状态,因为首次调用 getVoices() 可能异步延迟
移动端兼容性差是常态,别硬刚 iOS Safari 的语音限制
iOS Safari 对 Web Speech API 支持极弱:不触发 onvoiceschanged,getVoices() 始终返回空,且不允许网页主动触发语音合成(除非用户手势后一秒内)。这不是 bug,是苹果刻意限制。
这意味着:
– 所有依赖下拉选发音人的功能,在 iPhone 上基本不可用
– 不要试图用 setTimeout 或轮询绕过,iOS 就是不给
– 如果业务强依赖多语音,得降级为:Android 正常支持,iOS 只显示“系统默认朗读”,并隐藏下拉控件
容易被忽略的一点:即使在 Chrome for Android 上,如果用户没在系统设置里启用对应语言的 TTS 引擎(比如只装了英文语音包),getVoices() 也不会返回中文 voice——网页控制不了系统级语音安装状态。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










