eagleye

Quasar + TypeScript 企业级语音识别组件开发指南

Quasar + TypeScript 企业级语音识别组件开发指南

一、组件概述

本文档介绍基于Quasar 框架Vue 3 组合式 API开发的企业级语音识别组件SpeechRecognitionComponent,集成浏览器原生语音识别 API,支持实时语音转文本、状态管理、错误处理及语音指令扩展。组件遵循 TypeScript 类型安全规范,确保代码健壮性和可维护性,适用于智能客服、语音输入、会议记录等企业级场景。

二、核心功能

功能

描述

实时语音监听

支持开始/停止/暂停语音监听,实时反馈识别状态(监听中/已暂停/未启动)

结果分层显示

区分最终识别结果(稳定文本)和临时结果(实时草稿),提升用户体验

全类型安全

定义完整 TypeScript 接口(如SpeechRecognitionEvent),避免any类型

错误处理与兼容性

检测浏览器支持性,处理识别错误(如无权限、网络异常)并显示友好提示

语音指令扩展

支持自定义语音指令(如“清空内容”“停止监听”),实现语音交互逻辑

三、完整组件实现

3.1 模板(Template)

<template>

<q-card class="speech-recognition-card q-pa-md">

<!-- 标题区域 -->

<q-card-section class="q-pa-none">

<div class="text-h6">语音识别模块</div>

</q-card-section>

<!-- 状态与控制区域 -->

<q-card-section class="q-pa-none q-mt-md">

<!-- 状态指示器 -->

<div class="row items-center q-mb-md">

<q-icon

name="record_voice_over"

size="sm"

:color="isListening ? 'red' : 'grey'"

class="q-mr-sm"

/>

<span class="text-caption">状态: {{ recognitionState }}</span>

</div>

<!-- 控制按钮组 -->

<div class="row q-gutter-sm">

<q-btn

color="primary"

icon="keyboard_voice"

label="开始监听"

:disable="isListening"

@click="startRecognition"

/>

<q-btn

color="negative"

icon="stop"

label="停止监听"

:disable="!isListening"

@click="stopRecognition"

/>

<q-btn

color="warning"

icon="pause"

label="暂停监听"

:disable="!isListening || isPaused"

@click="pauseRecognition"

/>

</div>

<!-- 识别结果显示 -->

<q-input

v-model="transcript"

class="q-mt-md"

type="textarea"

filled

autogrow

label="识别结果"

readonly

rows="4"

/>

<!-- 临时结果提示 -->

<div v-if="interimTranscript" class="q-mt-xs text-caption text-italic text-grey-6">

正在输入: {{ interimTranscript }}

</div>

</q-card-section>

<!-- 错误提示区域 -->

<q-card-section v-if="errorMessage" class="q-pa-none q-mt-md">

<q-banner dense class="bg-negative text-white">

{{ errorMessage }}

</q-banner>

</q-card-section>

</q-card>

</template>

3.2 脚本(Script)

<script setup lang="ts">

import { ref, computed, onMounted, onUnmounted } from 'vue';

// ============================ 类型定义 ============================

/** 语音识别结果事件接口 */

interface SpeechRecognitionEvent extends Event {

resultIndex: number; // 结果起始索引

results: SpeechRecognitionResultList; // 识别结果列表

}

/** 语音识别错误事件接口 */

interface SpeechRecognitionErrorEvent extends Event {

error: string; // 错误类型(如 "not-allowed" "no-speech")

message?: string; // 错误描述(可选)

}

/** 语音识别核心接口(封装浏览器原生 API) */

interface SpeechRecognition extends EventTarget {

continuous: boolean; // 是否持续监听(true: 多轮识别,false: 单句识别)

interimResults: boolean; // 是否返回临时结果(true: 实时草稿,false: 仅最终结果)

lang: string; // 识别语言(如 "zh-CN" "en-US")

start(): void; // 开始监听

stop(): void; // 停止监听

abort(): void; // 终止监听(不返回结果)

onresult: ((event: SpeechRecognitionEvent) => void) | null; // 结果回调

onerror: ((event: SpeechRecognitionErrorEvent) => void) | null; // 错误回调

onstart: (() => void) | null; // 开始监听回调

onend: (() => void) | null; // 结束监听回调

onnomatch: (() => void) | null; // 无匹配结果回调

}

