☰
VueUse useSpeechRecognition:在 Vue 3 中响应式封装 Web 语音识别 API
2026/10/6 2:37:16 网站建设 项目流程
  • 前端

【免费下载链接】vueuse

Collection of essential Vue Composition Utilities for Vue 3

项目地址:https://gitcode.com/gh_mirrors/vu/vueuse
点击查看免费下载

导读

useSpeechRecognition是 VueUse 提供的一个响应式组合式函数,它将浏览器原生的 SpeechRecognition,并结合 核心实现源码、类型定义、在线演示 与 测试用例,完整讲解其 API 形态、配置选项、底层工作原理与实战写法,读完即可在自己的 Vue 3 项目中接入语音识别能力。


一、功能定位与适用场景

SpeechRecognition API 允许网页将用户的语音实时转录为文本,但由于该 API 长期未进入稳定规范,各浏览器实现差异较大(Chrome 系浏览器支持SpeechRecognition或带前缀的webkitSpeechRecognition,部分浏览器完全不支持)。VueUse 的useSpeechRecognition正是为抹平这一差异而设计:

  • 统一能力检测:自动探测window.SpeechRecognition或window.webkitSpeechRecognition,并通过isSupported暴露支持状态;
  • 响应式状态:将isListening、isFinal、result、confidence、error等回调结果转为 Vue 的 shallowRef,可直接在模板与组合式逻辑中绑定;
  • 生命周期自动管理:组件卸载时自动停止识别,避免资源泄漏。

该函数归类于 VueUse 的Sensors(传感器)类别,与useBattery、useGeolocation等浏览器能力封装同属一个体系,通过 core 包入口 导出。

浏览器兼容性提示:语音识别能力高度依赖浏览器与语音服务可用性,正式发布前建议通过isSupported做降级处理,具体支持矩阵可参考 caniuse 中SpeechRecognition相关条目。


二、快速开始:最小可用示例

参考文档给出的最小用法如下:

import { useSpeechRecognition } from '@vueuse/core' const { isSupported, isListening, isFinal, result, confidence, start, stop, } = useSpeechRecognition()

配合模板即可实现“点击开始/停止、实时显示转录文本”的最简交互:

<template> <div> <p v-if="!isSupported">当前浏览器不支持 SpeechRecognition</p> <template v-else> <button @click="isListening ? stop() : start()"> {{ isListening ? '停止' : '开始说话' }} </button> <p>识别结果:{{ result }}</p> <p v-if="isFinal">本轮已结束</p> </template> </div> </template>

这段代码中所有返回值都来自useSpeechRecognition()的解构,其中result、isFinal等是响应式引用,会随语音识别事件的到来自动更新,无需手动维护回调。


三、返回对象全解析

根据 index.ts 的返回值定义 与 类型声明(UseSpeechRecognitionReturn),完整返回对象如下:

属性类型说明
isSupportedComputedRef<boolean>当前环境是否支持语音识别(来自Supportable基接口)
isListeningShallowRef<boolean>是否正在监听语音
isFinalReadonly<ShallowRef<boolean>>最新一条结果是否为最终结果(非临时结果)
recognitionSpeechRecognition \| undefined底层识别器实例,可用于设置 grammars 等额外配置
resultReadonly<ShallowRef<string>>最新识别的转录文本
confidenceReadonly<ShallowRef<number>>最新结果的置信度,取值区间 0~1
errorShallowRef<SpeechRecognitionErrorEvent \| Error \| undefined>最近一次错误事件或异常对象
toggle(value?: boolean) => void切换监听状态,可显式传入布尔值
start() => void开始识别
stop() => void停止识别

几个需要重点理解的状态:

confidence(置信度):参考文档特别指出,该 ref 追踪的是“最新结果”的置信度,数值范围 0~1,对应 Web API 中SpeechRecognitionAlternative.confidence。置信度越高表示识别引擎对结果越有把握,可用于过滤低质量识别(例如低于 0.5 的结果提示用户重说)。其默认初始值为 0,见 index.ts#L77。

isFinal与result的配合:当interimResults: true时,识别过程中会不断产生临时结果,此时isFinal为false;当一段语音结束、产生最终结果时isFinal变为true。因此一个常见的模式是:只把isFinal === true时的result提交到业务逻辑,避免把中间过程的不稳定文本当真。

