在h5端实现录音发送功能(兼容内嵌微信小程序) recorder-core

本文将通过一个实际的 Vue3 组件示例,带你一步步实现“按住录音,松开发送,上滑取消”的语音录制功能。

我们将使用强大且小巧的开源库 recorder-core,支持 MP3、WAV、AAC 等编码格式,兼容性较好。

🔧 项目依赖

pnpm add recorder-core dayjs
# 或
npm install recorder-core dayjs

我们实现的组件是一个 input 输入框,按下开始录音,松开结束录音,上滑取消录音。核心逻辑全部由 recorder-core 管理。

✅ 权限处理机制

第一次调用 rec.open() 时会触发麦克风授权窗口,用户点击「允许」后才能真正录音。所以我们用 isAuthorized 标记避免重复弹窗。


✅ 录音时间和状态展示

我们通过 onProcess() 回调实时拿到录音时间和音量等级,再结合 dayjs 把时间格式化展示在 UI 上(audioLoading.vue 可以自定义成动画弹窗或语音时长条等)。


✅ 录音取消(上滑手势)

录音时用户可能不想发送,我们监听 @touchmove 来模拟“上滑取消”操作,直接关闭并丢弃录音。

完整代码如下

<template><inputdisabled="true"placeholder="按住 说话"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd"/><AudioLoading :audioLoading="audioLoading" :audioTime="audioTime" />
</template><script setup>import { ref } from 'vue';import dayjs from 'dayjs';import Recorder from 'recorder-core';import 'recorder-core/src/engine/mp3'; // mp3 封装import 'recorder-core/src/engine/mp3-engine'; // mp3 编码核心模块const audioLoading = ref(false); //语音弹框const audioTime = ref(0); //语音时间const isAuthorized = ref(false); // 是否授权import AudioLoading from './audioLoading.vue';
function formatDateToss(inputStr) {return dayjs(inputStr).format('mm:ss');}let rec = null;/*长按开始录制语音*/const handleTouchStart = e => {audioTime.value = 0;rec = Recorder({type: 'mp3',sampleRate: 16000,bitRate: 16,onProcess(buffers, powerLevel, duration, sampleRate) {audioLoading.value = true;audioTime.value = formatDateToss(duration);},});rec.open(() => {if (isAuthorized.value) {rec.start();}isAuthorized.value = true;},(msg, isUserNotAllow) => {audioLoading.value = false;console.log('停止录音失败: ' + msg);},);};/*语音录制结束*/const handleTouchEnd = () => {audioLoading.value = false;rec.stop((blob, duration) => {rec.close();const url = URL.createObjectURL(blob);console.log(url);},msg => {rec.close();console.log('停止录音失败: ' + msg);},);};//上滑取消const handleTouchMove = () => {rec.close();rec.stop();audioLoading.value = false;};
</script>

AudioLoading加载组件