// 扩展 Window 接口,适配浏览器前缀(如 webkitSpeechRecognition)

declare global {

interface Window {

SpeechRecognition: new () => SpeechRecognition;

webkitSpeechRecognition: new () => SpeechRecognition;

}

}

// ============================ 响应式状态 ============================

const transcript = ref<string>(''); // 最终识别结果(稳定文本)

const interimTranscript = ref<string>(''); // 临时识别结果(实时草稿)

const isListening = ref<boolean>(false); // 是否正在监听

const isPaused = ref<boolean>(false); // 是否暂停监听

const errorMessage = ref<string>(''); // 错误信息

const recognition = ref<SpeechRecognition | null>(null); // 语音识别实例

// ============================ 计算属性 ============================

/** 识别状态文本(监听中/已暂停/未启动) */

const recognitionState = computed<string>(() => {

if (!isListening.value) return '未启动';

if (isPaused.value) return '已暂停';

return '监听中';

});

// ============================ 核心逻辑 ============================

/** 初始化语音识别实例 */

const initSpeechRecognition = (): void => {

// 检测浏览器支持性(兼容 Chrome/WebKit 内核)

const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;

if (!SpeechRecognition) {

errorMessage.value = '您的浏览器不支持语音识别 API(推荐使用 Chrome 或 Edge)';

return;

}

// 创建识别实例并配置参数

recognition.value = new SpeechRecognition();

recognition.value.continuous = true; // 持续监听(多轮识别)

recognition.value.interimResults = true; // 返回临时结果(实时反馈)

recognition.value.lang = 'zh-CN'; // 识别语言:中文(可扩展为多语言配置)

// 绑定事件回调

recognition.value.onstart = () => {

isListening.value = true;

isPaused.value = false;

errorMessage.value = '';

};

recognition.value.onresult = (event: SpeechRecognitionEvent) => {

let finalTranscript = '';

interimTranscript.value = '';

// 遍历结果列表,区分临时/最终结果

for (let i = event.resultIndex; i < event.results.length; i++) {

const transcriptPart = event.results[i][0].transcript;

if (event.results[i].isFinal) {

finalTranscript += transcriptPart; // 最终结果:追加到稳定文本

} else {

interimTranscript.value += transcriptPart; // 临时结果:实时显示草稿

}

}

if (finalTranscript) transcript.value += finalTranscript;

};

recognition.value.onerror = (event: SpeechRecognitionErrorEvent) => {

console.error('语音识别错误:', event.error);

errorMessage.value = `识别失败: ${getErrorText(event.error)}`;

stopRecognition(); // 错误时自动停止监听

};

recognition.value.onend = () => {

isListening.value = false;

isPaused.value = false;

};

};

/** 错误类型转文本(用户友好提示) */

const getErrorText = (errorType: string): string => {

const errorMap: Record<string, string> = {

'not-allowed': '无麦克风权限,请在浏览器设置中启用',

'no-speech': '未检测到语音,请重试',

'audio-capture': '麦克风访问失败,请检查设备',

'network': '网络错误,无法连接识别服务'

};

return errorMap[errorType] || errorType;

};

// ============================ 控制方法 ============================

/** 开始语音监听 */

const startRecognition = (): void => {

if (!recognition.value) initSpeechRecognition(); // 延迟初始化(首次使用时)

try {

recognition.value?.start();

transcript.value = ''; // 清空历史结果

interimTranscript.value = ''; // 清空临时结果

} catch (error) {

errorMessage.value = `启动失败: ${error instanceof Error ? error.message : String(error)}`;

}

};

/** 停止语音监听 */

const stopRecognition = (): void => {

try {

recognition.value?.stop(); // 停止监听并返回最终结果

} catch (error) {

console.error('停止监听失败:', error);

} finally {

isListening.value = false;

isPaused.value = false;

}

};

/** 暂停语音监听(暂停后可恢复) */

const pauseRecognition = (): void => {

if (recognition.value && isListening.value) {

recognition.value.stop(); // 调用 stop() 触发 onend,标记暂停状态

isPaused.value = true;

}

};