error:既可能是原生SpeechRecognitionErrorEvent(含error码与message),也可能是底层start()/stop()调用抛出的普通Error(见 index.ts#L151-L153)。


四、配置选项(Options)

参考文档明确指出:以下选项的默认值会直接透传给原生SpeechRecognition实例。默认配置示例如下:

import { useSpeechRecognition } from '@vueuse/core' useSpeechRecognition({ lang: 'en-US', interimResults: true, continuous: true, })

完整选项定义见 UseSpeechRecognitionOptions,整理如下:

选项类型默认值说明
continuousbooleantrue是否连续返回多轮识别结果,还是只返回单条结果(对应原生continuous)
interimResultsbooleantrue是否返回尚未定稿的临时结果(对应原生interimResults)
langMaybeRefOrGetter<string>'en-US'识别语言,支持传入 ref/getter 实现响应式切换(对应原生lang)
maxAlternativesnumber1每条结果最多返回几个候选,对应原生maxAlternatives
windowWindowdefaultWindow自定义window实例(来自ConfigurableWindow),用于 iframe 或测试环境注入

关于各选项在源码中的落地,可见 index.ts#L65-L71 的解构默认值,以及 index.ts#L105-L108 中将这些值写入识别器实例的代码:

const { interimResults = true, continuous = true, maxAlternatives = 1, window = defaultWindow, } = options const lang = toRef(options.lang || 'en-US') // ... recognition.continuous = continuous recognition.interimResults = interimResults recognition.lang = toValue(lang) recognition.maxAlternatives = maxAlternatives

lang的响应式特性

lang是五个选项中唯一支持MaybeRefOrGetter(即string/Ref/Getter)的类型。源码用toRef将其规范化后,通过watch(lang, ...)监听:仅在未监听语音时才把新语言写入识别器(见 index.ts#L115-L118)。这是有意的设计——语音识别进行中修改语言会破坏当前会话,因此需要先stop()再切换语言,下一次start()即使用新语言。

watch(lang, (lang) => { if (recognition && !isListening.value) recognition.lang = lang })

window的可注入性

window选项继承自 ConfigurableWindow 接口,这在 VueUse 中是通用的测试与隔离手段。默认取defaultWindow(客户端环境下即window,见 _configurable.ts#L39)。测试文件正是利用这一点注入 Mock 实例(详见下文“测试验证”)。


五、源码级原理:从调用到事件的完整链路

useSpeechRecognition的实现思路非常清晰:以 Vue 的响应式状态为“数据中枢”,用原生 API 的事件回调驱动这些状态,再用watch把状态的改变反向翻译为对原生 API 的调用。全流程如下:

1. 能力检测(isSupported)

const SpeechRecognition = window && (window.SpeechRecognition || window.webkitSpeechRecognition) const isSupported = useSupported(() => SpeechRecognition)

通过 useSupported 将检测结果包装为计算属性,同时兼容带webkit前缀的实现。isSupported继承自Supportable接口(见 core 类型定义),是整个函数的“能力开关”。

2. 实例创建与初始化

if (isSupported.value) { recognition = new SpeechRecognition() as SpeechRecognition recognition.continuous = continuous recognition.interimResults = interimResults recognition.lang = toValue(lang) recognition.maxAlternatives = maxAlternatives }

仅在支持时才创建实例,避免在不支持的浏览器上抛错。

3. 事件回调 → 响应式状态

四个关键回调把原生事件翻译为 ref 更新(index.ts#L110-L137):

  • onstart:置isListening = true、重置isFinal = false;
  • onresult:取event.results[event.resultIndex]的首个候选,解构出transcript与confidence,分别写入result、confidence,isFinal由currentResult.isFinal决定,同时清空error;
  • onerror:把SpeechRecognitionErrorEvent写入error;
  • onend:置isListening = false,并恢复recognition.lang为当前lang值。

4. 响应式状态 → 原生调用(反向联动)

watch(isListening, (newValue, oldValue) => { if (newValue === oldValue) return try { if (newValue) recognition!.start() else recognition!.stop() } catch (err) { error.value = err as unknown as Error } })

当isListening变化时触发start()/stop(),并把可能抛出的异常捕获到error。这意味着你不需要直接调用recognition.start()——只需修改isListening(或调用start/stop/toggle这三个内部会改动isListening的函数)即可驱动底层,这正是start/stop实现如此简洁的原因(index.ts#L82-L97):

const start = () => { isListening.value = true } const stop = () => { isListening.value = false } const toggle = (value = !isListening.value) => { if (value) start() else stop() }

5. 自动清理

tryOnScopeDispose(() => { stop() })

组件卸载(或副作用作用域销毁)时自动停止识别,与 VueUse 其他组合式函数保持一致。

6. 完整类型支撑

由于 SpeechRecognition 属于实验性 API,仓库在 types.ts 中提供了完整的 TypeScript 类型补全,包括SpeechRecognition接口、事件映射SpeechRecognitionEventMap,以及错误码联合类型:

export type SpeechRecognitionErrorCode = | 'aborted' | 'audio-capture' | 'bad-grammar' | 'language-not-supported' | 'network' | 'no-speech' | 'not-allowed' | 'service-not-allowed'

这些错误码恰好是你在处理error状态时可以用来做分支提示的枚举,例如'not-allowed'表示用户拒绝了麦克风权限、'network'表示网络错误等。


六、实战进阶:颜色口令识别(官方 Demo 拆解)

官方演示 demo.vue 是一个很好的综合示例:它利用JSGF 语法(SpeechGrammarList)限制识别词表,实现“说颜色名 → 界面变色”的交互。核心逻辑如下:

const colors = ['aqua', 'azure', 'beige', /* ... */] const grammar = `#JSGF V1.0; grammar colors; public <color> = ${colors.join(' | ')} ;` const speech = useSpeechRecognition({ lang, continuous: true, }) if (speech.isSupported.value) { // 浏览器存在前缀差异时做兼容 const SpeechGrammarList = window.SpeechGrammarList || window.webkitSpeechGrammarList const speechRecognitionList = new SpeechGrammarList() speechRecognitionList.addFromString(grammar, 1) speech.recognition!.grammars = speechRecognitionList // 监听转录结果,匹配颜色词 watch(speech.result, () => { for (const i of speech.result.value.toLowerCase().split(' ').reverse()) { if (colors.includes(i)) { color.value = i break } } }) }

要点提炼:

  1. 自定义语法:通过speech.recognition!.grammars直接操作底层实例(recognition暴露出来正是为了这类扩展场景),addFromString(grammar, 1)中的第二个参数是该语法的权重;
  2. 语言实时切换:lang用shallowRef('en-US')传入,配合模板中的单选按钮在en-US/fr/es间切换,切换后需重新开始识别才生效(Demo 中通过isListening联动更新已选语言文案);
  3. 结果后处理:把result分词、小写化后反向匹配词表,命中即更新 UI——说明result是一个可以被watch的普通响应式值。

七、测试验证:行为被测试锁定的部分

仓库为useSpeechRecognition提供了浏览器环境测试 index.browser.test.ts,它用createMockWindow()注入一个MockSpeechRecognition类来模拟原生 API,验证了以下行为:

  • 函数可被正常定义与导出;
  • confidence初始值为0;
  • 触发onresult事件后,result更新为'hello world'、confidence更新为0.85(同时验证了transcript与confidence的解构取数逻辑);
  • 无window时仍保持返回结构完整:confidence.value === 0、result.value === ''、isListening.value === false,即 SSR / 非浏览器环境下不会抛错,只是能力不可用。

这意味着:如果你需要在自己的项目中为这个函数编写单元测试,同样可以借助window选项注入 mock,而不必依赖真实麦克风。


八、使用建议与注意事项

  1. 先检测后使用:模板中务必先渲染isSupported为false的降级 UI(如 Demo 中提示“Your browser does not support SpeechRecognition API”);
  2. 权限与安全:识别前浏览器会请求麦克风权限,error为'not-allowed'时应引导用户开启权限;语音数据由浏览器/语音服务处理,涉及隐私场景需在页面内明示;
  3. 语言切换需先停止:由于watch(lang)只在!isListening时生效,切换lang前应先stop();
  4. 区分临时与最终结果:业务上一般以isFinal === true为准,避免把识别过程中的中间文本提交;
  5. 置信度阈值:confidence在 0~1 之间,可结合场景设置阈值过滤低质量识别;
  6. 生命周期:tryOnScopeDispose保证组件卸载自动停止,无需手动清理,但长时间页面建议在不需要时显式stop()以节省资源。

小结

useSpeechRecognition用约 170 行代码,把实验性强、回调密集的 Web Speech API 封装成了“解构即用、状态响应式、生命周期自管理”的 Vue 组合式函数。本文涉及的关键文件均可继续深入研读:官方参考文档、核心实现、类型定义、演示源码 与 测试用例。若想了解其作为 Sensors 类函数的通用模式,可对比 useSupported 与 可配置 window 约定。

  • 前端

【免费下载链接】vueuse

Collection of essential Vue Composition Utilities for Vue 3

项目地址:https://gitcode.com/gh_mirrors/vu/vueuse
点击查看免费下载
上一篇:一条命令永久关闭 Windows Defender:defender-control 完整操作指南(附恢复方案)
下一篇:免费开源的 diff-pdf:快速对比两份 PDF 文件的完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询