web网页上实现录音功能(vue3)

文章目录

    • 一. 前言
    • 二. 技术实现
        • 1.核心API介绍
        • 2.模板部分
        • 3.核心逻辑实现
      • 4. 关键功能点解析
    • 三. 完整代码
    • 四. 功能扩展建议

一. 前言

在Web开发中实现音频录制功能是许多应用场景的常见需求。本文将通过一个完整的Vue 3组件示例,详细解析如何利用现代浏览器API实现网页端的录音功能。

二. 技术实现

1.核心API介绍

MediaRecorder API 是实现录音功能的核心,它允许我们直接捕获来自用户设备的媒体流。主要方法:

getUserMedia() 获取媒体设备权限
MediaRecorder() 创建录音实例
ondataavailable 接收音频数据
onstop 处理录音结束事件

2.模板部分
<template><div class="voice-recorder"><!-- 录音控制 --><button @click="toggleRecording" :class="{ recording: isRecording }">{{ isRecording ? "停止录音" : "开始录音" }}</button><!-- 生成的音频文件列表 --><div v-if="audioFiles.length > 0" class="audio-list"><div v-for="(audio, index) in audioFiles" :key="index"><audio controls :src="audio.url"></audio></div></div></div>
</template>
3.核心逻辑实现
const isRecording = ref(false);
const mediaRecorder = ref(null);
const audioChunks = ref([]);
const audioFiles = ref([]);
// 开始录音
const startRecording = async (e) => {if (isRecording.value) return;try {audioChunks.value = [];const stream = await navigator.mediaDevices.getUserMedia({ audio: true });mediaRecorder.value = new MediaRecorder(stream);mediaRecorder.value.ondataavailable = (e) => {audioChunks.value.push(e.data);};mediaRecorder.value.onstop = () => {const audioBlob = new Blob(audioChunks.value, { type: "audio/webm" });const audioURL = URL.createObjectURL(audioBlob);audioFiles.value.push({name: `recording_${Date.now()}.${getFileExtension(audioBlob.type)}`,url: audioURL,});audioChunks.value = [];};mediaRecorder.value.start();isRecording.value = true;} catch (error) {console.error("录音错误:", error);}
};

4. 关键功能点解析

(1) 音频格式处理
通过MIME类型映射获取文件扩展名:

// 获取文件扩展名
const getFileExtension = (mimeType) => {const extensions = {"audio/webm": "webm","audio/ogg": "ogg","audio/mp4": "mp4","audio/mpeg": "mp3","audio/wav": "wav",};return extensions[mimeType] || "webm";
};

(2) 资源管理
组件卸载时自动释放资源:

//停止录音
const stopRecording = () => {console.log("停止录音");isRecording.value = false;if (mediaRecorder.value) {mediaRecorder.value.stop();mediaRecorder.value.stream.getTracks().forEach((track) => track.stop());}
};
// 清理资源
onUnmounted(() => {stopRecording();
});

在这里插入图片描述

三. 完整代码

