UniApp 语音识别功能
·
基于 AINote.ts 代码中语音识别相关逻辑,结合 UniApp 跨端特性,梳理语音识别功能的踩坑点、调试限制及交互优化方案如下:
一、核心问题:基站/Web 端无法调试语音识别
1. 无法调试的根本原因
从代码中可见,语音识别核心逻辑依赖 plus.speech(如下代码片段),这是 5+ App 专属 API,仅在 App 端(iOS/Android)生效,基站(小程序)、H5(Web)端无此 API 支持:
// 代码中仅在 APP-PLUS 条件编译下初始化语音识别监听
//#ifdef APP-PLUS
plus.speech.addEventListener(
"start",
this.onVoiceStart.bind(this),
false
);
plus.speech.addEventListener(
"recognizing",
this.onVoiceRecognizing.bind(this),
false
);
//#endif
具体限制:
| 端类型 | 语音识别 API 支持情况 | 调试可行性 |
|---|---|---|
| App(iOS/Android) | 支持 plus.speech(5+ API) |
可调试 |
| 微信小程序 | 需改用 wx.startRecord/微信同声传译 |
不兼容原生 plus.speech |
| H5(Web) | 无 plus 环境,需改用 Web Speech API |
不兼容 |
| 基站(其他小程序) | 无统一语音识别 API,需适配各平台 | 不兼容 |
2. 解决方法(分端适配)
方案1:App 端(保留原有逻辑)
无需修改,代码中已通过 #ifdef APP-PLUS 做条件编译,确保仅 App 端执行 plus.speech 相关逻辑。
方案2:微信小程序端适配
改用微信小程序原生语音识别 API,补充条件编译代码:
//#ifdef MP-WEIXIN
// 小程序语音识别:初始化录音+同声传译(需先引入微信同声传译插件)
initWxVoiceRecognize() {
this.isRecording.value = true;
wx.startRecord({
duration: 60000, // 最长录音60秒
success: (res) => {
// 录音完成后调用微信同声传译转文字
wx.cloud.callFunction({
name: 'voiceToText', // 云函数:调用微信同声传译API
data: {
fileID: res.tempFilePath // 录音临时文件路径
},
success: (transRes) => {
this.voiceText.value = transRes.result; // 最终识别结果
}
});
},
fail: (err) => {
console.error('小程序录音失败', err);
this.isRecording.value = false;
}
});
}
//#endif
方案3:H5(Web)端适配
改用 Web Speech API(浏览器原生),补充条件编译代码:
//#ifdef H5
// Web 端语音识别(依赖浏览器支持,如 Chrome/Edge)
initWebVoiceRecognize() {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
uni.showToast({ title: '当前浏览器不支持语音识别', icon: 'none' });
return;
}
const recognition = new SpeechRecognition();
recognition.continuous = true; // 连续识别
recognition.interimResults = true; // 返回临时结果
// 识别中(实时返回部分结果)
recognition.onresult = (event) => {
const interimTranscript = [];
const finalTranscript = [];
for (let i = event.resultIndex; i < event.results.length; i++) {
const transcript = event.results[i][0].transcript;
if (event.results[i].isFinal) {
finalTranscript.push(transcript);
} else {
interimTranscript.push(transcript);
}
}
this.voicePartialResult.value = interimTranscript.join(''); // 临时结果
if (finalTranscript.length) {
this.voiceText.value = finalTranscript.join(''); // 最终结果
}
};
// 开始/结束识别
recognition.start();
this.isRecording.value = true;
this.webRecognitionInstance = recognition; // 保存实例用于停止
}
//#endif
方案4:调试阶段兜底
在非 App 端调试时,增加“模拟语音输入”功能,避免功能阻塞:
// 统一入口:语音识别开始
startVoiceRecognize() {
// #ifdef APP-PLUS
// 原有 App 端逻辑
plus.speech.startRecognize({
engine: 'iFlytek', // 讯飞引擎(需配置)
lang: 'zh-CN'
});
// #endif
// #ifdef MP-WEIXIN || H5
// 非 App 端:弹出输入框模拟语音输入
uni.showModal({
title: '调试模式',
content: '当前端不支持语音识别,手动输入模拟结果',
editable: true,
success: (res) => {
if (res.confirm && res.content) {
this.voiceText.value = res.content;
this.voicePartialResult.value = '(模拟识别完成)';
this.isRecording.value = false;
}
}
});
// #endif
}
二、交互优化(基于代码中现有逻辑升级)
代码中已包含 isRecording(录音状态)、isSlideUp(滑动取消)、voicePartialResult(临时结果)等基础交互,可进一步优化如下:
1. 状态可视化优化
(1)录音状态实时反馈
// 原有 voiceTitle 仅显示“未开始”,升级为多状态提示
watch([this.isRecording, this.voicePartialResult], ([isRecording, partial]) => {
if (isRecording) {
this.voiceTitle.value = `识别中...${partial || '请说话'}`;
// 增加录音动画(如麦克风波纹动效)
uni.setStorageSync('voiceAnimate', 'play');
} else {
this.voiceTitle.value = this.voiceText.value ? '识别完成' : '未开始';
uni.setStorageSync('voiceAnimate', 'stop');
}
}, { immediate: true });
(2)滑动取消交互强化
代码中已有 onTouchMove 监听滑动,补充“滑动阈值”和视觉提示:
onTouchMove(e: UniApp.TouchMoveEvent) {
const deltaY = e.touches[0].clientY - this.touchStartY;
// 向上滑动超过50px触发取消
if (deltaY < -50) {
this.isSlideUp.value = true;
this.voiceTitle.value = '松开取消识别'; // 视觉提示
} else {
this.isSlideUp.value = false;
}
}
// 触摸结束:判断是否取消
onTouchEnd() {
if (this.isSlideUp.value) {
this.endVoiceRecognize(); // 停止识别
uni.showToast({ title: '已取消语音识别', icon: 'none' });
}
}
2. 容错与体验优化
(1)录音异常兜底
// 监听语音识别错误(App 端)
onVoiceError(error: any) {
this.isRecording.value = false;
const errorMsg = {
'10001': '识别引擎初始化失败',
'10002': '无录音权限',
'10003': '识别超时'
}[error.code] || '识别失败,请重试';
uni.showToast({ title: errorMsg, icon: 'none' });
// 权限失败时引导开启
if (error.code === '10002') {
uni.showModal({
title: '权限提示',
content: '需要录音权限才能使用语音识别,是否前往设置开启?',
success: (res) => {
if (res.confirm) {
plus.speech.openSetting(); // 跳转到权限设置页
}
}
});
}
}
(2)输入框焦点与录音互斥
// 避免录音时输入框获取焦点
watch(this.isRecording, (isRecording) => {
if (isRecording) {
this.inputFocus.value = false; // 录音时失去输入框焦点
uni.hideKeyboard(); // 隐藏键盘
}
});
// 输入框聚焦时自动停止录音
watch(this.inputFocus, (focus) => {
if (focus && this.isRecording.value) {
this.endVoiceRecognize();
}
});
3. 性能优化
(1)及时销毁监听实例
// 页面卸载时销毁语音识别监听
onUnload() {
// #ifdef APP-PLUS
plus.speech.removeAllEventListeners();
if (this.isRecording.value) {
plus.speech.stopRecognize();
}
// #endif
// #ifdef H5
if (this.webRecognitionInstance) {
this.webRecognitionInstance.stop();
this.webRecognitionInstance = null;
}
// #endif
// #ifdef MP-WEIXIN
wx.stopRecord();
// #endif
}
(2)节流处理临时结果更新
// 原有 onVoiceRecognizing 可能高频触发,增加节流
private voiceThrottleTimer: number | null = null;
onVoiceRecognizing(e: any) {
if (this.voiceThrottleTimer) return;
this.voiceThrottleTimer = setTimeout(() => {
this.voicePartialResult.value = e.result; // 临时识别结果
this.voiceThrottleTimer = null;
}, 100); // 100ms 节流,减少DOM更新
}
三、总结
| 踩坑点 | 解决方案 |
|---|---|
非 App 端无 plus.speech |
分端适配(小程序用微信API、H5用Web Speech) |
| 调试阶段功能阻塞 | 增加模拟输入兜底逻辑 |
| 录音状态反馈不清晰 | 多状态标题+动效提示 |
| 滑动取消交互不友好 | 增加滑动阈值+视觉提示 |
| 权限/异常无兜底 | 错误码映射+权限引导 |
| 高频更新导致性能问题 | 节流处理临时结果更新 |
核心原则:UniApp 语音识别需分端适配,优先保证 App 端原生体验,非 App 端通过“模拟+专属API”兜底,同时强化状态反馈和容错,提升跨端交互一致性。
更多推荐


所有评论(0)