SpeechRecognition 仅 Chromium 浏览器原生支持,Safari 不支持、Firefox 实验性禁用;需检测全局对象、设 lang=zh-CN、区分 isFinal 处理结果、用 stop()+end 事件协同控制流程。

Web Speech API 的 SpeechRecognition 在 Chrome 里能用,但别在 Safari 或 Firefox 直接试
它目前只有 Chromium 内核浏览器(Chrome、Edge、新版 Opera)原生支持 SpeechRecognition,Safari 完全没实现,Firefox 仅实验性支持且默认禁用。如果你在非 Chrome 环境下看到 ReferenceError: SpeechRecognition is not defined,不是代码写错了,是浏览器不认这个构造函数。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 务必先检测全局对象:
if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) - 优先用
window.SpeechRecognition || window.webkitSpeechRecognition兼容旧版 Chrome - 别依赖
navigator.mediaDevices.getUserMedia自动触发——语音识别需用户显式点击按钮启动,否则多数浏览器会静默拒绝麦克风访问 - 首次使用时,浏览器弹出的麦克风权限提示不能跳过;若用户点“阻止”,后续调用
recognition.start()会触发error事件,event.error值为not-allowed
recognition.interimResults = true 是实时显示的关键,但别误以为它是“最终结果”
设为 true 后,识别过程中会多次触发 result 事件,每次返回的 event.results[i] 中,isFinal: false 的条目是暂定稿(比如把“导入数据”听成“导如数据”),isFinal: true 才是确认后的文本。很多人直接取 event.results[0][0].transcript 并覆盖输入框,导致界面上反复闪动、错乱。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用一个
let finalTranscript = ''累加所有isFinal: true的片段 - 用另一个
let interimTranscript = ''单独存当前未确认内容,只在输入框末尾追加(比如用input.value = finalTranscript + interimTranscript) - 每次
result事件中遍历event.results,按isFinal分流处理,别只看第一个 -
recognition.maxAlternatives = 1就够用,设高了反而拖慢响应,且多数场景不需要多候选
识别不准?大概率是没设对 recognition.lang 或网络延迟干扰了音频流
默认语言是 en-US,中文必须显式设为 zh-CN,否则即使你讲普通话,识别引擎也按英文音素建模,错误率陡增。另外,SpeechRecognition 是云端服务(Chrome 走 Google 服务器),弱网或高延迟下会出现“开始识别 → 卡住 → 报 no-speech”或“识别结果严重滞后”。这不是前端代码问题,但会影响体验判断。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 初始化后立刻赋值:
recognition.lang = 'zh-CN',不要依赖用户系统语言 - 避免在
start()后立刻stop():哪怕只隔 100ms,也可能中断音频上传,触发aborted错误 - 监听
error事件,区分处理:no-speech(安静太久)、audio-capture(麦克风被占)、network(请求失败)——不同错误该给用户不同提示 - 移动端注意:部分 Android Chrome 版本对后台标签页的音频采集有策略限制,切到其他 App 后识别会自动终止
语音识别结束不等于任务完成,end 和 result 事件的触发时机容易混淆
recognition.end() 只是告诉引擎“停止接收新音频”,已上传的音频仍在识别中,所以 result 事件可能在 end 之后才来。而 recognition.stop() 是强行中止整个流程,已上传但未返回的结果会被丢弃。如果用户点“停止”按钮后立刻清空输入框,又刚好遇到 result 晚到,就会丢失最后几秒的识别内容。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用户点击“停止”时调用
recognition.stop(),并设一个标志位(如isStopping = true) - 在
result回调开头加判断:if (isStopping) return,避免处理已废弃的结果 - 真正清理界面逻辑(如清空 input、重置按钮状态)放在
end事件里,而不是stop()调用后立即执行 - 若需连续识别,别在
end里自动start()——应等用户再次点击,否则可能因权限或状态异常反复失败
语音识别不是“打开就灵”,真实项目里最常卡住的地方是权限流转、事件时序和错误兜底。浏览器兼容性、网络抖动、用户操作节奏,三者叠加起来,比写对 SpeechRecognition 构造函数难得多。


