<template><div class="voice-recorder"><!-- 录音控制 --><button @click="toggleRecording" :class="{ recording: isRecording }">{{ isRecording ? "停止录音" : "开始录音" }}</button><!-- 生成的音频文件列表 --><div v-if="audioFiles.length > 0" class="audio-list"><div v-for="(audio, index) in audioFiles" :key="index"><audio controls :src="audio.url"></audio></div></div></div>
</template><script setup>
const isRecording = ref(false);
const mediaRecorder = ref(null);
const audioChunks = ref([]);
const audioFiles = ref([]);// 开始录音
const startRecording = async (e) => {if (isRecording.value) return;try {audioChunks.value = [];const stream = await navigator.mediaDevices.getUserMedia({ audio: true });mediaRecorder.value = new MediaRecorder(stream);mediaRecorder.value.ondataavailable = (e) => {audioChunks.value.push(e.data);};mediaRecorder.value.onstop = () => {const audioBlob = new Blob(audioChunks.value, { type: "audio/webm" });const audioURL = URL.createObjectURL(audioBlob);audioFiles.value.push({name: `recording_${Date.now()}.${getFileExtension(audioBlob.type)}`,url: audioURL,});audioChunks.value = [];};mediaRecorder.value.start();isRecording.value = true;} catch (error) {console.error("录音错误:", error);}
};//停止录音
const stopRecording = () => {console.log("停止录音");isRecording.value = false;if (mediaRecorder.value) {mediaRecorder.value.stop();mediaRecorder.value.stream.getTracks().forEach((track) => track.stop());}
};// 获取文件扩展名
const getFileExtension = (mimeType) => {const extensions = {"audio/webm": "webm","audio/ogg": "ogg","audio/mp4": "mp4","audio/mpeg": "mp3","audio/wav": "wav",};return extensions[mimeType] || "webm";
};// 切换录音状态
const toggleRecording = () => {if (!isRecording.value) {startRecording();} else {if (mediaRecorder.value) {mediaRecorder.value.stop();mediaRecorder.value.stream.getTracks().forEach((track) => track.stop());}}isRecording.value = !isRecording.value;
};// 清理资源
onUnmounted(() => {stopRecording();
});
</script><style lang="scss" scoped>
.voice-recorder {max-width: 800px;margin: 0 auto;padding: 20px;button {padding: 12px 24px;background: #42b983;color: white;border: none;border-radius: 6px;cursor: pointer;transition: background 0.3s;&.recording {background: #ff4444;}}button:hover {background: #3aa876;}button:disabled {background: #ddd;cursor: not-allowed;}
}.recording {background-color: #ff4444;color: white;
}.audio-list {margin-top: 20px;
}
</style>

四. 功能扩展建议

添加录音时长显示
实现音频波形可视化

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

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

相关文章

安美数字酒店宽带运营系统存在SQL注入漏洞

免责声明&#xff1a;本号提供的网络安全信息仅供参考&#xff0c;不构成专业建议。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权&#xff0c;请及时与我联系&#xff0c;我将尽快处理并删除相关内容。 漏洞描述 安美数字酒店宽带运营系统的lang…

206. 反转链表 92. 反转链表 II 25. K 个一组翻转链表

leetcode Hot 100系列 文章目录 一、翻转链表二、反转链表 II三、K 个一组翻转链表总结 一、翻转链表 建立pre为空&#xff0c;建立cur为head&#xff0c;开始循环&#xff1a;先保存cur的next的值&#xff0c;再将cur的next置为pre&#xff0c;将pre前进到cur的位置&#xf…

【区块链安全 | 第十七篇】类型之引用类型(一)

文章目录 引用类型数据存储位置分配行为 数组特殊数组&#xff1a;bytes 和 string 类型bytes.concat 和 string.concat 的功能分配 memory 数组数组字面量&#xff08;Array Literals&#xff09;二维数组字面量数组成员&#xff08;Array Members&#xff09;悬空引用&#x…

selenium和pytessarct提取古诗文网的验证码(python爬虫)

代码实现的主要功能&#xff1a; 浏览器自动化控制 验证码图像获取与处理 OCR验证码识别 表单自动填写与提交 登录状态验证 异常处理与资源清理 1. 浏览器初始化与页面加载 driver webdriver.Chrome() driver.get("https://www.gushiwen.cn/user/login.aspx?fro…

【输入某年某日,判断这是这一年的第几天】

for语句和switch语句分别实现 文章目录 前言 一、用switch做 二、用for循环做 ​编辑 总结 前言 用两种不同的方法求解【输入某年某日&#xff0c;判断这是这一年的第几天】 一、用switch做 代码如下&#xff08;示例&#xff09;&#xff1a; int main() {int y, m, d, cou…

香港理工视觉语言模型赋能智能制造最新综述!基于视觉语言模型的人机协作在智能制造中的应用

作者&#xff1a;Junming FAN 1 ^{1} 1, Yue YIN 1 ^{1} 1, Tian WANG 1 ^{1} 1, Wenhang DONG 1 ^{1} 1, Pai ZHENG 1 ^{1} 1, Lihui WANG 2 ^{2} 2单位&#xff1a; 1 ^{1} 1香港理工大学工业及系统工程系&#xff0c; 2 ^{2} 2瑞典皇家理工学院论文标题&#xff1a; Vision-…

大智慧前端面试题及参考答案

如何实现水平垂直居中? 在前端开发中,实现元素的水平垂直居中是一个常见的需求,以下是几种常见的实现方式: 使用绝对定位和负边距:将元素的position设置为absolute,然后通过top、left属性将其定位到父元素的中心位置,再使用负的margin值来调整元素自身的偏移,使其水平垂…

算法基础_基础算法【高精度 + 前缀和 + 差分 + 双指针】

算法基础_基础算法【高精度 前缀和 差分 双指针】 ---------------高精度---------------791.高精度加法题目介绍方法一&#xff1a;代码片段解释片段一&#xff1a; 解题思路分析 792. 高精度减法题目介绍方法一&#xff1a;代码片段解释片段一&#xff1a; 解题思路分析 7…

OkHttpHttpClient

学习链接 okhttp github okhttp官方使用文档 SpringBoot 整合okHttp okhttp3用法 Java中常用的HTTP客户端库&#xff1a;OkHttp和HttpClient&#xff08;包含请求示例代码&#xff09; 深入浅出 OkHttp 源码解析及应用实践 httpcomponents-client github apache httpclie…

DoDAF科普

摘要 DoDAF&#xff08;Department of Defense Architecture Framework&#xff0c;美国国防部架构框架&#xff09;是一种专门为复杂系统设计的标准化框架&#xff0c;广泛应用于军事和国防项目。它通过提供一致的架构描述方法&#xff0c;确保跨组织、跨国界的系统集成和互操…

搭建qemu环境

1.安装qemu apt install qemu-system2.编译内核 设置gcc软链接sudo ln -s arm-linux-gnueabihf-gcc arm-linux-gccsudo ln -s arm-linux-gnueabihf-ld arm-linux-ldsudo ln -s arm-linux-gnueabihf-nm arm-linux-nmsudo ln -s arm-linux-gnueabihf-objcopy arm-linux-objc…

使用Claude Desktop和MCP工具创建个人编程助手

最近我在Claude Desktop上试用了MCP工具,体验过程令人兴奋不已。 我花时间测试了多个用于编程场景的MCP服务器——而Claude本就擅长编程,这一组合可谓相得益彰。 这些工具赋予Claude强大的自主任务执行能力,比如仅通过聊天就能实现Vibe编程。当然,必须谨慎控制其访问权限…

K8S集群搭建 龙蜥8.9 Dashboard部署(2025年四月最新)

一、版本兼容性和服务器规划 组件版本/配置信息备注操作系统Anolis OS 8.9基于 Linux 5.10.134-17.3.an8.x86_64内核版本Linux 5.10.134-17.3.an8.x86_64与 Kubernetes 1.29 兼容架构x86-64Kubernetes 版本v1.29.5最新稳定版&#xff0c;兼容 Linux 5.10 内核Docker 版本24.0.…

项目6——前后端互通的点餐项目

一、项目介绍 1、有哪些需求需要连接后台完成功能? 前台传给后台 后台返回给前台 注册: 用户名 密码 操作是否成功 登录: 用户名 密码 操作是否成功 下单: 用户名 菜名 操作是否成功 Request : 前端发送给后台的所有数据的载体 Res…

Go和Golang语言简介

李升伟 整理 Go 和 Golang 实际上指的是同一种编程语言&#xff0c;只是名称不同。 Go 名称&#xff1a;Go 是该编程语言的正式名称。 起源&#xff1a;由 Google 的 Robert Griesemer、Rob Pike 和 Ken Thompson 于 2007 年开始设计&#xff0c;2009 年正式发布。 设计目…

GitHub二次验证登录2FA(Enable two-factor authentication )

不用下载app&#xff0c;点击二维码下面的setup key获取到secret并且保存好 接下来几行代码就可以解析了。 添加依赖 <dependency><groupId>com.amdelamar</groupId><artifactId>jotp</artifactId><version>1.3.0</version> </d…

RabbitMQ技术方案分析

方案分析 在上一篇文档中&#xff0c;详细讲述了如何通过CanalMQ实现对分库分表的数据库和数据表进行数据同步&#xff0c;而在这个方案中&#xff0c;还有一个关键点是需要注意的&#xff1a;首先&#xff0c;数据增删改的信息是保证写入binlog的&#xff0c;Canal解析出增删…

node.js版本管理

概述 遇到了版本升级后&#xff0c;以前项目不兼容的问题。 下载一个node.js的版本管理工具&#xff0c;官网下载地址&#xff0c;可以选择版本下载&#xff0c;我选择的1.11.1版本的。下载完成后点击安装&#xff0c;分别选择nvm安装目录和nodejs的安装目录&#xff0c;点击安…

leetcode-热题100(3)

leetcode-74-搜索二维矩阵 矩阵最后一列升序排序&#xff0c;在最后一列中查找第一个大于等于target的元素 然后在该元素所在行进行二分查找 bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {int n matrixSize;int m matrixColSize[0];in…

在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面

大家好&#xff0c;我是 V 哥。 《鸿蒙 HarmonyOS 开发之路 卷1 ArkTS篇》已经出版上市了哈&#xff0c;有需要的朋友可以关注一下&#xff0c;卷2应用开发篇也马上要出版了&#xff0c;V 哥正在紧锣密鼓的写鸿蒙开发实战卷3的教材&#xff0c;卷3主要以项目实战为主&#xff0…