uni-app在app端无法使用uni.createspeechrecognizer实现语音识别,因其仅支持微信小程序;可行方案为:①原生插件封装讯飞sdk(低延迟但配置复杂),②uni.getrecordermanager配合百度实时语音api流式上传pcm数据(轻量可控、跨平台兼容)。

uni-app 在 App 端(iOS/Android)实现实时语音识别转文字显示,不能靠 uni.createSpeechRecognizer —— 这个 API 仅在微信小程序中有效,App 端调用会静默失败或报 undefined。
真正可行的路径只有两条:原生插件封装讯飞 SDK 或 调用百度语音实时 API + 自行管理录音流。前者延迟低、体验好但配置重;后者更轻量、可控性强,适合大多数业务场景。
为什么 uni.createSpeechRecognizer 在 App 端完全不可用
这个 API 是 uni-app 对微信小程序 wx.onVoiceRecognize 的封装,底层依赖微信客户端能力。App 端(app-plus)运行环境没有对应原生实现,调用后既不触发回调,也不抛错,start() 返回 undefined 或静默无响应。
- 常见错误现象:
const recognizer = uni.createSpeechRecognizer()执行后recognizer为null或undefined,recognizer.start()报TypeError: Cannot read property 'start' of undefined - 别浪费时间 patch 它——uni-app 官方文档已明确标注该 API “仅小程序支持”
- 替代方案必须绕过这个 API,直接对接原生能力或云服务
推荐方案:用 uni.getRecorderManager + 百度实时语音 API
这是目前最稳定、跨平台兼容性最好、且无需额外原生开发的方案。核心逻辑是:自己控制录音 → 按固定帧长(如 200ms)切片 → 用 WebSocket 流式上传 → 接收百度返回的中间识别结果并实时渲染。
- 需提前在百度智能云开通「实时语音识别」服务,获取
api_key和secret_key(注意:不是app_id,百度实时 API 不用它) - 必须用
uni.getRecorderManager,而非uni.chooseVideo或临时文件上传——只有它能持续输出 PCM 数据片段 - 录音格式必须设为
format: 'mp3'或'aac',但百度实时 API 要求pcm;所以实际需用encodeBitRate: 16000+samplerate: 16000+numberOfChannels: 1,再在前端做简单 PCM 封装(或后端转) - WebSocket 地址为:
wss://vop.baidubce.com/ws/stream,鉴权需携带access_token(通过/oauth/2.0/token获取) - 每帧数据需按百度协议打包:4 字节长度前缀 + PCM 数据体,否则服务端直接断连
科大讯飞原生插件方案的坑点清单
如果你坚持用讯飞(比如已有授权、需离线识别或定制热词),必须走原生插件路线,但以下问题极易卡住:
-
manifest.json中插件配置必须严格匹配插件包名,例如:"iFlytek": { "provider": "com.iflytek" },少一个字母或大小写错误,iOS 上直接白屏无日志 - iOS 需手动在
Xcode的Capabilities → Microphone开关打开,且Info.plist中必须含NSMicrophoneUsageDescription,否则首次调用就 crash - Android 9+ 默认禁止明文 HTTP,若插件内部用 HTTP 请求(老版本 SDK 常见),需在
androidmanifest.xml加android:usesCleartextTraffic="true" - 讯飞 SDK 的
onBeginOfSpeech和onEndOfSpeech在某些低端安卓机上触发不准,建议加 300ms 静音超时兜底 -
uni-plugin-iflytek的createIFlytekRecorder初始化失败时,catch不会抛出具体错误码,只能靠console.log查看原生日志
关键细节:实时性 ≠ 每字刷新,而是“流式中间结果”
用户期待的“边说边出字”,本质是服务端返回带 result_type: "final_result" 或 "partial_result" 的 JSON。百度和讯飞都支持,但处理方式不同:
- 百度返回字段为
text(当前句完整文本)和result(当前流式片段),应优先用result更新 UI,避免整句重绘闪动 - 讯飞 SDK 的
onResults回调中,isLast为false时才是中间结果,此时应追加到当前transcript后,而不是覆盖 - 无论哪家,都建议加防抖:连续 500ms 无新结果才触发最终确认态(比如加下划线或置灰),否则用户修改口误时 UI 会疯狂跳变
- 别忽略网络抖动——WebSocket 断连后重连,要续传上次
sn(序列号),否则百度会丢帧
真实项目里,80% 的“识别不准”和“卡顿”都来自音频采集参数不匹配或流式协议解析错位,而不是模型本身。先跑通一帧 PCM 的端到端链路,再谈优化。











