🧑 写在开头
点赞 + 收藏 === 学会🤣🤣🤣
功能实现需要用到
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 插件市场。
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时执行一次
<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
。
<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
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
来源链接:https://www.cnblogs.com/smileZAZ/p/18624889
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容