You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

语音合成:如何切换语音性别?

解决基于Web Speech API的文本转语音多性别朗读问题

我刚好用Web Speech API做过类似的项目,你的问题都是实际开发里很常见的坑,我来一步步给你捋清楚:

1. 语音列表的性别标识与美式英语男声缺失问题

首先得明确:Web Speech API的SpeechSynthesisVoice对象没有标准化的gender属性——这是W3C规范里的坑,不同浏览器厂商的实现差异很大。比如Chrome确实会在部分语音名称里加Male/Female标识,但这不是统一规则,Firefox或者Edge的命名逻辑可能完全不一样。

至于你找不到美式英语男声,大概率不是浏览器的问题,而是你的系统没安装对应的语音包。Chrome是直接调用操作系统的TTS语音的,比如Windows系统,你需要去「设置 → 时间和语言 → 语音」里手动添加美式英语的男声(比如Microsoft David Desktop);如果是Mac,去「系统设置 → 辅助功能 → 语音」里添加对应的语音。添加完成后,刷新页面再调用getVoices()就能看到了。

2. 如何判断设备上的语音是否可用?

其实window.speechSynthesis.getVoices()返回的列表,已经是当前设备已启用且可被浏览器调用的语音了。不过这里有个异步坑:第一次页面加载时直接调用getVoices()可能返回空数组,因为浏览器还没完成语音列表的加载。

正确的做法是监听voiceschanged事件,确保拿到完整的可用语音列表:

let voices = [];

// 监听语音列表加载完成事件
window.speechSynthesis.onvoiceschanged = () => {
  voices = window.speechSynthesis.getVoices();
  // 这里可以开始遍历查找需要的语音
};

// 初始化时主动触发一次(兼容部分浏览器)
if (window.speechSynthesis.getVoices().length > 0) {
  voices = window.speechSynthesis.getVoices();
}

之后你就可以遍历voices数组,通过名称、语言代码(比如en-US)来筛选你需要的语音,比如找美式英语男声:

const maleEnUSVoice = voices.find(voice => 
  voice.lang === 'en-US' && voice.name.includes('Male')
);

3. 实现跨浏览器通用的男女语音方案

很遗憾,Web Speech API本身没办法让你随应用下载语音包——它完全依赖操作系统自带的语音资源,这也是跨设备兼容的最大痛点。如果想要全设备(不管什么浏览器、什么系统)都能稳定使用指定的男女语音,有两个可行方案:

  • 方案一:使用云端TTS服务
    调用第三方的文本转语音API,传入文本和指定的语音性别/语种,API会返回音频文件(比如MP3),然后你用HTML5的<audio>标签播放即可。这种方式完全不依赖系统语音,跨浏览器跨设备都能保证一致的效果。

  • 方案二:嵌入本地语音包
    如果你不想依赖云端服务,可以把开源的TTS引擎(比如eSpeak、MaryTTS)的语音包打包到你的Web应用里,通过JavaScript调用本地的TTS逻辑生成音频。不过这种方式会增加应用的体积,而且需要处理不同浏览器的音频解码兼容性,实现起来复杂度较高。

总结一下:如果追求快速实现跨设备兼容,云端TTS是最优解;如果必须离线使用,那就得考虑嵌入本地语音包的方案。

内容的提问来源于stack exchange,提问作者Coco

火山引擎 最新活动