App端录音必须用uni.startRecord()和uni.stopRecord(),禁用MediaRecorder;需分步处理权限、显式指定format为aac、将tempFilePath转File对象上传,且须适配iOS后台中断与Android定制ROM限制。

App端录音上传不能直接套用H5的MediaRecorder,必须走uni-app原生封装的uni.startRecord()和uni.stopRecord(),否则在iOS/Android真机上会静音、报错或根本无回调。
App端录音权限与初始化必须分两步走
很多开发者卡在“点了开始没反应”,其实是权限检测和调用顺序错了。iOS需提前在Info.plist加NSMicrophoneUsageDescription,Android需在manifest.json中声明android.permission.RECORD_AUDIO;但光有声明不够,运行时还得主动申请:
-
uni.getSystemInfoSync().platform === 'ios'时,必须先调用uni.authorize({scope: 'scope.record'}),再调uni.startRecord() - Android部分机型(如华为EMUI 12+)即使已授权,
uni.startRecord()仍可能失败,需捕获fail回调并引导用户手动进设置页开启 - 不要在
onLoad里直接启动录音——App冷启动时Audio Session可能未就绪,建议延迟300ms再调用
录音格式参数必须显式指定,不能依赖默认值
不同平台输出格式差异极大:android默认.amr(后端难解析),iOS默认.caf(非标准、体积大),而服务器通常只认.mp3或.wav。必须在uni.startRecord()中强制指定:
-
format: 'mp3'—— 微信小程序和部分App端支持,但iOS原生不支持此参数,会忽略 -
encodeBitRate: 128000+sampleRate: 44100—— 提高兼容性,避免低采样率导致语音识别失败 - 更稳妥的做法:统一用
format: 'aac'(iOS/Android均原生支持),后端用ffmpeg转MP3,比前端WASM转码更稳定
上传前必须处理tempFilePath路径和文件名
App端uni.stopRecord()返回的tempFilePath是本地沙盒路径(如_www/123456.aac),不能直接丢给uni.uploadFile()——它只接受file对象或合法URI。常见错误包括:
- 直接传
tempFilePath字符串,结果上传空文件或400错误 - 用
uni.getFileInfo()获取大小后没校验是否为0字节(录音失败时也返回路径) - 没重命名文件,后端按扩展名路由时
.aac被拦截
正确做法是用uni.chooseMessageFile()绕过限制(不推荐),或更直接地:用uni.downloadFile()把tempFilePath拉成临时URL,再用uni.uploadFile()上传——但效率低;最优解是调用uni.getFileSystemManager().readFile()读取二进制,再构造Blob和File对象:
const file = new File([arrayBuffer], 'rec_' + Date.now() + '.aac', { type: 'audio/aac' });
注意:arrayBuffer需从readFile的data字段取,不是res.tempFilePath本身。
真机调试时最容易被忽略的三个点
模拟器永远正常,但真机上线后崩溃或无声,往往栽在这三处:
- iOS后台录音会被系统强制中断——若用户切到其他App,
uni.stopRecord()不会触发,需监听app.onHide()主动停止并提示 - Android部分定制ROM(如小米MIUI)对录音有后台保活限制,需在
manifest.json中添加"permission": {"audioRecord": {"desc": "用于语音留言"}}并确保描述语匹配系统弹窗文案 - 上传超时默认60秒,但30秒以上录音在弱网下极易失败,必须显式设
timeout: 120000,且服务端Nginx要同步调大client_max_body_size和proxy_read_timeout
别指望条件编译自动兜底——App端录音链路长、环节多,每个节点都得单独验证,尤其是权限拒绝后的降级提示逻辑,必须手真机点一遍拒绝按钮再测。


