<template><view class="modal-body" v-if="audioLoading"><view class="time">{{ audioTime }}</view><view class="sound-waves"><viewv-for="(item, index) in radomHeight":key="index":style="`height: ${item}rpx; margin-top: -${item / 2}rpx;`"></view><view style="clear: both; width: 0; height: 0"></view></view><view class="desc">松开发送,上滑取消</view></view>
</template><script setup>import { watch, ref } from 'vue';import { onLoad } from '@dcloudio/uni-app';const props = defineProps({audioTime: {type: Number,},audioLoading: {type: Boolean,default: false,},});const radomHeight = ref([50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,50, 50, 50,]);onLoad(() => {});let timer;watch(() => props.audioLoading,val => {if (val) {timer = setInterval(() => {myradom();}, 500);} else {clearInterval(timer);}},);const myradom = () => {let _radomheight = radomHeight.value;for (var i = 0; i < radomHeight.value.length; i++) {//+1是为了避免为0_radomheight[i] = 100 * Math.random().toFixed(2) + 10;}radomHeight.value = _radomheight;};
</script><style scoped lang="scss">.modal-body {position: fixed;top: 500rpx;left: 235rpx;width: 280rpx;height: 280rpx;background: rgba(0, 0, 0, 0.75);border-radius: 16rpx;backdrop-filter: blur(20rpx);box-sizing: border-box;padding-top: 40rpx;}.time {width: 100%;text-align: center;font-size: 28rpx;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;color: #ffffff;}.sound-waves {width: 100%;box-sizing: border-box;padding-left: 10%;margin-top: 70rpx;height: 50rpx;text-align: center;}.sound-waves view {transition: all 0.5s;width: 1%;margin-left: 1.5%;margin-right: 1.5%;height: 100rpx;background-color: #ffffff;float: left;}.desc {width: 100%;font-size: 30rpx;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;color: #ffffff;line-height: 42rpx;text-align: center;margin-top: 20rpx;}.record-btn {width: 584rpx;height: 74rpx;line-height: 74rpx;text-align: center;background: #ffffff;border-radius: 16rpx;font-size: 32rpx;font-family: PingFangSC-Semibold, PingFang SC;font-weight: 600;color: #000000;}.record-btn::after {border: none;}
</style>

注意如果内嵌到微信小程序中开发环境 会直接拒绝权限

必须部署到http环境才可以

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

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

相关文章

深入掌握Node.js HTTP模块:从开始到放弃

文章目录 一、HTTP模块入门&#xff1a;从零搭建第一个服务器1.1 基础概念解析1.2 手把手创建服务器 二、核心功能深入解析2.1 处理不同请求类型2.2 实现文件下载功能 三、常见问题解决方案3.1 跨域问题处理3.2 防止服务崩溃3.3 调试技巧 四、安全最佳实践4.1 请求头安全设置4.…

SSM整合:Spring+SpringMVC+MyBatis完美融合实战指南

前言 在Java企业级开发领域&#xff0c;SSM&#xff08;SpringSpringMVCMyBatis&#xff09;框架组合一直占据着重要地位。这三个轻量级框架各司其职又相互配合&#xff0c;为开发者提供了高效、灵活的开发体验。本文将深入探讨SSM框架的整合过程&#xff0c;揭示整合背后的原…

[AI]大模型MCP快速入门及智能体执行模式介绍

[AI]大模型MCP快速入门及智能体执行模式介绍 一、MCP入门 介绍 MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;是一种由Anthropic公司于2024年提出的开放标准协议&#xff0c;旨在为大型语言模型&#xff08;LLM&#xff09;提供统一接口&am…

Mac M1 安装 ffmpeg

1.前言 官网那货没有准备m系列的静态包&#xff0c;然后我呢&#xff0c;不知道怎么想的就从maven项目中的 javacv-platform&#xff0c;且版本为1.5.11依赖里面将这个静态包把了出来&#xff0c;亲测能用&#xff0c;感觉比那些网上说的用什么wget编译安装、brew安装快多了。…

unity控制相机围绕物体旋转移动

记录一下控制相机围绕物体旋转与移动的脚本&#xff0c;相机操作思路分为两块&#xff0c;一部分为旋转&#xff0c;一部分为移动&#xff0c;旋转是根据当前center中心点的坐标&#xff0c;根据距离设置与默认的旋转进行位置移动&#xff0c;移动是根据相机的左右和前后进行计…

python打卡day38@浙大疏锦行

知识点回顾&#xff1a; Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09;Dataloader类minist手写数据集的了解 作业&#xff1a;了解下cifar数据集&#xff0c;尝试获取其中一张图片 一、首先加载CIFAR数据集 import torch import torchvi…

用户配置文件(Profile)

2.4.5 用户配置文件&#xff08;Profile&#xff09; 用户配置文件由以下组件构成&#xff1a; 一个运营商安全域&#xff08;MNO-SD&#xff09; 辅助安全域&#xff08;SSD&#xff09;和CASD Applets 应用程序&#xff08;如NFC应用&#xff09; 网络接入应用&#xff…

如何给自研MCP加上安全验证

前言 刚过去两个月,市面的 MCP 服务,如雨后春笋一般不断涌现出来,包括;百度、高德、网盘、支付宝。这些 MCP 服务,可以让我们基于 Spring AI 框架构建的 Agent 具备非常丰富的使用功能。同时这也说明,程序员👨🏻‍💻,应该具备开发 MCP 服务的能力,Spring AI 让 J…

Unity网络开发实践项目

摘要&#xff1a;该网络通信系统基于Unity实现&#xff0c;包含以下几个核心模块&#xff1a; 协议配置&#xff1a;通过XML定义枚举&#xff08;如玩家/英雄类型&#xff09;、数据结构&#xff08;如PlayerData&#xff09;及消息协议&#xff08;如PlayerMsg&#xff09;&a…

OpenCV CUDA模块图像过滤------创建一个 Sobel 滤波器函数createSobelFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于创建一个 Sobel 滤波器&#xff0c;用于在 GPU 上进行边缘检测。它基于图像的梯度计算&#xff1a; dx 表示对 x 方向求导的阶数&…

【JavaSE】枚举和注解学习笔记

枚举和注解 -枚举 规定多选一数据类型的解决方案-枚举 枚举对应英文(enumeration,简写 enum) 2)枚举是一组常量的集合。 3)可以这里理解:枚举属于一种特殊的类&#xff0c;里面只包含一组有限的特定的对象。 枚举的两种实现方式 自定义实现枚举 使用enum关键字实现枚举 自…

Spark SQL进阶:解锁大数据处理的新姿势

目录 一、Spark SQL&#xff0c;为何进阶&#xff1f; 二、进阶特性深剖析 2.1 窗口函数&#xff1a;数据洞察的新视角 2.2 高级聚合&#xff1a;挖掘数据深度价值 2.3 自定义函数&#xff08;UDF 和 UDTF&#xff09;&#xff1a;拓展功能边界 三、性能优化实战 3.1 数…

如何利用 Conda 安装 Pytorch 教程 ?

如何利用 Conda 安装 Pytorch 教程 &#xff1f; 总共分为六步走&#xff1a; &#xff08;1&#xff09;第一步&#xff1a;验证conda 环境是否安装好&#xff1f; 1) conda -V2) conda --version&#xff08;2&#xff09;第二步&#xff1a;查看现有环境 conda env list…

什么是HTTP

HTTP&#xff08;HyperText Transfer Protocol&#xff09;是万维网数据通信的基础协议&#xff0c;作为应用层协议具有以下关键特性&#xff1a; 客户端-服务器模型&#xff1a;基于请求/响应模式 无状态协议&#xff1a;默认不保留通信状态 可扩展性&#xff1a;通过首部字…

2025-05-27 学习记录--Python-模块

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、模块 ⭐️ &#xff08;一&#xff09;模块的导入与使用 &#x1f36d; 模块的导入&#xff1a;&#x1f41d; 模块 就好比…

leetcode 131. Palindrome Partitioning

目录 一、题目描述 二、方法1、回溯法每次暴力判断回文子串 三、方法2、动态规划回溯法 一、题目描述 分割回文子串 131. Palindrome Partitioning 二、方法1、回溯法每次暴力判断回文子串 class Solution {vector<vector<string>> res;vector<string>…

重构开发范式!飞算JavaAI革新Spring Cloud分布式系统开发

分布式系统凭借高可用性、可扩展性等核心优势&#xff0c;成为大型软件项目的标配架构。Spring Cloud作为Java生态最主流的分布式开发框架&#xff0c;虽被广泛应用于微服务架构搭建&#xff0c;但其传统开发模式却面临效率瓶颈——从服务注册中心配置到网关路由规则编写&#…

python 生成复杂表格,自动分页等功能

py&#xff54;&#xff48;&#xff4f;&#xff4e; 生成复杂表格&#xff0c;自动分页等功能 解决将Python中的树形目录数据转换为Word表格&#xff0c;并生成带有合并单元格的检测报告的问题。首先&#xff0c;要解决“tree目录数据”和“Word表格互换”&#xff0c;指将树…

根据Cortex-M3(包括STM32F1)权威指南讲解MCU内存架构与如何查看编译器生成的地址具体位置

首先我们先查看官方对于Cortex-M3预定义的存储器映射 1.存储器映射 1.1 Cortex-M3架构的存储器结构 内部私有外设总线&#xff1a;即AHB总线&#xff0c;包括NVIC中断&#xff0c;ITM硬件调试&#xff0c;FPB, DWT。 外部私有外设总线&#xff1a;即APB总线&#xff0c;用于…

Linux中硬件信息查询利器——lshw命令详解!

lshw&#xff08;List Hardware&#xff09;是 Linux 系统下的一款命令行工具&#xff0c;用于全面检测并显示详细的硬件信息。它能够报告 CPU、内存、主板、存储设备、显卡、网络设备等几乎所有硬件组件的详细信息&#xff0c;适用于系统管理、故障排查和硬件兼容性检查等场景…