当前位置: 首页 > article >正文

记录--uniapp 安卓端实现录音功能,保存为amr/mp3文件

🧑‍💻 写在开头
点赞 + 收藏 === 学会🤣🤣🤣

功能实现需要用到MediaRecorder、navigator.mediaDevices.getUserMedia、Blob等API,uniapp App端不支持,需要借助renderjs来实现

实现逻辑

  1. 通过navigator.mediaDevices.getUserMedia调用设备麦克风,获取音频流
  2. 使用MediaRecorder录制音频数据
  3. 用Blob、FileReader将音频数据转为转为base64格式
  4. 调用fs.root.getFile创建空白amr/mp3文件
  5. 通过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

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

在这里插入图片描述


http://www.kler.cn/a/449764.html

相关文章:

  • 利用.NET Upgrade Assitant对项目进行升级
  • 增量训练(持续学习)
  • PostgreSQL 的历史
  • [Xshell] Xshell的下载安装使用、连接linux、 上传文件到linux系统-详解(附下载链接)
  • JVM系列(十二) -常用调优命令汇总
  • Ubuntu硬盘分区及挂载(命令行)
  • Blazor项目中使用EF读写 SQLite 数据库
  • 在Ubuntu上通过Docker部署NGINX服务器
  • 第三节:GLM-4v-9B数据加载之huggingface数据加载方法教程(通用大模型数据加载实列)
  • 96 vSystem
  • 区块链与比特币:技术革命的双子星
  • ImportError: DLL load failed while importing jiter
  • 工信部“人工智能+”制造行动点亮CES Asia 2025
  • 便捷的线上游戏陪玩、线下家政预约以及语音陪聊服务怎么做?系统代码解析
  • 基于Spring Boot的电影网站系统
  • K8S Ingress 服务配置步骤说明
  • 1114 Family Property (25)
  • 【环境搭建】Python、PyTorch与cuda的版本对应表
  • 在Vue2中,el-tree组件的页面节点前三角符号仅在有下级节点时显示
  • LeetCode 54. 螺旋矩阵 (C++实现)
  • Deformable DETR:Deformable Transformers for End-to-End Object Detection论文学习
  • 【从零开始入门unity游戏开发之——C#篇26】C#面向对象动态多态——接口(Interface)、接口里氏替换原则、密封方法(`sealed` )
  • Springboot项目本地连接并操作MySQL数据库
  • 数据结构概念介绍
  • Javascript数据结构——二叉树篇
  • 微信小程序xr-frame透明视频实现