共计 3297 个字符,预计需要花费 9 分钟才能阅读完成。
背景与痛点
在开发需要语音合成功能的 Web 应用时,我们通常会使用在线 TTS 服务,比如 Google Cloud Text-to-Speech、Azure Cognitive Services 等。这些服务虽然功能强大,但存在几个明显的痛点:

- 必须联网才能使用,在弱网或无网络环境下无法工作
- 通常需要 API 密钥和付费,增加了使用门槛
- 存在隐私风险,需要将文本内容发送到第三方服务器
技术对比
目前主流的语音合成方案主要有以下几种:
- 在线 TTS 服务(如 Google Cloud TTS、Azure TTS)
- 优点:语音质量高,支持多种语言和声音
-
缺点:需要网络连接,通常收费
-
本地 TTS 引擎(如 eSpeak、Festival)
- 优点:完全离线
-
缺点:需要安装额外软件,集成复杂
-
Web Speech API(浏览器内置 TTS)
- 优点:无需安装,完全离线(Chrome),免费
- 缺点:语音质量一般,浏览器支持有限
核心实现
Chrome 浏览器内置的 TTS 功能通过 Web Speech API 的 SpeechSynthesis 接口提供。下面我们来看具体实现方法。
基础使用
// 检查浏览器是否支持 SpeechSynthesis
if ('speechSynthesis' in window) {
// 创建一个语音实例
const utterance = new SpeechSynthesisUtterance('你好,这是一个测试');
// 设置语音参数
utterance.rate = 1.0; // 语速 (0.1-10)
utterance.pitch = 1.0; // 音调 (0-2)
utterance.volume = 1.0; // 音量 (0-1)
// 开始语音合成
speechSynthesis.speak(utterance);
} else {console.log('您的浏览器不支持语音合成');
}
选择语音
Chrome 通常内置了多种语音,我们可以让用户选择:
// 获取可用语音列表
const voices = speechSynthesis.getVoices();
// 中文语音通常以 "Google 普通话" 开头
const chineseVoice = voices.find(voice =>
voice.name.includes('Chinese') || voice.lang.includes('zh')
);
if (chineseVoice) {const utterance = new SpeechSynthesisUtterance('中文测试');
utterance.voice = chineseVoice;
speechSynthesis.speak(utterance);
}
注意:语音列表是异步加载的,通常需要监听 voiceschanged 事件:
speechSynthesis.onvoiceschanged = function() {const voices = speechSynthesis.getVoices();
// 现在可以使用语音列表了
};
完整示例
下面是一个功能更完整的实现,包含语音选择、参数控制和状态反馈:
class TTSService {constructor() {this.voices = [];
this.isSpeaking = false;
// 初始化语音列表
this.initVoices();}
initVoices() {
// 直接尝试获取语音
this.voices = speechSynthesis.getVoices();
// 如果还没有加载完成,监听事件
if (this.voices.length === 0) {speechSynthesis.onvoiceschanged = () => {this.voices = speechSynthesis.getVoices();
speechSynthesis.onvoiceschanged = null;
};
}
}
speak(text, options = {}) {if (!this.voices.length) {console.warn('No voices available');
return;
}
const utterance = new SpeechSynthesisUtterance(text);
// 应用选项
utterance.rate = options.rate || 1.0;
utterance.pitch = options.pitch || 1.0;
utterance.volume = options.volume || 1.0;
// 自动选择中文语音
const chineseVoice = this.voices.find(v =>
v.lang.includes('zh') || v.name.includes('Chinese')
) || this.voices[0];
utterance.voice = chineseVoice;
// 事件监听
utterance.onstart = () => {
this.isSpeaking = true;
console.log('开始朗读');
};
utterance.onend = () => {
this.isSpeaking = false;
console.log('朗读结束');
};
utterance.onerror = (event) => {
this.isSpeaking = false;
console.error('朗读出错:', event.error);
};
// 开始朗读
speechSynthesis.speak(utterance);
}
stop() {speechSynthesis.cancel();
this.isSpeaking = false;
}
}
// 使用示例
const tts = new TTSService();
tts.speak('这是一个离线语音合成示例');
性能考量
经过测试,Chrome 内置 TTS 在不同文本长度下的表现如下:
- 短文本(<100 字)
- 几乎即时响应
-
内存占用可以忽略不计
-
中等文本(100-1000 字)
- 合成时间在 1 - 3 秒
-
内存占用约 10-50MB
-
长文本(>1000 字)
- 合成时间可能达到 5 -10 秒
- 内存占用可能超过 100MB
- 建议拆分成多个片段处理
避坑指南
常见问题
- 语音列表为空
-
解决方案:确保监听了
voiceschanged事件 -
语音不连贯
- 原因:长文本合成质量差
-
解决方案:将文本分成短句,适当添加停顿
-
跨浏览器兼容性
- Chrome/Edge 支持良好
- Firefox 需要联网
- Safari 支持有限
优化技巧
-
预加载语音
// 在应用启动时预加载 const utterance = new SpeechSynthesisUtterance(''); speechSynthesis.speak(utterance); speechSynthesis.cancel(); // 立即取消 -
添加自然停顿
const text = '第一句。第二句。'; const sentences = text.split(/[。!?]/g); sentences.forEach((sentence, i) => {setTimeout(() => {if (sentence.trim()) {tts.speak(sentence.trim()); } }, i * 1500); // 每句间隔 1.5 秒 }); -
错误处理
try {speechSynthesis.speak(utterance); } catch (error) {console.error('语音合成失败:', error); // 降级方案 if (navigator.onLine) {// 尝试使用在线 TTS} else {// 显示文本} }
实践建议
- 适用场景
- 离线 Web 应用(PWA)
- 内部工具
-
低要求的语音提示
-
不适用场景
- 需要高质量语音
- 复杂语音控制
-
大规模商用
-
扩展方向
- 结合 Web Audio API 进行音效处理
- 开发语音插件系统
- 实现语音队列管理
结语
Chrome 内置的 TTS 功能为 Web 开发者提供了一种简单、免费的离线语音解决方案。虽然它的语音质量无法与专业 TTS 服务相比,但在网络受限场景下非常有用。通过合理的使用和优化,它可以满足基本的语音合成需求。
建议读者实际尝试本文的代码示例,并根据自己的需求进行调整。如果你有更好的优化建议或使用经验,欢迎分享讨论。
