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. 性能优化:在音频分析和定时器操作过程中,可能会存在一定的性能开销,尤其是在处理长时间录制或高频率音频数据时。可以考虑优化音频分析算法,减少不必要的计算和数据处理,或者采用更高效的定时器管理策略,避免定时器累积和频繁触发导致的性能问题。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【jpa】会什么jpa会自动新建一个hibernate_sequence表

目录 1. 说明2. 主键生成策略3. hibernate_sequence表的创建4. 如何避免自动创建hibernate_sequence表 1. 说明 1.JPA(Java Persistence API)在默认情况下,如果使用Hibernate作为持久化框架,并且没有显式指定主键生成策略&#x…

秒优科技-供应链管理系统 login/doAction SQL注入漏洞复现

0x01 产品简介 秒优科技提供的供应链管理系统,即秒优SCM服装供应链管理系统,是一款专为服装电商企业设计的全方位解决方案。是集款式研发、订单管理、物料管理、生产管理、工艺管理、收发货管理、账单管理、报表管理于一体的服装电商供应链管理解决方案。它涵盖了从企划到开…

【TF-IDF】Hugging Face Model Recommendation System

利用了机器学习技术的模型检索 TF-IDF (Term Frequency-Inverse Document Frequency) 文本特征提取例子This project is a Hugging Face Model Recommendation System designed to assist users in discovering the most suitable models based on their task descriptions. Th…

136.WEB渗透测试-信息收集-小程序、app(7)

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易锦网校会员专享课 上一个内容:135.WEB渗透测试-信息收集-小程序、app(6) 进入之后我们通过输入…

samout llm解码 幻觉更低更稳定

这段代码定义了一个简单的对话生成系统,包括模型加载、词汇表加载、以及基于给定提示生成文本的功能。下面是对代码的解析: load_model_and_voc(device"cpu"): 该函数用于加载预训练的模型和词汇表(vocabulary)。它首先…

K近邻原理和距离

K近邻 基本思想欧氏距离算法流程代码基于近邻用户的协同过滤基于近邻物品的协同过滤杰卡德相似度 基本思想 我们根据涂色样本点和未涂色样本点 X 的距离给涂色样本点编号1-6,即:1号样本点距离X最近,其余次之。 那么问题来了:样本…

Transformer 中 Self-Attention 的二次方复杂度(Quadratic Complexity )问题及改进方法:中英双语

Transformer 中 Self-Attention 的二次方复杂度问题及改进方法 随着大型语言模型(LLM)输入序列长度的增加,Transformer 结构中的核心模块——自注意力机制(Self-Attention) 的计算复杂度和内存消耗都呈现二次方增长。…

模型 A/B测试(科学验证)

系列文章 分享 模型,了解更多👉 模型_思维模型目录。控制变量法。 1 A/B测试的应用 1.1 Electronic Arts(EA)《模拟城市》5游戏网站A/B测试 定义目标: Electronic Arts(EA)在发布新版《模拟城…

Java修饰符详解:从基础到高级用法

在Java编程语言中,有许多修饰符可以使用,它们大致可以分为两大类:访问控制修饰符、其他类型的修饰符。 这些修饰符主要用于指定类、方法或变量的特性,并且通常位于声明语句的开头部分。下面通过一些示例来进一步说明这一点&#…

onnx文件转pytorch pt模型文件

onnx文件转pytorch pt模型文件 1.onnx2torch转换及测试2.存在问题参考文献 从pytorch格式转onnx格式,官方有成熟的API;那么假如只有onnx格式的模型文件,该怎样转回pytorch格式? https://github.com/ENOT-AutoDL/onnx2torch提供了…

Git merge 和 rebase的区别(附图)

在 Git 中,merge 和 rebase 是两种用于整合分支变化的方法。虽然它们都可以将一个分支的更改引入到另一个分支中,但它们的工作方式和结果是不同的。以下是对这两者的详细解释: Git Merge 功能:合并分支,将两个分支的…

【Web】0基础学Web—js运算符、选择结构、循环结构

0基础学Web—js运算符、选择结构、循环结构 js运算符选择结构循环结构 js运算符 算术运算符: - * / %取余 赋值运算符: - * / % 单目运算符: i i --i i– 单独使用是自增1 或 自减1 如果被使用&#xff0c;先看到啥先操作啥 比较运算符&#xff1a; > 、 >、 < 、…

系列3:基于Centos-8.6 Kubernetes使用nfs挂载pod的应用日志文件

每日禅语 古代&#xff0c;一位官员被革职遣返&#xff0c;心中苦闷无处排解&#xff0c;便来到一位禅师的法堂。禅师静静地听完了此人的倾诉&#xff0c;将他带入自己的禅房之中。禅师指着桌上的一瓶水&#xff0c;微笑着对官员说&#xff1a;​“你看这瓶水&#xff0c;它已经…

tkdiff安装:Linux下文本对比工具

tkdiff在Linux下源码安装 1.下载解压2.编译安装3.配置环境变量4.验证及运行 本文&#xff0c;在Linux下使用源码安装tkdiff工具&#xff0c;以tkdiff-4.2版本为例&#xff0c;其他版本根据需要替换即可。 1.下载解压 去 http://sourceforge.net/projects/tkdiff/files/tkdiff…

耐蚀镍基合金的焊接技术与质量控制

耐蚀镍基合金是一类在腐蚀环境中具有优异性能的合金材料&#xff0c;广泛应用于化工、海洋工程、石油天然气等领域。其焊接技术与质量控制对于确保合金的使用性能和安全性至关重要。以下是对耐蚀镍基合金焊接技术与质量控制的详细探讨。 一、焊接技术 焊条选择 耐蚀镍基合金的焊…

Django REST framework(DRF)在处理不同请求方法时的完整流程

文章目录 一、POST 请求创建对象的流程二、GET 请求获取对象列表的流程三、GET 请求获取单个对象的流程四、PUT/PATCH 请求更新对象的流程五、自定义方法的流程自定义 GET 方法自定义 POST 方法 一、POST 请求创建对象的流程 请求到达视图层 方法调用&#xff1a; dispatch说明…

机器视觉与OpenCV--01篇

计算机眼中的图像 像素 像素是图像的基本单位&#xff0c;每个像素存储着图像的颜色、亮度或者其他特征&#xff0c;一张图片就是由若干个像素组成的。 RGB 在计算机中&#xff0c;RGB三种颜色被称为RGB三通道&#xff0c;且每个通道的取值都是0到255之间。 计算机中图像的…

qemu源码解析【03】qom实例

目录 qemu源码解析【03】qom实例arm_sbcon_i2c实例 qemu源码解析【03】qom实例 arm_sbcon_i2c实例 以hw/i2c/arm_sbcon_i2c.c代码为例&#xff0c;这个实例很简单&#xff0c;只用100行左右的代码&#xff0c;调用qemu系统接口实现了一个i2c硬件模拟先看include/hw/i2c/arm_s…

小程序自定义tab-bar,踩坑记录

从官方下载代码 https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html 1、把custom-tab-bar 文件放置 pages同级 修改下 custom-tab-bar 下的 JS文件 Component({data: {selected: 0,color: "#7A7E83",selectedColor: "#3…

操作系统(14)请求分页

前言 操作系统中的请求分页&#xff0c;也称为页式虚拟存储管理&#xff0c;是建立在基本分页基础上&#xff0c;为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能的一种内存管理技术。 一、基本概念 分页&#xff1a;将进程的逻辑地址空间分成若干个大小相等的页&am…