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

前端h5录音

时隔差不多半个月, 现在才来写这编博客。由于某些原因,我一直没有写,请大家原谅。前段时间开发了一个小模块。模块的主要功能就是有一个录音的功能。也就是说,模仿微信发送语音的功能一样。不多说,直接来一段代码

//自定义长按事件,注意, directives是跟 data ,created() 同一级的,注意注意
directives: {longpress: {bind(el, binding, vnode) {let pressTimer = null;let maxPressTime = 60000; // 60秒 = 60000毫秒  let startCallback = binding.value.start || Vue.noop;let endCallback = binding.value.end || Vue.noop;function handlePress() {startCallback();pressTimer = setTimeout(() => {endCallback();clearTimeout(pressTimer);pressTimer = null;}, maxPressTime);}function handleRelease() {if (pressTimer) {clearTimeout(pressTimer);pressTimer = null;endCallback();}}// 确保这些函数在unbind中可用  el._handlePress = handlePress;el._handleRelease = handleRelease;// 添加事件监听器  el.addEventListener('mousedown', handlePress);el.addEventListener('touchstart', handlePress);el.addEventListener('mouseup', handleRelease);el.addEventListener('touchend', handleRelease);el.addEventListener('mouseleave', handleRelease);el.addEventListener('touchcancel', handleRelease);},unbind(el) {// 移除事件监听器  el.removeEventListener('mousedown', el._handlePress);el.removeEventListener('touchstart', el._handlePress);el.removeEventListener('mouseup', el._handleRelease);el.removeEventListener('touchend', el._handleRelease);el.removeEventListener('mouseleave', el._handleRelease);el.removeEventListener('touchcancel', el._handleRelease);// 清理自定义属性  el._handlePress = null;el._handleRelease = null;}}
},
data(){return {zheZhao:false,//录音时的遮罩层isMai:false,//初始化,是否支持录音luYinAttr: {isAn:false,s: 0,timer:null,audioArray:[],startTime: null,//录音开始时间endTime: null, //录音结束时间mediaRecorder: null,recording: false, //录音状态(用于录音记时)timeLength: 0,//录音时长recordedChunks: [],timer: null,longPressThreshold:800,},}
}
//初始化录音对象(记住,录音一定得在 https里面。当然,在本地开发 localhost 可以不需要,但上线一定得在https里面)
luYin() {//这儿先做判断,判断当前设备或当前网络是否支持录音,如果不支持,那下面的也就不用多说了。//console.log(navigator, 'navigator.mediaDevices')if (!('mediaDevices' in navigator)) {this.isMai = false;return false;}navigator.mediaDevices.getUserMedia({ audio: true }).then(this.luYinSuccess) //支持录音,继续执行下面的操作.catch(this.luYinErr) //不支持录音,没下文
},
luYinSuccess(stream) {const audioContext = new AudioContext();//const sourceNode = audioContext.createMediaStreamSource(stream); //没用上,先注释const mediaRecorder = new MediaRecorder(stream);const recordedChunks = [];this.luYinAttr.mediaRecorder = mediaRecorderthis.luYinAttr.recordedChunks = recordedChunksthis.isMai = true;
},
luYinErr(err) {this.isMai = false;//console.log('The following error occurred: ' + err);
},//startRecording ,  stopRecording是开始计时和结束计时(由于录音的时间不能太长,这儿我,限制为1分分钟的时长。所以,我得有一个录音计时,超过1分钟,录音取消)
//开始计时
startRecording() {console.log('开始计时')this.luYinAttr.isAn = true;this.zheZhao = true;this.luYinAttr.s = 0;this.luYinAttr.recording = true;this.luYinAttr.startTime = Date.now();this.luYinAttr.timer = setInterval(() => {this.luYinAttr.s = this.luYinAttr.s + 1;} , 500)
},
//结束录音计时
stopRecording() {this.luYinAttr.recording = false;const endTime = Date.now();const startTime = this.luYinAttr.startTimeconst recordDuration = (endTime - startTime) / 1000; // 计算录音时长(秒) if (recordDuration >= 60) {this.luYinAttr.timeLength = 60;//结束录音}this.luYinAttr.timeLength = recordDuration;/*const maxWidth = 300; // 设置图标的最大宽度  const indicatorWidth = Math.min(recordDuration * 20, maxWidth); // 根据录音时长计算图标宽度,假设每秒对应2个像素宽度  console.log(indicatorWidth, '时长')console.log('结束计时')*/
},startLongPress() {//console.log('长按开始');let that = this;clearTimeout(this.luYinAttr.timer);that.luYinAttr.timer = setTimeout(function () {// 执行长按操作  //console.log('长按操作开始');that.luYinAttr.mediaRecorder.start();//console.log(that.luYinAttr.mediaRecorder.state , 'qqggg');//startRecord.disabled = true;//stopRecord.disabled = false;that.startRecording();}, that.luYinAttr.longPressThreshold);// 在这里编写长按开始时的逻辑
},
endLongPress() {//长按结束事件let that = this;//console.log('取消')clearTimeout(that.luYinAttr.timer);that.luYinAttr.mediaRecorder.stop();that.stopRecording();that.luYinAttr.mediaRecorder.ondataavailable = async function (e) {console.log(e)if (e.data.size > 0) {const blobObj = e.data;let nowTime = new Date().getTime();let fileName = 'LY_' + nowTime + '.mp3';const file = new File([blobObj], fileName, { type: 'audio/mpeg' });//that.uplodAudio(file) //上传录音that.luYinAttr.isAn = false;that.zheZhao = false;clearInterval(that.luYinAttr.timer)} else {// no data to push  }};
},//试听录音(在苹果机上不支持)
listenAudio(obj, index) {let myTimer = null;this.play.listenStatus = this.play.listenStatus + 1;if (this.play.listenStatus > 1) {clearInterval(myTimer)return false;}if (!this.playActive.isLongPressing) {let that = this;let itemAudio = [(that.luYinAttr.recordedChunks)[index]]//console.log(itemAudio, 'itemAudio', obj)let len = JSON.parse(JSON.stringify(obj.timeLength));obj.timeLength = 0;myTimer = setInterval(() => {obj.timeLength = obj.timeLength + 1;if (obj.timeLength == len) {clearInterval(myTimer)this.play.listenStatus = 0;}} , 1000)const blob = new Blob(itemAudio, { 'type': 'audio/ogg; codecs=opus' });//const blob = new Blob(that.luYinAttr.recordedChunks, { 'type': 'audio/ogg; codecs=opus' });//console.log(blob, 'blob')const audioURL = window.URL.createObjectURL(blob);//console.log(audioURL, 'audioURL')const audio = new Audio(audioURL);//console.log(audio,'audio')audio.play().catch(err => {console.log('Failed to play sound:', err);});}
},
<template v-if="isMai == true"><div class="" style="background:#ffffff; padding:10px 16px;"><div class="list" style="text-align:center"><template v-for="(audioArrayItem , audioArrayIndex) in luYinAttr.audioArray"><el-tooltip placement="top" :manual="true" :value="audioArrayItem.tooltip"><div slot="content"><span @click="returnAudioArrayItem(audioArrayItem , audioArrayIndex)">移除</span></div><div style="margin-bottom:10px;"  @click.prevent="listenAudio(audioArrayItem , audioArrayIndex)"><div style="overflow:hidden"><div style="float:left"><p style="background: #3975C6; color: #ffffff; padding:0 8px; display:inline-block; border-radius:4px;"><span class="icon iconfont playIcon" style="display:inline-block; height:20px; font-size:14px; text-align:center;">&#xe618;</span><span style="position:relative; top:-5px; margin:0 5px;"><template v-for="(item , index) in audioArrayItem.timeLength"><span>,,</span></template></span><span>{{ audioArrayItem.timeLength }}'</span></p></div><div style="float:right"><van-button type="info" size="mini" @click.stop="returnAudioArrayItem(audioArrayItem , audioArrayIndex)">移除</van-button></div></div></div></el-tooltip></template></div><div class="byBtn" :class="luYinAttr.isAn == true ? 'myIsYesAn': 'myIsNoAn' " style="text-align: center; font-size:14px;" v-longpress="{ start: startLongPress, end: endLongPress }"><p class="icon iconfont" style="color: #3975C6; font-size: 24px;">&#xe7a6;</p><p>任务详情 - 按住说话</p></div></div>
</template>

相关文章:

前端h5录音

时隔差不多半个月&#xff0c; 现在才来写这编博客。由于某些原因&#xff0c;我一直没有写&#xff0c;请大家原谅。前段时间开发了一个小模块。模块的主要功能就是有一个录音的功能。也就是说&#xff0c;模仿微信发送语音的功能一样。不多说&#xff0c;直接来一段代码 //自…...

Android Studio 使用Flutter开发第一个Web页面(进行中)

附上Flutter官方文档 1、新建Flutter项目&#xff08;需要勾选web选项&#xff09; 新建项目构成为&#xff1a; 2、配置 Flutter 使用 path 策略 官方文档 在main.dart中&#xff0c;需要导入flutter_web_plugins/url_strategy.dart包&#xff0c;并在main(){}函数中usePath…...

Vue.js组件精讲 第2章 基础:Vue.js组件的三个API:prop、event、slot

如果您已经对 Vue.js 组件的基础用法了如指掌&#xff0c;可以跳过本小节&#xff0c;不过当做复习稍读一下也无妨。 组件的构成 一个再复杂的组件&#xff0c;都是由三部分组成的&#xff1a;prop、event、slot&#xff0c;它们构成了 Vue.js 组件的 API。如果你开发的是一个…...

npm install 报 ERESOLVE unable to resolve dependency tree 异常解决方法

问题 在安装项目依赖时&#xff0c;很大可能会遇到安装不成功的问题&#xff0c;其中有一个很大的原因&#xff0c;可能就是因为你的npm版本导致的。 1.npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree 2.ERESOLVE unable to resolve dependenc…...

RPC还是HTTP

RPC是一个远程调用的通讯协议 RPC要比HTTP快一些 1. HTTP体积大 原因是HTTP协议会带着一堆无用信息 HTTP由三部分组成 请求头 请求行 请求体 这三部分只有请求体是需要的 2. HTTP支持的序列化协议比较少 RPC支持更多轻量级的通讯协议 3. RPC协议支持定制...

Conda 常用命令总结

创建虚拟环境 conda create -n name python[your_version] 激活环境 conda activate name 退出环境 conda deactivate 查看虚拟环境 conda info --envs 删除虚拟环境 conda remove -n name --all 删除所有的安装包及cache(索引缓存、锁定文件、未使用过的包和tar包) …...

Spring MVC 文件上传和下载

文章目录 Spring MVC 中文件上传利用 commons-fileupload 文件上传使用 Servlet 3.1 内置的文件上传功能 Spring MVC 中文件下载 Spring MVC 中文件上传 为了能上传文件&#xff0c;必须将 from 表单的 method 设置为 POST&#xff0c;并将 enctype 设置为 multipart/form-data…...

WSL访问adb usb device

1.Windows上用PowerShell运行&#xff1a; winget install --interactive --exact dorssel.usbipd-win 2.在WSLUbuntu上终端运行&#xff1a; sudo apt install linux-tools-generic hwdata sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-too…...

CDF与PDF(描述随机变量的分布情况)

一、概念解释 CDF(Cumulative Distribution Function)和PDF(Probability Density Function)是概率论和统计学中常用的两个评价指标,用于描述随机变量的分布情况。 1. CDF(累积分布函数): - CDF是描述随机变量在某个取值及其之前所有可能取值的概率的函数。它表示了累…...

react项目中需要条形码功能,安装react-barcode使用时报错

react项目中需要条形码功能&#xff0c;用yarn add安装react-barcode后&#xff0c;在项目中使用import Barcode from ‘react-barcode’&#xff0c;页面中一直白屏&#xff0c;加载中 查看控制台报以下错误 load component failed Error: Module "./react-barcode"…...

ES6基础(JavaScript基础)

本文用于检验学习效果&#xff0c;忘记知识就去文末的链接复习 1. ECMAScript介绍 ECMAScript是一种由Ecma国际&#xff08;前身为欧洲计算机制造商协会&#xff0c;英文名称是European Computer Manufacturers Association&#xff09;通过ECMA-262标准化的脚本程序设计语言…...

[蓝桥杯] 纸张尺寸(C语言)

题目链接 蓝桥杯2022年第十三届省赛真题-纸张尺寸 - C语言网 题目理解 输入一行包含一个字符串表示纸张的名称&#xff0c;该名称一定是 A0、A1、A2、A3、A4、A5、A6、A7、A8、A9 之一&#xff0c;输出两行&#xff0c;每行包含一个整数&#xff0c;依次表示长边和短边的长度…...

AI推介-多模态视觉语言模型VLMs论文速览(arXiv方向):2024.04.05-2024.04.10

文章目录~ 1.BRAVE: Broadening the visual encoding of vision-language models2.ORacle: Large Vision-Language Models for Knowledge-Guided Holistic OR Domain Modeling3.MedRG: Medical Report Grounding with Multi-modal Large Language Model4.InternLM-XComposer2-4…...

【golang】动态生成微信小程序二维码实战下:golang 生成 小程序二维码图片 并通过s3协议上传到对象存储桶 | 腾讯云 cos

项目背景 在自研的系统&#xff0c;需要实现类似草料二维码的功能 将我们自己的小程序&#xff0c;通过代码生成相想要的小程序二维码 代码已经上传到 Github 需要的朋友可以自取 https://github.com/ctra-wang/wechat-mini-qrcode 一、生成Qrcode并提交到对象存储 通过源生A…...

kubeadm k8s 1.24之后版本安装,带cri-dockerd

最后编辑时间&#xff1a;2024/3/26 适用于1.24之后的版本 单节点配置 检查是否已经安装kubectl, kubelet, kubeadm直接输入命令确定&#xff0c;如果提示没有该指令则正确 kubectl kubelet kubeadm如果之前安装&#xff0c;首先reset&#xff0c;然后使用apt remove和snap r…...

13-pyspark的共享变量用法总结

目录 前言广播变量广播变量的作用 广播变量的使用方式 累加器累加器的作用累加器的优缺点累加器的使用方式 PySpark实战笔记系列第四篇 10-用PySpark建立第一个Spark RDD(PySpark实战笔记系列第一篇)11-pyspark的RDD的变换与动作算子总结(PySpark实战笔记系列第二篇))12-pysp…...

BI数据分析软件:行业趋势与功能特点剖析

随着数据量的爆炸性增长&#xff0c;企业对于数据的需求也日益迫切。BI数据分析软件作为帮助企业实现数据驱动决策的关键工具&#xff0c;在当前的商业环境中扮演着不可或缺的角色。本文将从行业趋势、功能特点以及适用场景等方面&#xff0c;深入剖析BI数据分析软件&#xff0…...

centos7上docker搭建vulhub靶场

1 vulhub靶场概述 VulHub是一个在线靶场平台&#xff0c;提供了丰富的漏洞环境供安全爱好者学习和实践。 该平台主要面向网络安全初学者和进阶者&#xff0c;通过模拟真实的漏洞环境&#xff0c;帮助用户深入了解漏洞的成因、利用方式以及防范措施。 此外&#xff0c;VulHub还…...

Flutter入门指南

文章目录 一、环境搭建二、基本概念三、创建一个简单的Flutter应用四、常用组件及代码示例五、总结推荐阅读 笔者项目中使用Flutter的模块并不多。虽然笔者还没有机会在项目中正式使用Flutter&#xff0c;但是也在学习Flutter的一些基本用法。本文就是一篇Flutter的入门介绍&am…...

keepalived脑裂问题

脑裂问题产生的原因 就是vip同时存在 master和backup 就叫做脑裂 比如说 backup 机器的防火墙没关&#xff0c;并且没有允许vrrp通过&#xff0c;backup 没有收到master的心跳数据&#xff0c;就会抢夺资源&#xff0c;发生脑裂问题测试 我们打开test3的防火墙&#xff0c;此…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...