uniapp Vue3 语法实现浏览器中音频录制、停止、保存、播放、转码、实时音频输出

一、引言

在现代 Web 应用开发中,音频处理功能变得越来越重要。本文将详细介绍如何使用 uniapp 结合 Vue3 语法在浏览器环境中实现音频录制、停止、保存、播放、转码以及实时音频输出等一系列功能。通过深入剖析代码结构和功能实现细节,帮助读者全面理解和掌握相关技术,以便在自己的项目中应用或进行进一步的拓展和优化。

二、代码整体结构概述

这段代码是一个 Vue3 组件的模板和脚本部分,用于在 uniapp 项目中实现音频录制相关功能。模板部分包含了用于控制音频录制、停止、播放的按钮,以及显示音频 Base64 数据和音频频率进度条的元素。脚本部分则通过引入 Vue3 的相关函数和对象,定义了一系列变量和函数来实现音频录制的核心逻辑,包括获取音频流、实例化媒体录制器、处理录制数据、分析音频频率、转换音频格式以及与界面元素的交互等。

三、详细功能实现解析

(一)数据变量定义

  1. audioBase64:使用 ref 函数创建的响应式数据,用于存储音频的 Base64 编码数据,初始值为空字符串。它将在音频录制完成并转换为 Base64 格式后被赋值,以便在界面上显示或进行其他处理。
  2. mediaRecorder:用于存储媒体录制器实例。通过 navigator.mediaDevices.getUserMedia 获取音频流后,利用该实例来启动和停止音频录制,并处理录制过程中产生的数据块。
  3. audioStream:存储获取到的音频流对象。该音频流是从用户设备的音频输入设备(如麦克风)获取的,是后续音频录制和分析的基础数据来源。
  4. audioContextAudioContext 实例,用于创建和管理音频处理节点,如音频分析器等。它提供了对音频硬件的访问和音频处理的上下文环境。
  5. analyser:音频分析器实例,通过 audioContext.createAnalyser 创建。它用于对音频流进行分析,获取音频的频率数据等信息,以便实现实时音频输出(如进度条显示音频频率变化)。
  6. isRecording:布尔类型的响应式数据,标记当前是否正在进行音频录制,初始值为 false。通过该变量控制录制按钮的禁用状态,避免重复录制操作。
  7. hasRecorded:布尔类型的响应式数据,标记是否已经有录制的音频内容,初始值为 false。用于控制播放音频按钮的禁用状态,只有在有录制内容后才能播放。
  8. frequencyProgress:响应式数据,用于存储音频频率对应的进度条进度值,初始值为 0。根据音频分析器获取的频率数据进行映射和更新,以在界面上直观地展示音频频率的变化情况。
  9. recordedChunks:数组,用于存储每次录制的音频数据块。在录制过程中,媒体录制器的 ondataavailable 事件会将数据块添加到该数组中,最后用于生成完整的音频 Blob 对象。
  10. audioContextClosed:布尔变量,标记 AudioContext 是否已经关闭,初始值为 false。用于避免重复关闭 AudioContext 导致的错误。
  11. halfSecondUpdateIntervalId:用于存储每 0.5 秒更新频率的定时器标识。通过该标识可以在合适的时候清除定时器,避免定时器的累积和不必要的资源占用。

(二)音频录制功能 - startRecording 函数

  1. 首先,函数会检查当前是否已经在录制音频,如果 isRecording.valuetrue,则直接返回,不进行重复录制操作。
  2. 若未在录制,则调用 resetRecordingData 函数重置录制相关数据。这个函数会清空 recordedChunks 数组,将 hasRecorded.value 设置为 false,关闭 audioContext(如果未关闭)并断开 analyser 的连接,同时将 frequencyProgress.value 设置为 0。这样做的目的是为了确保每次新的录制都是在一个干净的状态下开始,清除之前录制可能留下的残留数据和状态。
  3. 接着使用 navigator.mediaDevices.getUserMedia 方法获取音频流,传入的参数 { audio: true } 表示只获取音频设备的媒体流。如果获取成功,将音频流赋值给 audioStream 变量,并在控制台打印获取到的音频流信息。然后创建 MediaRecorder 实例,传入获取到的音频流,并启动录制,即 mediaRecorder.start()
  4. mediaRecorderondataavailable 事件注册回调函数,当有可用的音频数据块时,会触发该事件。在回调函数中,判断数据块的大小是否大于 0,如果是,则将数据块添加到 recordedChunks 数组中,用于后续生成完整的音频文件。
  5. 调用 initAudioAnalyzer 函数初始化音频分析器,传入获取到的音频流作为参数。这个函数将在后面详细介绍,它主要用于创建音频分析器实例,并设置相关参数,以及启动定时器来定期更新音频频率数据并反映在进度条上。
  6. 最后,将 isRecording.value 设置为 true,表示当前正在录制音频,同时界面上的“开始录制”按钮将被禁用,“停止录制”按钮将被启用。

