Vue 可组合项实战:从零构建语音识别功能
一、为什么选择Vue组合式API开发语音识别?
Vue 3的组合式API(Composition API)为复杂功能开发提供了更灵活的组织方式。相比选项式API,组合式API通过setup()函数将逻辑按功能而非选项类型分组,特别适合需要管理多个状态和副作用的场景,如语音识别这类涉及浏览器API调用、状态管理和UI交互的功能。
核心优势:
- 逻辑复用性:通过自定义组合函数(composables)封装语音识别逻辑,可在多个组件中共享
- 类型友好性:与TypeScript深度集成,适合中大型项目
- 响应式系统:利用
ref和reactive精确控制识别状态 - 生命周期明确:通过
onMounted/onUnmounted管理资源
二、技术栈准备
1. 浏览器API依赖
现代浏览器提供的Web Speech API包含两个核心接口:
SpeechRecognition(识别):将语音转为文本SpeechSynthesis(合成):将文本转为语音
注意:目前仅Chrome、Edge、Safari等浏览器支持,需做兼容性检测
2. 开发环境配置
npm init vue@latest vue-speech-democd vue-speech-demonpm install
在vite.config.js中添加TypeScript支持(可选):
export default defineConfig({plugins: [vue()],resolve: {alias: {'@': path.resolve(__dirname, './src')}}})
三、核心组合函数实现
1. 创建useSpeechRecognition.ts
import { ref, onUnmounted } from 'vue'export function useSpeechRecognition() {const recognition = ref<SpeechRecognition | null>(null)const isListening = ref(false)const transcript = ref('')const error = ref<string | null>(null)const initRecognition = () => {const SpeechRecognition = window.SpeechRecognition ||(window as any).webkitSpeechRecognitionif (!SpeechRecognition) {error.value = '浏览器不支持语音识别'return null}const instance = new SpeechRecognition()instance.continuous = trueinstance.interimResults = trueinstance.lang = 'zh-CN' // 中文识别instance.onresult = (event: SpeechRecognitionEvent) => {let interimTranscript = ''let finalTranscript = ''for (let i = event.resultIndex; i < event.results.length; i++) {const transcriptPiece = event.results[i][0].transcriptif (event.results[i].isFinal) {finalTranscript += transcriptPiece + ' '} else {interimTranscript += transcriptPiece}}transcript.value = finalTranscript || interimTranscript}instance.onerror = (event: SpeechRecognitionErrorEvent) => {error.value = `识别错误: ${event.error}`stopListening()}instance.onend = () => {if (isListening.value) {instance.start() // 自动重启(根据需求调整)}}recognition.value = instancereturn instance}const startListening = () => {if (!recognition.value) {initRecognition()}recognition.value?.start()isListening.value = trueerror.value = null}const stopListening = () => {recognition.value?.stop()isListening.value = false}// 组件卸载时清理onUnmounted(() => {stopListening()})return {transcript,isListening,error,startListening,stopListening}}
2. 关键点解析
- 浏览器兼容处理:通过类型断言(
as any)处理不同浏览器前缀 - 状态管理:使用
ref创建响应式变量 - 事件处理:
onresult:处理实时识别结果onerror:捕获异常onend:处理识别结束
- 资源清理:在
onUnmounted中停止识别
四、组件实现与优化
1. 创建SpeechRecognizer.vue
<script setup lang="ts">import { useSpeechRecognition } from './composables/useSpeechRecognition'const {transcript,isListening,error,startListening,stopListening} = useSpeechRecognition()</script><template><div class="speech-container"><div v-if="error" class="error-message">{{ error }}</div><div class="transcript-area">{{ transcript || '等待语音输入...' }}</div><button@click="isListening ? stopListening() : startListening()":disabled="!!error"class="control-btn">{{ isListening ? '停止识别' : '开始识别' }}</button></div></template><style scoped>.speech-container {max-width: 600px;margin: 0 auto;padding: 20px;}.transcript-area {min-height: 100px;border: 1px solid #ddd;padding: 15px;margin: 20px 0;border-radius: 8px;background: #f9f9f9;}.control-btn {padding: 10px 20px;background: #42b983;color: white;border: none;border-radius: 4px;cursor: pointer;}.control-btn:disabled {background: #cccccc;cursor: not-allowed;}.error-message {color: #ff4444;margin-bottom: 15px;}</style>
2. 高级优化技巧
-
语言切换:通过props支持多语言识别
// 在composable中修改export function useSpeechRecognition(lang = 'zh-CN') {// ...instance.lang = lang// ...}
-
识别结果处理:添加结果过滤和格式化
const formatTranscript = (rawText: string) => {return rawText.trim().replace(/\s+/g, ' ') // 去除多余空格.replace(/[。!?]+[,、]*/g, '$& ') // 优化标点}
-
性能优化:添加防抖处理连续识别
```typescript
import { debounce } from ‘lodash-es’
// 在onresult处理中
const processResult = debounce((event) => {
// 处理逻辑
}, 300)
instance.onresult = (event) => {
processResult(event)
}
## 五、部署与测试### 1. 兼容性检测在`main.ts`中添加检测逻辑:```typescriptconst checkSpeechAPI = () => {if (!('SpeechRecognition' in window) &&!('webkitSpeechRecognition' in window)) {alert('当前浏览器不支持语音识别功能,请使用Chrome/Edge/Safari')}}checkSpeechAPI()
2. 测试用例设计
| 测试场景 | 预期结果 |
|---|---|
| 点击开始按钮 | 麦克风权限请求弹出 |
| 正常说话 | 实时显示识别文本 |
| 长时间不说话 | 自动停止识别(根据continuous设置) |
| 切换标签页 | 识别暂停(部分浏览器行为) |
| 不支持浏览器访问 | 显示错误提示 |
六、扩展应用场景
- 语音搜索:结合后端API实现实时搜索
- 语音笔记:将识别结果保存到本地存储
- 无障碍功能:为视障用户提供语音导航
- IoT控制:通过语音指令控制智能家居设备
七、最佳实践总结
- 错误处理:始终捕获
onerror事件并提供用户反馈 - 资源管理:在组件卸载时清理识别实例
- 状态明确:通过
isListening清晰反映当前状态 - 性能考量:对连续识别结果进行适当节流
- 用户体验:提供视觉反馈(如麦克风动画)
通过组合式API开发的语音识别功能,不仅代码结构清晰,而且易于维护和扩展。开发者可以根据实际需求,轻松添加更多功能如语音命令解析、多语言支持等。这种模式特别适合需要复用语音识别逻辑的中大型Vue应用。