记录---uniapp 安卓端实现录音功能,保存为amr/mp3文件
🧑💻 写在开头
点赞 + 收藏 === 学会🤣🤣🤣
功能实现需要用到
MediaRecorder、navigator.mediaDevices.getUserMedia、Blob
等API,uniapp App端不支持,需要借助renderjs
来实现
实现逻辑
- 通过
navigator.mediaDevices.getUserMedia
调用设备麦克风,获取音频流 - 使用
MediaRecorder
录制音频数据 - 用
Blob、FileReader
将音频数据转为转为base64
格式 - 调用
fs.root.getFile
创建空白amr/mp3
文件 - 通过
h5plus
调用安卓APIjava.io.FileOutputStream
将数据保存进文件中
代码实现
获取音频流
申请媒体权限
首先需要提前申请下权限。App 端调用navigator.mediaDevices.getUserMedia
时不像浏览器上会弹框申请权限,插件市场有官方提供的免费插件:App权限判断和提示 - DCloud 插件市场。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | async onLoad() { // 申请麦克风权限 let isRecord = await permision.requestAndroidPermission( 'android.permission.RECORD_AUDIO' ) if (isRecord == -1) { uni.showModal({ title: '提示' , content: '未获取到麦克风权限,可能导致应用运行出现问题' , confirmText: '去开启' , cancelText: "暂不开启" , success: res => { if (res.confirm) { // 跳转权限页面 permision.gotoAppPermissionSetting() } } }) } } |
获取音频流代码
mediaRecorder.start(60 * 1000);
表示60秒执行一次ondataavailable,可用来实现分段录制。不传参数则只在stop时执行一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <script lang= "renderjs" > export default { async startRecord() { try { let localStream = await navigator.mediaDevices.getUserMedia({ video: false , audio: true , }); let mediaRecorder = new MediaRecorder(localStream); mediaRecorder.ondataavailable = event => { const blob = new Blob([event.data]); var reader = new FileReader(); reader.readAsDataURL(blob); reader.onload = (e) => { let base64str = e.target.result // 调用外层script中的base64ToFile方法,将 base64 传入。 this.$ownerInstance.callMethod( 'base64ToFile' , base64str) } } // 录制停止 mediaRecorder.onstop = (e) => { } mediaRecorder.start(60 * 1000); // 60秒执行一次ondataavailable,可实现分段录制,不传参数只在stop时执行一次 } catch (e) { console.log( '麦克风权限获取失败' ) } } } < /script > |
保存amr/mp3文件
- 文件保存在uniapp_save文件夹下可以通过
uni.getSavedFileList
方法获取到。- plus.io.PRIVATE_DOC 位置参考:
内部存储>Android>data>io.dcloud.HBuilder>apps>HBuilder>doc
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <script> export default { base64ToFile(base64Str, fileName = `uniapp_save/${new Date().valueOf()}.amr`) { // 去除 base64 前缀 var index = base64Str.indexOf( ',' ) var base64Str = base64Str.slice(index + 1, base64Str.length) plus.io.requestFileSystem(plus.io.PRIVATE_DOC, function (fs) { fs.root.getFile(fileName, { create: true }, function (entry) { // 获得本地路径URL, file : ///xxx/doc/1663062980631 .amr var fullPath = entry.fullPath; var FileOutputStream = plus.android.importClass( "java.io.FileOutputStream" ); try { function base64ToByteArray(base64Str) { const binaryString = atob(base64Str); const uint8Array = new Uint8Array(binaryString.length); for ( let i = 0; i < binaryString.length; i++) { uint8Array[i] = binaryString.charCodeAt(i); } let arr = [] Array.from(uint8Array).map(num => { arr.push(num >= 128 ? (num - 256) : num) }) return arr; } var out = new FileOutputStream(fullPath); let bytes = base64ToByteArray(base64Str); if (bytes == null || bytes.length == 0) { out.close(); uni.hideLoading(); uni.showModal({ title: "生成失败" , content: "nativeJS限制参数长度无法获取文件!" , showCancel: false }) return } else { out.write(bytes); out.close(); console.log(`保存成功,文件地址为:_doc/${fileName}`) } } catch (e) { console.log(e.message); } }) }) } } < /script > |
参考资料
- 在base64转本地文件(如pdf,apk,音频等)如果base64长度过长 在 安卓中 Base64.decode(str, 0) 返回 null 的解决问题 - DCloud问答
- HTML5+ API
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
2023-12-23 记录--前端验证码破解
2020-12-23 uni-app开发经验分享十六:发布android版App的详细过程