// ============================ 生命周期 ============================

onMounted(() => {

initSpeechRecognition(); // 组件挂载时初始化(预检测浏览器支持性)

});

onUnmounted(() => {

if (isListening.value) stopRecognition(); // 组件卸载时停止监听,释放资源

});

</script>

3.3 样式(Style)

<style scoped lang="scss">

.speech-recognition-card {

min-width: 300px;

max-width: 600px;

margin: 0 auto; // 居中布局

box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); // 轻微阴影提升层次感

}

/* 临时结果样式优化 */

.text-italic {

font-style: italic;

color: #666; // 灰色区分临时结果与最终结果

}

</style>

四、企业级最佳实践

4.1 类型安全与代码健壮性

  • 严格类型定义:通过SpeechRecognitionSpeechRecognitionEvent等接口,避免any类型,确保编译时类型校验。
  • 空值处理:所有状态变量(如recognition)初始化为null,操作前通过?.安全调用(如recognition.value?.start())。
  • 错误分级处理:将原生错误类型(如not-allowed)映射为用户友好提示,避免技术术语暴露。
  • 延迟初始化:语音识别实例在首次调用startRecognition时初始化,减少组件挂载时的资源占用。
  • 组件卸载清理onUnmounted钩子中停止监听,避免内存泄漏和无效资源占用。
  • 状态联动:通过isListeningisPaused精确控制按钮禁用状态,防止重复操作(如监听中无法再次开始)。
  • 实时反馈:通过图标颜色(红色=监听中/灰色=未启动)和状态文本,直观展示组件运行状态。
  • 分层结果显示:临时结果(灰色斜体)与最终结果(黑色正常文本)区分,降低用户等待焦虑。
  • 错误可视化:使用 Quasarq-banner组件展示错误信息,样式醒目且符合 Quasar 设计规范。

4.2 性能与资源管理

4.3 用户体验优化

五、扩展功能:语音指令系统

基于核心组件扩展语音指令功能,支持通过语音触发特定操作(如“清空内容”“停止监听”),适用于无接触交互场景。

5.1 指令类型与注册

// 扩展脚本部分(添加到 <script setup lang="ts"> 中)

// 语音指令类型定义

interface VoiceCommand {

command: string; // 指令关键词(如“清空内容”)

callback: () => void; // 指令触发的回调函数

description: string; // 指令描述(用于用户提示)

}

// 注册指令列表(支持动态增删)

const voiceCommands = ref<VoiceCommand[]>([

{

command: "清空内容",

callback: () => { transcript.value = ''; },

description: "清空当前识别结果"

},

{

command: "停止监听",

callback: () => { stopRecognition(); },

description: "停止语音识别"

}

]);

const activeCommand = ref<string>(''); // 当前执行的指令(用于UI反馈)

5.2 指令匹配与执行

修改recognition.value.onresult回调,添加指令匹配逻辑:

// 替换原 onresult 回调

recognition.value.onresult = (event: SpeechRecognitionEvent) => {

let finalTranscript = '';

interimTranscript.value = '';

// 提取结果(原有逻辑不变)

for (let i = event.resultIndex; i < event.results.length; i++) {

const transcriptPart = event.results[i][0].transcript;

if (event.results[i].isFinal) finalTranscript += transcriptPart;

else interimTranscript.value += transcriptPart;

}

// 新增:指令匹配逻辑

if (finalTranscript) {

transcript.value += finalTranscript;

const matchedCmd = voiceCommands.value.find(cmd =>

finalTranscript.trim().toLowerCase().includes(cmd.command.toLowerCase())

);

if (matchedCmd) {

activeCommand.value = matchedCmd.command; // 显示指令执行状态

setTimeout(() => {

matchedCmd.callback(); // 执行指令回调

activeCommand.value = ''; // 300ms后清除状态

}, 300);

}

}

};

5.3 指令UI反馈

在模板中添加指令执行状态显示:

<!-- 模板中新增(放在识别结果下方) -->

<q-card-section v-if="activeCommand" class="q-pa-none q-mt-xs">

<q-banner dense class="bg-positive text-white">

<q-icon name="check_circle" class="q-mr-sm" />

已执行指令: {{ activeCommand }}

</q-banner>

</q-card-section>