(三)音频分析器初始化 - initAudioAnalyzer 函数

  1. 首先检查 audioContextClosed 变量,如果已经关闭,则直接返回,不再进行初始化操作,避免重复创建和初始化音频分析器导致的错误。
  2. 创建 AudioContext 实例并赋值给 audioContext 变量,通过 audioContext.createMediaStreamSource 方法从传入的音频流创建音频源,并连接到音频分析器 analyser
  3. 设置音频分析器的参数,如 fftSize 设置为 2048,这个参数决定了频率分析的精度和分辨率。然后获取分析器的频率数据缓冲区长度 bufferLength,并创建一个 Uint8Array 类型的数组 dataArray 用于存储频率数据。
  4. 定义了一个名为 updateFrequency 的函数,用于每秒更新一次音频频率数据。在这个函数中,首先通过 analyser.getByteFrequencyData 方法获取当前音频的频率数据并存储到 dataArray 中,然后计算频率数据的总和 sum,并求出平均频率值 average。接着将平均频率值进行映射处理,将其转换为适合进度条显示的值 mappedValue,通过 Math.min 函数确保该值不超过 100,并使用 Math.round 函数进行四舍五入取整。最后在控制台打印原始平均频率值和映射后的进度条值。通过 setInterval 函数以每秒一次的频率调用 updateFrequency 函数,并将定时器的标识存储在 intervalId 变量中,以便在录制停止时清除该定时器。
  5. mediaRecorderonstop 事件注册回调函数,在录制停止时,清除之前创建的每秒更新频率的定时器。
  6. 新增了一个每 0.5 秒更新频率的定时器逻辑。通过 setInterval 函数创建一个定时器,每隔 0.5 秒执行一次匿名函数。在匿名函数中,同样获取音频频率数据并计算平均频率值和映射后的进度条值,然后直接将映射后的进度条值赋值给 frequencyProgress.value,这样就可以实现进度条根据音频频率实时跳动的效果。将这个定时器的标识存储在 halfSecondUpdateIntervalId 变量中,以便在后续停止录制或其他合适的时机清除该定时器。

(四)音频停止录制功能 - stopRecording 函数

  1. 首先检查 mediaRecorder 是否存在且当前状态是否为“recording”(正在录制),如果满足条件,则调用 mediaRecorder.stop() 停止录制。
  2. mediaRecorderonstop 事件注册回调函数,在录制停止后执行以下操作:
    • 遍历 audioStream 的所有音频轨道,并调用 stop 方法停止音频流,释放音频设备资源。
    • 如果 audioContext 存在且未关闭,调用 audioContext.close() 方法关闭音频上下文,将 audioContextClosed 设置为 true,表示音频上下文已关闭,避免重复关闭操作。
    • 如果 analyser 存在,调用 analyser.disconnect() 方法断开音频分析器与音频源的连接,释放相关资源。
    • 调用 convertAudioToBase64 函数将录制的音频数据转换为 Base64 格式,并存储在 audioBase64.value 中,以便在界面上显示音频数据。
    • isRecording.value 设置为 false,表示录制已停止,“开始录制”按钮将被启用,“停止录制”按钮将被禁用;将 hasRecorded.value 设置为 true,表示已经有录制的音频内容,“播放音频”按钮将被启用;将 frequencyProgress.value 设置为 0,重置进度条。
    • 最后,清除每 0.5 秒更新频率的定时器,通过 clearInterval 函数传入 halfSecondUpdateIntervalId 来实现。

(五)音频播放功能 - playAudio 函数

  1. 使用 recordedChunks 数组创建一个 Blob 对象,指定类型为 audio/mp3,表示创建的 Blob 是一个音频文件,格式为 MP3。
  2. 通过 URL.createObjectURL 方法创建一个对象 URL,该 URL 指向创建的音频 Blob 对象,以便在浏览器中播放音频。
  3. 创建一个 Audio 元素实例,传入创建的对象 URL,然后调用 play 方法播放音频,从而实现播放录制的音频功能。

(六)音频转换为 Base64 功能 - convertAudioToBase64 函数

  1. 创建一个 FileReader 实例,用于读取文件数据并转换为特定格式。
  2. 使用 recordedChunks 数组创建一个音频 Blob 对象,类型为 audio/mp3
  3. FileReaderonloadend 事件注册回调函数,当读取操作完成时,将读取结果(即音频的 Base64 编码数据)赋值给 audioBase64.value,以便在界面上显示音频的 Base64 数据。
  4. 如果音频 Blob 对象存在,调用 reader.readAsDataURL 方法开始读取音频数据并转换为 Base64 格式。

