语音交互正变得越来越普及,从智能音箱到手机助手,用户已经习惯了用说话代替打字。其实在浏览器端,JavaScript也提供了原生的语音能力:SpeechRecognition接口负责把用户说的话转换成文字,speechSynthesis接口负责把文字朗读出来。这两个接口合称Web Speech API,无需引入任何第三方SDK,就能让网页具备听和说的能力。本文将详细讲解它们的用法、配置技巧和兼容性处理。

一、语音识别:SpeechRecognition的基本用法
语音识别的核心对象是SpeechRecognition,不过在Chrome等浏览器中它挂载在webkitSpeechRecognition下,所以实际使用时通常要做一层兼容判断。识别的原理大致是:浏览器把麦克风采集到的音频发送到云端识别服务(Chrome使用Google的识别引擎),再把识别结果回传给页面,因此使用语音识别必须联网。
下面是一段最基础的识别代码,启动后持续监听麦克风,并把识别结果显示到页面上:
// 兼容不同浏览器的构造函数
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
alert('当前浏览器不支持语音识别,请使用Chrome或Edge');
} else {
const recognition = new SpeechRecognition();
recognition.lang = 'zh-CN'; // 识别语言设为中文
recognition.continuous = true; // 持续识别,不会自动停止
recognition.interimResults = true; // 返回临时结果,实现边说边显示
recognition.maxAlternatives = 1; // 每次返回的最佳候选结果数量
recognition.onresult = function (event) {
let finalText = '';
let interimText = '';
for (let i = event.resultIndex; i < event.results.length; i++) {
const result = event.results[i];
if (result.isFinal) {
finalText += result[0].transcript; // 最终确认的结果
} else {
interimText += result[0].transcript; // 临时结果,可能还会变化
}
}
document.getElementById('result').innerText = finalText + interimText;
};
recognition.onerror = function (event) {
console.error('识别出错:', event.error);
};
recognition.start();
}
几个关键参数值得展开说明。lang设置为zh-CN后,识别引擎会按中文发音规则处理音频,中英混合场景可以设置为zh-CN还能勉强识别简单英文单词,但纯英文内容建议切换为en-US。continuous决定是否连续识别,设为false时用户说完一句话,检测到静音后就会自动结束。interimResults开启后能拿到实时变化的临时文本,这是实现打字机效果的关键,不过临时结果的准确率低于最终结果,展示时最好用不同样式区分。
二、识别中断处理与常见坑
实际项目中最大的麻烦是识别会莫名其妙停止。Chrome对连续识别有一分钟左右的时长限制,服务端超时后会触发onend事件。解决办法是在onend里判断是否需要继续,如果用户没有主动点击停止按钮,就重新调用start():
let shouldListen = true; // 用户是否希望继续识别
recognition.onend = function () {
// 非用户主动停止时,自动重启识别
if (shouldListen) {
try {
recognition.start();
} catch (e) {
// start()在已运行状态下会抛异常,需捕获
console.warn('重启识别失败:', e.message);
}
}
};
// 用户点击停止按钮
stopBtn.addEventListener('click', function () {
shouldListen = false;
recognition.stop();
});
除了超时问题,还有几个坑需要提前规避。第一,语音识别必须在HTTPS环境下运行,本地开发时localhost是例外,部署到线上必须配置SSL证书,否则调用getUserMedia和识别接口都会被浏览器拦截。第二,首次调用时会弹出麦克风授权弹窗,用户拒绝后会触发error事件,error类型为not-allowed,此时应给出友好提示引导用户重新授权。第三,频繁调用start和stop可能触发network错误,两次start之间最好间隔几百毫秒。第四,移动端Safari对SpeechRecognition的支持不完整,生产环境务必做好特性检测,提供键盘输入作为降级方案。
三、语音合成:让网页开口说话
语音合成比识别简单得多,window.speechSynthesis对象开箱即用。最简三行代码就能朗读文字:
const utterance = new SpeechSynthesisUtterance('你好,欢迎使用本网页');
utterance.lang = 'zh-CN';
speechSynthesis.speak(utterance);
但要在实际项目中用得好,还需要处理发音人、语速、音量等细节。getVoices()返回系统可用的发音人列表,不同操作系统内置的中文发音人不同,Windows下通常有Huihui、Kangkang等微软发音人,macOS则有婷婷。发音人加载是异步的,首次调用getVoices()可能返回空数组,必须监听voiceschanged事件。下面是一个完整的合成模块:
function speak(text, rate) {
const utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'zh-CN';
utterance.rate = rate || 1; // 语速,0.1到10,1为正常
utterance.pitch = 1; // 音调,0到2
utterance.volume = 1; // 音量,0到1
// 挑选中文发音人,优先选择本地语音
const voices = speechSynthesis.getVoices();
const zhVoice = voices.find(function (v) {
return v.lang.indexOf('zh') === 0 && v.localService;
}) || voices.find(function (v) { return v.lang.indexOf('zh') === 0; });
if (zhVoice) {
utterance.voice = zhVoice;
}
// 监听朗读边界,可用于文字高亮
utterance.onboundary = function (event) {
console.log('当前朗读到字符位置:', event.charIndex);
};
speechSynthesis.cancel(); // 先取消之前的朗读,避免排队堆积
speechSynthesis.speak(utterance);
}
几个实用技巧:朗读长文本时,Chrome存在一个已知bug,超过约15秒的utterance可能中途停止,规避办法是把长文本按句子切分,逐段入队合成。onboundary事件在部分中文发音人上不触发,做文字跟读高亮功能时要有降级方案,比如按字数和语速估算进度。另外调用speak前先执行cancel()可以避免朗读任务无限排队,这是很多开发者踩过的坑。
四、浏览器兼容性与综合建议
兼容性方面,语音合成(speechSynthesis)的支持面较广,Chrome、Edge、Firefox、Safari桌面端和主流移动端都支持。语音识别(SpeechRecognition)则相对受限,Firefox基本不支持,Safari使用自有前缀webkitSpeechRecognition且行为与Chrome有差异,Edge基于Chromium表现与Chrome一致。稳妥的做法是封装一个统一入口,检测能力后再决定是否展示语音按钮。
从工程角度给几点建议:一是把识别结果当作辅助输入而非唯一输入,识别准确率受环境噪音、口音影响明显,配合文本框让用户可修正;二是注意隐私合规,明确告知用户即将使用麦克风,并提供关闭开关;三是识别和合成可以组合使用,构建语音对话机器人——识别拿到用户输入,接口返回应答文本后直接合成朗读,整个链路纯前端即可跑通。掌握这两个接口后,语音搜索、听写工具、无障碍阅读等功能都可以快速落地。
JavaScript语音识别Web Speech API语音合成修改时间:2026-09-11 11:54:41