<!-- 指令列表提示(非监听状态显示) -->

<q-card-section v-if="!isListening" class="q-pa-none q-mt-xs">

<div class="text-caption text-grey-6">

<div class="text-weight-medium">语音指令:</div>

<div v-for="(cmd, idx) in voiceCommands" :key="idx">

• "{{ cmd.command }}" - {{ cmd.description }}

</div>

</div>

</q-card-section>

六、总结

本组件通过TypeScript 类型安全响应式状态管理错误友好处理可扩展指令系统,实现企业级语音识别功能。核心优势包括:

  • 低侵入性:基于浏览器原生 API,无需额外依赖,轻量化集成。
  • 高可定制:支持语言切换、指令扩展、样式定制,适配不同业务场景。
  • 企业级标准:符合代码健壮性、性能优化和用户体验规范,可直接用于生产环境。

可进一步扩展方向:多语言支持、后端 ASR 服务集成(如阿里云语音识别)、噪声抑制等高级特性。# Quasar + TypeScript 企业级语音识别组件开发指南

一、组件概述

本文档介绍基于Quasar 框架Vue 3 组合式 API开发的企业级语音识别组件SpeechRecognitionComponent。该组件集成浏览器原生语音识别 API,支持实时语音转文本、状态管理、错误处理及语音指令扩展,适用于智能客服、语音输入、会议记录等场景。组件遵循 TypeScript 类型安全规范,确保代码健壮性和可维护性,满足企业级应用对稳定性、性能和用户体验的要求。

二、核心功能

功能

描述

实时语音监听

支持开始/停止/暂停语音监听,实时反馈识别状态(监听中/已暂停/未启动)

分层结果展示

区分最终识别结果(稳定文本)和临时结果(实时草稿),提升用户体验

全类型安全

定义完整 TypeScript 接口(如SpeechRecognitionEvent),避免any类型

错误处理与兼容性

检测浏览器支持性,处理识别错误(如无权限、网络异常)并显示友好提示

语音指令扩展

支持自定义语音指令(如“清空内容”“停止监听”),实现语音交互逻辑

三、完整组件实现

3.1 模板实现(Template)

<template>

<q-card class="speech-recognition-card q-pa-md">

<!-- 标题区域 -->

<q-card-section class="q-pa-none">

<div class="text-h6">语音识别模块</div>

</q-card-section>

<!-- 状态与控制区域 -->

<q-card-section class="q-pa-none q-mt-md">

<!-- 状态指示器 -->

<div class="row items-center q-mb-md">

<q-icon

name="record_voice_over"

size="sm"

:color="isListening ? 'red' : 'grey'"

class="q-mr-sm"

/>

<span class="text-caption">状态: {{ recognitionState }}</span>

</div>

<!-- 控制按钮组 -->

<div class="row q-gutter-sm">

<q-btn

color="primary"

icon="keyboard_voice"

label="开始监听"

:disable="isListening"

@click="startRecognition"

/>

<q-btn

color="negative"

icon="stop"

label="停止监听"

:disable="!isListening"

@click="stopRecognition"

/>

<q-btn

color="warning"

icon="pause"

label="暂停监听"

:disable="!isListening || isPaused"

@click="pauseRecognition"

/>

</div>

<!-- 识别结果显示 -->

<q-input

v-model="transcript"

class="q-mt-md"

type="textarea"

filled

autogrow

label="识别结果"

readonly

rows="4"

/>

<!-- 临时结果提示 -->

<div v-if="interimTranscript" class="q-mt-xs text-caption text-italic text-grey-6">

正在输入: {{ interimTranscript }}

</div>

</q-card-section>

<!-- 错误提示区域 -->

<q-card-section v-if="errorMessage" class="q-pa-none q-mt-md">

<q-banner dense class="bg-negative text-white">

{{ errorMessage }}

</q-banner>

</q-card-section>

</q-card>

</template>

3.2 脚本实现(Script)

<script setup lang="ts">

import { ref, computed, onMounted, onUnmounted } from 'vue';

// ============================ 类型定义 ============================

/** 语音识别结果事件接口:扩展原生 Event,包含识别结果 */