(七)生命周期钩子函数

  1. onMounted:在组件挂载时执行的生命周期钩子函数,目前该函数体为空,可根据实际需求在组件挂载后进行一些初始化操作,如设置界面元素的初始状态或注册一些全局事件监听等。
  2. onUnmounted:在组件卸载时执行的生命周期钩子函数。在该函数中,如果 audioStream 存在,遍历其音频轨道并停止音频流,释放音频设备资源;如果 audioContext 存在且未关闭,调用 audioContext.close() 方法关闭音频上下文,确保在组件卸载时清理所有与音频相关的资源,避免内存泄漏和其他潜在问题。

四、代码的优势与可扩展性

  1. 功能完整性:该代码实现了音频录制的完整流程,包括开始录制、停止录制、播放录制音频、将音频转换为 Base64 格式以及实时音频频率分析和进度条展示等功能,能够满足大多数基本的音频处理需求。
  2. 实时反馈:通过音频分析器和定时器的配合,实现了音频频率的实时分析和进度条的实时更新,为用户提供了直观的音频录制状态反馈,增强了用户体验。
  3. 可扩展性:代码结构相对清晰,各个功能模块相对独立,易于进行扩展和修改。例如,可以进一步优化音频分析算法,增加更多音频特效处理功能,或者与后端服务器进行交互,将录制的音频上传到服务器进行存储或进一步处理等。
  4. 兼容性:基于浏览器的标准 API(如 navigator.mediaDevices.getUserMediaMediaRecorderAudioContext 等)实现,在现代主流浏览器中具有较好的兼容性,可以方便地应用于各种基于浏览器的项目中,无论是桌面端还是移动端浏览器。

五、可能的优化方向

  1. 错误处理增强:目前代码中虽然对获取音频设备权限失败等错误进行了简单的控制台打印处理,但可以进一步完善错误处理机制,例如向用户显示友好的错误提示信息,引导用户检查设备设置或权限配置等。
  2. 音频格式支持多样化:目前代码中仅将录制的音频转换为 MP3 格式并进行处理,如果需要支持更多音频格式(如 WAV、OGG 等),可以进一步扩展代码,根据用户需求或系统配置动态选择音频格式进行处理。
  3. 性能优化:在音频分析和定时器操作过程中,可能会存在一定的性能开销,尤其是在处理长时间录制或高频率音频数据时。可以考虑优化音频分析算法,减少不必要的计算和数据处理,或者采用更高效的定时器管理策略,避免定时器累积和频繁触发导致的性能问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/938225.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Qt】按钮类控件:QPushButton、QRadioButton、QCheckBox、ToolButton

目录 QPushButton 例子: QRadioButton 例子: 按钮的常见信号函数 单选按钮分组 例子: QCheckButton 例子: QToolButton QWidget的常见属性及其功能对于它的派生类控件都是有效的(也就是Qt中的各种控件),包括…

SpringBoot3 升级介绍

优质博文:IT-BLOG-CN 一、项目背景 截止2023.05.18,springboot发布了最新版本3.1.0。而在我们开发项目中,springboot一直使用的是1.5.8版本(相差6年的维护更新)。版本差距较大,很多新功能未能得到使用。例如近几年Loom的兴起&am…

运筹说 第130期 | 对策论引言

通过对对策论基础知识进行梳理和总结,小编绘制了《对策论思维导图》,如下图所示,对策论章节一共包含4个小节。 第1小节是对策论引言。介绍了对策论的基本概念,包含对策行为和对策论、对策现象的三要素、对策问题举例及对策的分类…

Windows 与 Linux 下 Ping IPv6 地址 | 常用网络命令

注:本文为网络命令相关文章合辑。 未整理去重。 一、IPv6 概述 IPv6 即 “Internet 协议版本 6”,因 IPv4 地址资源面临耗尽问题而被引入以替代 IPv4。IPv6 则提供了理论上多达 2 128 2^{128} 2128 个地址,有效解决地址不足困境。 IPv6 具…

密码学——密码学概述、分类、加密技术(山东省大数据职称考试)

大数据分析应用-初级 第一部分 基础知识 一、大数据法律法规、政策文件、相关标准 二、计算机基础知识 三、信息化基础知识 四、密码学 五、大数据安全 六、数据库系统 七、数据仓库. 第二部分 专业知识 一、大数据技术与应用 二、大数据分析模型 三、数据科学 密码学 大数据…

Android Studio、JDK、AGP、Gradle、kotlin-gradle-plugin 兼容性问题

文章目录 问题:解决办法:gradle与 java的版本兼容AGP与Gradle的版本兼容kotlin 与 jvm 的版本兼容KGP、Gradle、AGP兼容关系kotlin 与 java 的编译版本配置 问题: 你从githb上clone了一个项目,本地跑的时候,各种报错。…

ChatGPT搜索全新升级,向全体用户开放,近屿智能助力AI行业发展

