必须用特性检测获取构造函数:const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;若不存在则降级为文本输入,并提示不支持;实例化后须立即设lang(如'zh-CN'),start()必须由用户手势(如click)在HTTPS/localhost触发,onresult中需用Array.from(event.results)提取final结果。

直接用 SpeechRecognition 就能实现,但浏览器不统一、权限没弹出、结果拿不到——这三类问题占了实际落地的 80% 以上。
怎么创建兼容的 SpeechRecognition 实例
Chrome/Edge 用 webkitSpeechRecognition,Firefox 用 SpeechRecognition(部分版本需开启 media.webspeech.recognition.enable),Safari 不支持。不能硬写 new SpeechRecognition(),否则在 Chrome 下直接报 ReferenceError。
- 必须用特性检测:
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; - 检测实例是否可用:
if (!SpeechRecognition) { console.error('当前浏览器不支持语音识别'); } - 创建后立即设
lang,否则默认是en-us,中文识别率暴跌——哪怕用户系统语言是中文
为什么 start() 后没反应,也不弹麦克风授权
不是代码卡住,而是 start() 必须由**用户手势触发**(如 click、tap),且页面必须是 HTTPS 或 localhost。在控制台直接调用、或 onload 里自动 start,浏览器会静默拒绝,连错误都不抛。
- 按钮绑定 click 是最稳妥方式:
document.getElementById('btn').addEventListener('click', () => recognition.start()); - HTTP 环境下(非 localhost)会直接失败,
onerror触发时event.error是not-allowed - 如果用户点了“禁止”,之后再调
start()会进onend,但不会进onerror,得靠onend里检查状态补提示
如何正确提取 onresult 中的文本
event.results 是只读的 SpeechRecognitionResultList,不是普通数组,不能直接用 map 或 forEach;而且每个 result 是一组备选识别项,[0] 才是置信度最高的主结果。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
立即学习“前端免费学习笔记(深入)”;
- 必须转成数组才能操作:
Array.from(event.results) - 每个
result是SpeechRecognitionResult,它本身是个类数组,取第 0 项:result[0].transcript - 启用
interimresults: true后,中间结果可能被后续覆盖,最终结果才稳定——别把interim当最终输出存库 - 示例提取逻辑:
const finalTranscript = Array.from(event.results).filter(r => r.isFinal).map(r => r[0].transcript).join('');
continuous 和 interimresults 设错会导致什么
这两个布尔值看着简单,但组合起来行为差异极大,尤其影响内存和 UI 反馈节奏:
-
continuous: false+interimresults: true:说一句停一句,每句内有实时字幕,适合短指令场景(如“打开设置”) -
continuous: true+interimresults: true:一直听,结果流式吐出,但event.results.length会持续增长,不手动清理容易 OOM -
continuous: true时,stop()不会立刻终止识别,要等当前音频帧处理完,所以 UI 上“停止”按钮反馈要有延迟感 - 移动端 Safari 完全不支持
continuous,设了也当没设——得降级为单次识别 + 手动重连
最易被忽略的是:识别器实例不能复用多次 start() 后不 stop(),下次 start() 会触发 onend 并清空内部缓冲,导致结果丢失。每次识别周期必须显式管理生命周期,而不是靠事件自动收尾。


