interface SpeechRecognitionEvent extends Event {

resultIndex: number; // 结果起始索引

results: SpeechRecognitionResultList; // 识别结果列表(原生接口,包含临时/最终结果)

}

/** 语音识别错误事件接口:扩展原生 Event,包含错误信息 */

interface SpeechRecognitionErrorEvent extends Event {

error: string; // 错误类型(如 "not-allowed" "no-speech")

message?: string; // 错误描述(可选,部分浏览器支持)

}

/** 语音识别核心接口:封装浏览器原生 SpeechRecognition API */

interface SpeechRecognition extends EventTarget {

continuous: boolean; // 是否持续监听(true:多轮识别,false:单句识别)

interimResults: boolean; // 是否返回临时结果(true:实时草稿,false:仅最终结果)

lang: string; // 识别语言(如 "zh-CN" "en-US")

start(): void; // 开始监听

stop(): void; // 停止监听(返回最终结果)

abort(): void; // 终止监听(不返回结果)

onresult: ((event: SpeechRecognitionEvent) => void) | null; // 结果回调

onerror: ((event: SpeechRecognitionErrorEvent) => void) | null; // 错误回调

onstart: (() => void) | null; // 开始监听回调

onend: (() => void) | null; // 结束监听回调

onnomatch: (() => void) | null; // 无匹配结果回调

}

// 扩展 Window 接口,适配浏览器前缀(如 Chrome 的 webkitSpeechRecognition)

declare global {

interface Window {

SpeechRecognition: new () => SpeechRecognition;

webkitSpeechRecognition: new () => SpeechRecognition;

}

}

// ============================ 响应式状态 ============================

const transcript = ref<string>(''); // 最终识别结果(稳定文本,用户可见)

const interimTranscript = ref<string>(''); // 临时识别结果(实时草稿,灰色斜体显示)

const isListening = ref<boolean>(false); // 是否正在监听(控制按钮状态)

const isPaused = ref<boolean>(false); // 是否暂停监听(区分停止与暂停状态)

const errorMessage = ref<string>(''); // 错误信息(用户友好提示)

const recognition = ref<SpeechRecognition | null>(null); // 语音识别实例(浏览器原生 API 封装)

// ============================ 计算属性 ============================

/** 识别状态文本:根据 isListening 和 isPaused 动态生成用户友好状态 */

const recognitionState = computed<string>(() => {

if (!isListening.value) return '未启动';

if (isPaused.value) return '已暂停';

return '监听中';

});

// ============================ 核心逻辑 ============================

/** 初始化语音识别实例:检测浏览器支持性并配置参数 */

const initSpeechRecognition = (): void => {

// 检测浏览器支持性(兼容 Chrome/WebKit 内核浏览器)

const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;

if (!SpeechRecognition) {

errorMessage.value = '您的浏览器不支持语音识别 API(推荐使用 Chrome 或 Edge)';

return;

}

// 创建识别实例并配置核心参数

recognition.value = new SpeechRecognition();

recognition.value.continuous = true; // 持续监听(支持多轮语音输入)

recognition.value.interimResults = true; // 返回临时结果(实时反馈)

recognition.value.lang = 'zh-CN'; // 识别语言:中文(可扩展为多语言配置)

// 绑定事件回调:处理识别结果

recognition.value.onresult = (event: SpeechRecognitionEvent) => {

let finalTranscript = ''; // 最终结果(稳定文本)

interimTranscript.value = ''; // 临时结果(实时草稿,初始化为空)

// 遍历结果列表,区分临时/最终结果

for (let i = event.resultIndex; i < event.results.length; i++) {

const transcriptPart = event.results[i][0].transcript; // 当前片段文本

if (event.results[i].isFinal) {

finalTranscript += transcriptPart; // 最终结果:追加到稳定文本

} else {

interimTranscript.value += transcriptPart; // 临时结果:实时更新草稿

}

}

// 最终结果非空时,更新识别结果

if (finalTranscript) transcript.value += finalTranscript;

};

// 绑定事件回调:处理错误

recognition.value.onerror = (event: SpeechRecognitionErrorEvent) => {

console.error('语音识别错误:', event.error);

errorMessage.value = `识别失败: ${getErrorText(event.error)}`; // 错误信息用户友好化

stopRecognition(); // 错误时自动停止监听

};

// 绑定事件回调:监听结束(如超时、手动停止)

recognition.value.onend = () => {

isListening.value = false;

isPaused.value = false;

};

};