12月17日,OpenAI在第八天直播中正式宣布ChatGPT搜索功能全面升级,并即日起对所有ChatGPT用户开放。此次更新不仅带来了显著的性能提升,还引入了多项突破性功能,如更快的搜索速度、全新的地图体验以及YouTube视频嵌入,为…

VSCode编辑+GCC for ARM交叉编译工具链+CMake构建+OpenOCD调试(基于STM32的标准库/HAL库)

本文以【STM32F103ZET6】单片机作为示例来进行演示,标准库/HAL库的工程是通用的,修改CMakeLists.txt里面的源文件和头文件引用部分即可。 更多细节请参考【VSCode编辑GCC for ARM交叉编译工具链Makefile构建OpenOCD调试(基于STM32的标准库&am…

ResNet网络:深度学习中的革命性架构

目录 ​编辑 引言 ResNet网络的特点 1. 残差块(Residual Block) 2. 恒等映射(Identity Mapping) 3. 深层网络训练 4. Batch Normalization 5. 全局平均池化 6. 灵活的结构 ResNet的应用案例 ResNet的研究进展 实战案例…

Axure9设置画布固定

在使用AxureRP9设计原型时,如果遇到画布在拖动时变得难以控制,可以尝试在Windows系统中通过‘文件’>‘首选项’,或在Mac系统中通过‘AxureRP9’>‘偏好设置’进行设置,以稳定画布的行为。 现象 页面底层的画布&#xff0…

景联文科技入选中国信通院发布的“人工智能数据标注产业图谱”

近日,由中国信息通信研究院、中国人工智能产业发展联盟牵头,联合中国电信集团、沈阳市数据局、保定高新区等70多家单位编制完成并发布《人工智能数据标注产业图谱》。景联文科技作为人工智能产业关键环节的代表企业,入选图谱中技术服务板块。…

ESlint代码规范,手动与自动修复

规范说明 规则参考 - ESLint - 插件化的 JavaScript 代码检查工具 规范说明 ​ ​ 可看到是main.js文件报错分别是第三行第30个字符,以及第七行第一个字符 后面则是规范说明,可以根据说明查找相应的规范 一.手动修正 ctrl f 可以搜索 二.自动修正 …

一条线上的点

给你一个数组 points &#xff0c;其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。 提示&#xff1a; 1 < points.length < 300points[i].length 2-104 < xi, yi < 104points 中的所有点 互不相同 解析&#xff1a;使用斜…

wxpython图形用户界面编程

wxpython图形用户界面编程 一、wxpython的基础 1.1 wxpython的基础 作为图形用户界面开发工具包 wxPython&#xff0c;主要提供了如下 GUI 内容&#xff1a; 窗口。控件。事件处理。布局管理。 1.2 wxpython的类层次机构 1.3 wxpython的安装 Windows 和 macOS 平台安装&a…

【优选算法篇】位运算小课堂:从入门到精通的奇妙之旅(上篇)

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…

pytest入门九:feature

fixture是pytest特有的功能&#xff0c;用以在测试执行前和执行后进行必要的准备和清理工作。使用pytest.fixture标识&#xff0c;定义在函数前面。在你编写测试函数的时候&#xff0c;你可以将此函数名称做为传入参数&#xff0c;pytest将会以依赖注入方式&#xff0c;将该函数…

Day9 神经网络的偏导数基础

多变量函数与神经网络 在神经网络中&#xff0c;我们经常遇到多变量函数。这些函数通常描述了网络的输入、权重、偏置与输出之间的关系。例如&#xff0c;一个简单的神经元输出可以表示为&#xff1a; z f ( w 1 x 1 w 2 x 2 … w n x n b ) z f(w_1x_1 w_2x_2 \ldots…

sg-exam:Star 2.2k,一套完善的在线教育平台,支持在线考试、在线学习,教育项目用它就没有错~~

​嗨&#xff0c;大家好&#xff0c;我是小华同学&#xff0c;关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 sg-exam是一个基于Java语言的在线考试系统&#xff0c;它集成了试卷管理、试题管理、考试安排、在线作答、自动阅卷等功能。该项目旨在帮助教育机构…

ArkTS中string和String/number和Number类型大小写的区别

ArkTS和TypeScript类似&#xff0c;string 和 String&#xff0c;number 和 Number 之间有一些重要的区别&#xff1a; 基本类型与对象类型 基本类型 (string, number)&#xff1a; string 和 number 是基本数据类型&#xff0c;用于表示原始值。例如&#xff1a;let str: str…

Ubuntu22.04切换gcc版本教程

在编译安装程序的时候,由于gcc版本过高,导致编译无法通过,需要降低gcc版本。 一、安装gcc版本 根据自己的需求安装gcc版本。 sudo apt update sudo apt install gcc-10 g++-10二、切换gcc版本 sudo update-alternatives --install /usr/bin/gcc gcc