/** 错误类型映射:将原生错误类型转换为用户友好提示 */

const getErrorText = (errorType: string): string => {

const errorMap: Record<string, string> = {

'not-allowed': '无麦克风权限,请在浏览器设置中启用',

'no-speech': '未检测到语音,请重试',

'audio-capture': '麦克风访问失败,请检查设备',

'network': '网络错误,无法连接识别服务'

};

return errorMap[errorType] || errorType; // 未知错误直接显示类型

};

// ============================ 控制方法 ============================

/** 开始语音监听:初始化实例(首次调用时)并启动监听 */

const startRecognition = (): void => {

if (!recognition.value) initSpeechRecognition(); // 延迟初始化,减少组件挂载时资源占用

try {

recognition.value?.start(); // 调用原生 API 启动监听

transcript.value = ''; // 清空历史结果

interimTranscript.value = ''; // 清空临时结果

} catch (error) {

errorMessage.value = `启动失败: ${error instanceof Error ? error.message : String(error)}`;

}

};

/** 停止语音监听:调用原生 API 停止并重置状态 */

const stopRecognition = (): void => {

try {

recognition.value?.stop(); // 调用原生 API 停止监听(返回最终结果)

} catch (error) {

console.error('停止监听失败:', error); // 非关键错误仅控制台输出,不影响用户

} finally {

isListening.value = false; // 强制重置状态,避免 API 异常导致状态不一致

isPaused.value = false;

}

};

/** 暂停语音监听:停止监听但标记为暂停状态(可恢复) */

const pauseRecognition = (): void => {

if (recognition.value && isListening.value) {

recognition.value.stop(); // 调用原生 API 停止监听

isPaused.value = true; // 标记为暂停状态,区别于完全停止

}

};

// ============================ 生命周期 ============================

/** 组件挂载时初始化:预检测浏览器支持性,提前发现环境问题 */

onMounted(() => {

initSpeechRecognition();

});

/** 组件卸载时清理:停止监听并释放资源,避免内存泄漏 */

onUnmounted(() => {

if (isListening.value) stopRecognition();

});

</script>

3.3 样式实现(Style)

<style scoped>

/* 卡片容器样式:限制宽度范围,适配不同屏幕 */

.speech-recognition-card {

min-width: 300px; /* 最小宽度,避免移动端过窄 */

max-width: 600px; /* 最大宽度,避免桌面端过宽 */

margin: 0 auto; /* 居中布局,提升视觉体验 */

}

/* 临时结果样式:灰色斜体,区分于最终结果 */

.text-italic {

font-style: italic;

color: #666; /* 灰色文本,弱化视觉权重 */

}

</style>

四、企业级最佳实践

4.1 类型安全与代码健壮性

  • 严格类型定义:通过SpeechRecognitionSpeechRecognitionEvent等接口,明确原生 API 的参数和返回值类型,避免any类型导致的运行时错误。例如,SpeechRecognitionEvent接口定义了resultIndex和results属性,确保事件处理时类型校验通过。
  • 空值安全处理:所有状态变量(如recognition)初始化为null,操作前通过可选链(?.)安全调用(如recognition.value?.start()),避免空指针异常。
  • 错误分级处理:将原生错误类型(如not-allowed)映射为用户友好提示(如“无麦克风权限”),隐藏技术细节,提升用户体验。
  • 延迟初始化:语音识别实例在首次调用startRecognition时初始化,而非组件挂载时,减少初始加载资源占用。
  • 组件卸载清理onUnmounted钩子中停止监听,释放麦克风资源,避免组件销毁后仍占用设备权限。
  • 状态联动控制:通过isListening和isPaused精确控制按钮禁用状态(如监听中禁用“开始”按钮),防止重复操作导致的 API 异常。
  • 实时状态反馈:通过图标颜色(红色=监听中/灰色=未启动)和状态文本(“监听中”“已暂停”),直观展示组件运行状态,降低用户等待焦虑。
  • 分层结果展示:临时结果(灰色斜体)与最终结果(黑色正常文本)区分,实时反馈语音输入进度,提升交互流畅性。
  • 错误可视化:使用 Quasarq-banner组件展示错误信息,样式醒目且符合 Quasar 设计规范,确保用户不会忽略关键提示。

4.2 性能与资源管理

4.3 用户体验优化

五、扩展功能:语音指令系统

基于核心组件扩展语音指令功能,支持通过语音触发特定操作(如“清空内容”“停止监听”),适用于无接触交互场景(如医疗、工业控制)。

5.1 指令类型与注册

// 扩展脚本部分(添加到 <script setup lang="ts"> 中)

/** 语音指令类型:定义指令关键词、回调函数和描述 */

interface VoiceCommand {

command: string; // 指令关键词(如“清空内容”)

callback: () => void; // 指令触发的回调函数(如清空识别结果)

description: string; // 指令描述(用于用户提示,如“清空当前识别结果”)

}

/** 注册语音指令列表:支持动态增删,适配不同业务场景 */

const voiceCommands = ref<VoiceCommand[]>([

{

command: "清空内容",

callback: () => { transcript.value = ''; },

description: "清空当前识别结果"

},

{

command: "停止监听",

callback: () => { stopRecognition(); },

description: "停止语音识别"

}

]);

const activeCommand = ref<string>(''); // 当前执行的指令(用于 UI 反馈)

5.2 指令匹配与执行

修改onresult事件处理逻辑,添加指令匹配:

// 修改 recognition.value.onresult 回调,加入指令判断

recognition.value.onresult = (event: SpeechRecognitionEvent) => {

let finalTranscript = '';

interimTranscript.value = '';

// 遍历结果列表,提取临时/最终结果(原有逻辑不变)

for (let i = event.resultIndex; i < event.results.length; i++) {

const transcriptPart = event.results[i][0].transcript;

if (event.results[i].isFinal) finalTranscript += transcriptPart;

else interimTranscript.value += transcriptPart;

}

// 最终结果非空时,检查是否匹配语音指令

if (finalTranscript) {

transcript.value += finalTranscript;

// 匹配指令:忽略大小写,判断结果是否包含指令关键词

const matchedCommand = voiceCommands.value.find(cmd =>

finalTranscript.trim().toLowerCase().includes(cmd.command.toLowerCase())

);

if (matchedCommand) {

activeCommand.value = matchedCommand.command; // 显示指令执行状态

setTimeout(() => {

matchedCommand.callback(); // 执行指令回调

activeCommand.value = ''; // 300ms 后清除状态

}, 300);

}

}

};

5.3 指令 UI 反馈

在模板中添加指令执行状态和可用指令列表:

<!-- 扩展模板部分(添加到 <template> 中) -->

<!-- 指令执行状态提示 -->

<q-card-section v-if="activeCommand" class="q-pa-none q-mt-xs">

<q-banner dense class="bg-positive text-white">

<q-icon name="check_circle" class="q-mr-sm" />

已执行指令: {{ activeCommand }}

</q-banner>

</q-card-section>

<!-- 可用指令列表(非监听状态显示) -->

<q-card-section v-if="!isListening" class="q-pa-none q-mt-xs">

<div class="text-caption text-grey-6">

<div class="text-weight-medium">语音指令:</div>

<div v-for="(cmd, idx) in voiceCommands" :key="idx">

• "{{ cmd.command }}" - {{ cmd.description }}

</div>

</div>

</q-card-section>

六、总结

本组件通过TypeScript 类型安全响应式状态管理错误友好处理可扩展指令系统,实现了企业级语音识别功能。核心优势包括:

  • 低侵入性:基于浏览器原生 API,无需额外依赖,轻量化集成到 Quasar 应用。
  • 高可定制:支持语言切换、指令扩展、样式定制,适配智能客服、会议记录等多场景。
  • 企业级标准:符合代码健壮性、性能优化和用户体验规范,可直接用于生产环境。

可进一步扩展方向:多语言支持(动态切换lang属性)、后端 ASR 服务集成(如阿里云语音识别)、噪声抑制(结合 Web Audio API)等高级特性。

 

posted on 2025-09-18 10:37  GoGrid  阅读(27)  评论(0)    收藏  举报

导航