vue实现录音功能js-audio-recorder带波浪图
前言:
因为业务需要,现在将整理的录音功能资料记录下,使用插件js-audio-recorder
目录:
实现效果:可得到三种录音数据,pcm,wav,mp3 等
官方api入口:点我(网不好的童鞋可以看最下面的api截图)
官方案例入口:点我
官方源码git入口:点我
实现步骤:
一:安装插件 js-audio-recorder
二:安装将格式转换为mp3的插件 lamejs
三:附上实现源码:
到这里,代码就结束了,上面每个方法都有很详细的注释,就不累赘了
整理api:(有代理的可以看官网,这里是摘取官网的api)
1,使用
安装
npm 方式
script 标签方式
2,属性
实例初始化
sampleBits
sampleRate
numChannels
compiling
实例属性
duration
fileSize
3,操作
start()
pause()
resume()
stop()
play()
getPlayTime()
pausePlay()
resumePlay()
stopPlay()
destroy()
音频数据
录音结束,获取取录音数据
录音结束,下载录音文件
录音中,获取录音数据
录音波形显示
播放外部
Player.play(blob)
其他
录音权限
getPermission()
4,Event
onprocess(duration)
onprogress(duration)
onplay
onpauseplay
onresumeplay
onstopplay
onplayend
5,应用
语音识别
6,Player
Player 播放类
Player.play([arraybuffer])
Player.pausePlay()
Player.resumePlay()
Player.stopPlay()
Player.addPlayEnd(fn)
Player.getPlayTime()
Player.getAnalyseData()
7,其他音频格式
MP3
安装lamejs
实现效果:可得到三种录音数据,pcm,wav,mp3 等
官方api入口:点我(网不好的童鞋可以看最下面的api截图)
官方案例入口:点我
官方源码git入口:点我
实现步骤:
一:安装插件 js-audio-recorder
cnpm i js-audio-recorder --s
二:安装将格式转换为mp3的插件 lamejs
cnpm install lamejs --s
三:附上实现源码:
提示:慎用自身的这个监听事件,可以拿到数据,但是每秒拿到的数据非常多
<template><div class="home" style="margin:1vw;"><Button type="success" @click="getPermission()" style="margin:1vw;">获取麦克风权限</Button><br/><Button type="info" @click="startRecorder()" style="margin:1vw;">开始录音</Button><Button type="info" @click="resumeRecorder()" style="margin:1vw;">继续录音</Button><Button type="info" @click="pauseRecorder()" style="margin:1vw;">暂停录音</Button><Button type="info" @click="stopRecorder()" style="margin:1vw;">结束录音</Button><br/><Button type="success" @click="playRecorder()" style="margin:1vw;">录音播放</Button><Button type="success" @click="pausePlayRecorder()" style="margin:1vw;">暂停录音播放</Button><Button type="success" @click="resumePlayRecorder()" style="margin:1vw;">恢复录音播放</Button><Button type="success" @click="stopPlayRecorder()" style="margin:1vw;">停止录音播放</Button><br/><Button type="info" @click="getRecorder()" style="margin:1vw;">获取录音信息</Button><Button type="info" @click="downPCM()" style="margin:1vw;">下载PCM</Button><Button type="info" @click="downWAV()" style="margin:1vw;">下载WAV</Button><Button type="info" @click="getMp3Data()" style="margin:1vw;">下载MP3</Button><br/><Button type="error" @click="destroyRecorder()" style="margin:1vw;">销毁录音</Button><br/><div style="width:100%;height:200px;border:1px solid red;"><canvas id="canvas"></canvas><span style="padding: 0 10%;"></span><canvas id="playChart"></canvas></div></div>
</template><script>import Recorder from 'js-audio-recorder'const lamejs = require('lamejs')const recorder = new Recorder({sampleBits: 16, // 采样位数,支持 8 或 16,默认是16sampleRate: 48000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000numChannels: 1, // 声道,支持 1 或 2, 默认是1// compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false})// 绑定事件-打印的是当前录音数据recorder.onprogress = function(params) {// console.log('--------------START---------------')// console.log('录音时长(秒)', params.duration);// console.log('录音大小(字节)', params.fileSize);// console.log('录音音量百分比(%)', params.vol);// console.log('当前录音的总数据([DataView, DataView...])', params.data);// console.log('--------------END---------------')}export default {name: 'home',data () {return {//波浪图-录音drawRecordId:null,oCanvas : null,ctx : null,//波浪图-播放drawPlayId:null,pCanvas : null,pCtx : null,}},mounted(){this.startCanvas();},methods: {/*** 波浪图配置* */startCanvas(){//录音波浪this.oCanvas = document.getElementById('canvas');this.ctx = this.oCanvas.getContext("2d");//播放波浪this.pCanvas = document.getElementById('playChart');this.pCtx = this.pCanvas.getContext("2d");},/*** 录音的具体操作功能* */// 开始录音startRecorder () {recorder.start().then(() => {this.drawRecord();//开始绘制图片}, (error) => {// 出错了console.log(`${error.name} : ${error.message}`);});},// 继续录音resumeRecorder () {recorder.resume()},// 暂停录音pauseRecorder () {recorder.pause();this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;},// 结束录音stopRecorder () {recorder.stop()this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;},// 录音播放playRecorder () {recorder.play();this.drawPlay();//绘制波浪图},// 暂停录音播放pausePlayRecorder () {recorder.pausePlay()},// 恢复录音播放resumePlayRecorder () {recorder.resumePlay();this.drawPlay();//绘制波浪图},// 停止录音播放stopPlayRecorder () {recorder.stopPlay();},// 销毁录音destroyRecorder () {recorder.destroy().then(function() {recorder = null;this.drawRecordId && cancelAnimationFrame(this.drawRecordId);this.drawRecordId = null;});},/*** 获取录音文件* */getRecorder(){let toltime = recorder.duration;//录音总时长let fileSize = recorder.fileSize;//录音总大小//录音结束,获取取录音数据let PCMBlob = recorder.getPCMBlob();//获取 PCM 数据let wav = recorder.getWAVBlob();//获取 WAV 数据let channel = recorder.getChannelData();//获取左声道和右声道音频数据},/*** 下载录音文件* *///下载pcmdownPCM(){//这里传参进去的时文件名recorder.downloadPCM('新文件');},//下载wavdownWAV(){//这里传参进去的时文件名recorder.downloadWAV('新文件');},/*** 获取麦克风权限* */getPermission(){Recorder.getPermission().then(() => {this.$Message.success('获取权限成功')}, (error) => {console.log(`${error.name} : ${error.message}`);});},/*** 文件格式转换 wav-map3* */getMp3Data(){const mp3Blob = this.convertToMp3(recorder.getWAV());recorder.download(mp3Blob, 'recorder', 'mp3');},convertToMp3(wavDataView) {// 获取wav头信息const wav = lamejs.WavHeader.readHeader(wavDataView); // 此处其实可以不用去读wav头信息,毕竟有对应的config配置const { channels, sampleRate } = wav;const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);// 获取左右通道数据const result = recorder.getChannelData()const buffer = [];const leftData = result.left && new Int16Array(result.left.buffer, 0, result.left.byteLength / 2);const rightData = result.right && new Int16Array(result.right.buffer, 0, result.right.byteLength / 2);const remaining = leftData.length + (rightData ? rightData.length : 0);const maxSamples = 1152;for (let i = 0; i < remaining; i += maxSamples) {const left = leftData.subarray(i, i + maxSamples);let right = null;let mp3buf = null;if (channels === 2) {right = rightData.subarray(i, i + maxSamples);mp3buf = mp3enc.encodeBuffer(left, right);} else {mp3buf = mp3enc.encodeBuffer(left);}if (mp3buf.length > 0) {buffer.push(mp3buf);}}const enc = mp3enc.flush();if (enc.length > 0) {buffer.push(enc);}return new Blob(buffer, { type: 'audio/mp3' });},/*** 绘制波浪图-录音* */drawRecord () {// 用requestAnimationFrame稳定60fps绘制this.drawRecordId = requestAnimationFrame(this.drawRecord);// 实时获取音频大小数据let dataArray = recorder.getRecordAnalyseData(),bufferLength = dataArray.length;// 填充背景色this.ctx.fillStyle = 'rgb(200, 200, 200)';this.ctx.fillRect(0, 0, this.oCanvas.width, this.oCanvas.height);// 设定波形绘制颜色this.ctx.lineWidth = 2;this.ctx.strokeStyle = 'rgb(0, 0, 0)';this.ctx.beginPath();var sliceWidth = this.oCanvas.width * 1.0 / bufferLength, // 一个点占多少位置,共有bufferLength个点要绘制x = 0; // 绘制点的x轴位置for (var i = 0; i < bufferLength; i++) {var v = dataArray[i] / 128.0;var y = v * this.oCanvas.height / 2;if (i === 0) {// 第一个点this.ctx.moveTo(x, y);} else {// 剩余的点this.ctx.lineTo(x, y);}// 依次平移,绘制所有点x += sliceWidth;}this.ctx.lineTo(this.oCanvas.width, this.oCanvas.height / 2);this.ctx.stroke();},/*** 绘制波浪图-播放* */drawPlay () {// 用requestAnimationFrame稳定60fps绘制this.drawPlayId = requestAnimationFrame(this.drawPlay);// 实时获取音频大小数据let dataArray = recorder.getPlayAnalyseData(),bufferLength = dataArray.length;// 填充背景色this.pCtx.fillStyle = 'rgb(200, 200, 200)';this.pCtx.fillRect(0, 0, this.pCanvas.width, this.pCanvas.height);// 设定波形绘制颜色this.pCtx.lineWidth = 2;this.pCtx.strokeStyle = 'rgb(0, 0, 0)';this.pCtx.beginPath();var sliceWidth = this.pCanvas.width * 1.0 / bufferLength, // 一个点占多少位置,共有bufferLength个点要绘制x = 0; // 绘制点的x轴位置for (var i = 0; i < bufferLength; i++) {var v = dataArray[i] / 128.0;var y = v * this.pCanvas.height / 2;if (i === 0) {// 第一个点this.pCtx.moveTo(x, y);} else {// 剩余的点this.pCtx.lineTo(x, y);}// 依次平移,绘制所有点x += sliceWidth;}this.pCtx.lineTo(this.pCanvas.width, this.pCanvas.height / 2);this.pCtx.stroke();}},}
</script><style lang='less' scoped></style>
到这里,代码就结束了,上面每个方法都有很详细的注释,就不累赘了
整理api:(有代理的可以看官网,这里是摘取官网的api)
1,使用
安装
npm 方式
推荐使用npm
安装的方式:
安装:
npm i js-audio-recorder
Copy
调用:
import Recorder from 'js-audio-recorder';let recorder = new Recorder();
Copy
script 标签方式
<script type="text/javascript" src="./dist/recorder.js"></script>let recorder = new Recorder();
2,属性
实例初始化
可以配置输出数据参数,
let recorder = new Recorder({sampleBits: 16, // 采样位数,支持 8 或 16,默认是16sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000numChannels: 1, // 声道,支持 1 或 2, 默认是1// compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
});
Copy
- 返回: recorder实例。
sampleBits
采样位数。
sampleRate
采样率。
numChannels
声道数。
compiling
(0.x版本中生效,最新目前不支持)
是否边录音边转换。
获取数据方法:
- 回调方式
recorder.onprogress = function(params) {console.log(params.data); // 当前获取到到音频数据
}
Copy
data,DataView型数组,格式如 [DataView, DataView, DataView ...] 。
- 主动获取
getWholeData(); // [DataView, DataView, DataView ...]getNextData(); // [DataView, DataView, DataView ...]
Copy
getWholeData() 的值和onprogress
回调中的data数据一致。
getNextData() 获取的是前一次 getNextData() 之后的值,他只是data数据的一小部分。
实例属性
duration
获取录音的总时长。
console.log(recorder.duration);
Copy
fileSize
录音文件大小(单位:字节)。
console.log(recorder.fileSize);
3,操作
start()
开始录音。
- 返回: Promise。
recorder.start().then(() => {// 开始录音
}, (error) => {// 出错了console.log(`${error.name} : ${error.message}`);
});
Copy
pause()
录音暂停。
- 返回: void
recorder.pause();
Copy
resume()
继续录音。
- 返回: void。
recorder.resume()
Copy
stop()
结束录音。
- 返回: void。
recorder.stop();
Copy
play()
录音播放。
- 返回: void。
recorder.play();
Copy
getPlayTime()
获取音频已经播的时长。
- 返回: number。
recorder.getPlayTime();
Copy
pausePlay()
暂停录音播放。
- 返回: void。
recorder.pausePlay();
Copy
resumePlay()
恢复录音播发。
- 返回: void。
recorder.resumePlay();
Copy
stopPlay()
停止播放。
- 返回: void。
recorder.stopPlay();
Copy
destroy()
销毁实例。
- 返回: Promise。
// 销毁录音实例,置为null释放资源,fn为回调函数,
recorder.destroy().then(function() {recorder = null;
});
Copy
音频数据
录音结束,获取取录音数据
getPCMBlob()
获取 PCM 数据,在录音结束后使用。
- 返回: Blob
注:使用该方法会默认调用 stop() 方法。
recorder.getPCMBlob();
Copy
getWAVBlob()
获取 WAV 数据,在录音结束后使用
- 返回: Blob
注:使用该方法会默认调用 stop() 方法。
recorder.getWAVBlob();
Copy
getChannelData()
获取左声道和右声道音频数据。
recorder.getChannelData();
Copy
录音结束,下载录音文件
downloadPCM([ filename ])
下载 PCM 格式
- fileName String 重命名文件
- 返回: Blob
注:使用该方法会默认调用 stop() 方法。
recorder.downloadPCM(fileName ?);
Copy
downloadWAV([ filename ])
下载 WAV 格式
- fileName String 重命名文件
- 返回: Blob
注:使用该方法会默认调用 stop() 方法。
录音中,获取录音数据
(0.x版本中生效,最新目前不支持)
该方式为边录边转换,建议在 compiling 为 true 时使用。
getWholeData()
获取已经录音的所有数据。若没有开启边录边转(compiling为false),则返回是空数组。
- 返回: Array, 数组中是DataView数据
定时获取所有数据:
setInterval(() => {recorder.getWholeData();
}, 1000)
Copy
getNextData()
获取前一次 getNextData() 之后的数据。若没有开启边录边转(compiling为false),则返回是空数组。
- 返回: Array, 数组中是DataView数据
定时获取新增数据:
setInterval(() => {recorder.getNextData();
}, 1000)
// 实时录音,则可将该数据返回给服务端。
Copy
录音波形显示
getRecordAnalyseData()
返回的是一个1024长的,0-255大小的Uint8Array类型。用户可以根据这些数据自定义录音波形。此接口获取的是录音时的。
let dataArray = recorder.getRecordAnalyseData();
Copy
getPlayAnalyseData()
返回数据同 getRecordAnalyseData(),该方法获取的是播放时的。
let dataArray = recorder.getPlayAnalyseData();
Copy
播放外部
Player.play(blob)
播放外部音频,格式由浏览器的audio支持的类型决定。
Player.play(/* 放入arraybuffer数据 */);
Copy
其他
录音权限
未给予录音权限的页面在开始录音时需要再次点击允许录音,才能真正地录音,存在丢失开始这一段录音的情况,增加方法以便用户提前获取麦克风权限。
getPermission()
获取麦克风权限。
- 返回:promise。
Recorder.getPermission().then(() => {console.log('给权限了');
}, (error) => {console.log(`${error.name} : ${error.message}`);
});
Copy
此处then
回调与start
的一致。
4,Event
js-audio-recorder 支持的事件回调。
onprocess(duration)
用于获取录音时长。
不推荐使用,用onprogress代替。
recorder.onprocess = function(duration) {console.log(duration);
}
Copy
onprogress(duration)
目前支持获取以下数据:
- 录音时长(duration)。
- 录音大小(fileSize)。
- 录音音量百分比(vol)。
- 所有的录音数据(data)。
recorder.onprogress = function(params) {console.log('录音时长(秒)', params.duration);console.log('录音大小(字节)', params.fileSize);console.log('录音音量百分比(%)', params.vol);// console.log('当前录音的总数据([DataView, DataView...])', params.data);
}
Copy
onplay
录音播放开始回调。
recorder.onplay = () => {console.log('onplay')
}
Copy
onpauseplay
录音播放暂停回调。
recorder.onpauseplay = () => {console.log('onpauseplay')
}
Copy
onresumeplay
录音播放恢复回调。
recorder.onresumeplay = () => {console.log('onresumeplay')
}
Copy
onstopplay
录音播放停止回调。
recorder.onstopplay = () => {console.log('onstopplay')
}
Copy
onplayend
录音播放完成回调。
recorder.onplayend = () => {console.log('onplayend')
}
5,应用
语音识别
recorder上可以测试,注意选择16000采样率,16采样位数,单声道录音。
6,Player
Player 播放类
import Player from './player/player';
Copy
用于协助播放录音文件,包括,开始、暂停、恢复、停止等功能。所支持的格式由浏览器的audio支持的类型决定。可单独使用。
Player.play([arraybuffer])
播放外部的音频。所支持的格式由浏览器的audio支持的类型决定。
实际是调用了decodeAudioData
实现音频播放。
Recorder.play(/* 放入arraybuffer数据 */);
Copy
Player.pausePlay()
暂停播放。
Player.resumePlay()
恢复播放。
Player.stopPlay()
停止播放。
Player.addPlayEnd(fn)
增加播放完成回调函数。
Player.getPlayTime()
获取播放时间。
Player.getAnalyseData()
获取回放录音的波形数据。
7,其他音频格式
MP3
将pcm(wav)音频文件转化为mp3格式。
注:使用16采样位数。
利用lamejs进行转换,使用情况见demo,例子:
function convertToMp3(wavDataView) {// 获取wav头信息const wav = lamejs.WavHeader.readHeader(wavDataView); // 此处其实可以不用去读wav头信息,毕竟有对应的config配置const { channels, sampleRate } = wav;const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);// 获取左右通道数据const result = recorder.getChannelData()const buffer = [];const leftData = result.left && new Int16Array(result.left.buffer, 0, result.left.byteLength / 2);const rightData = result.right && new Int16Array(result.right.buffer, 0, result.right.byteLength / 2);const remaining = leftData.length + (rightData ? rightData.length : 0);const maxSamples = 1152;for (let i = 0; i < remaining; i += maxSamples) {const left = leftData.subarray(i, i + maxSamples);let right = null;let mp3buf = null;if (channels === 2) {right = rightData.subarray(i, i + maxSamples);mp3buf = mp3enc.encodeBuffer(left, right);} else {mp3buf = mp3enc.encodeBuffer(left);}if (mp3buf.length > 0) {buffer.push(mp3buf);}}const enc = mp3enc.flush();if (enc.length > 0) {buffer.push(enc);}return new Blob(buffer, { type: 'audio/mp3' });
}
Copy
安装lamejs
npm install lamejs
vue实现录音功能js-audio-recorder带波浪图相关推荐
- vue.runtime.esm.js:4560 [Vue warn]: Property or method “item“ is not defined on the instance but
报错异常 vue.runtime.esm.js:4560 [Vue warn]: Property or method "item" is not defined on the i ...
- dropzonejs vue 使用_dropzone.js使用实践
官网地址:http://www.dropzonejs.com/ 一,它是什么: DropzoneJS is an open source library that provides drag'n'dr ...
- 【项目技术点总结之一】vue集成d3.js利用svg加载图片实现缩放拖拽功能
[项目技术点总结之一]vue集成d3.js利用svg加载图片实现缩放拖拽功能 前言 概述 技术介绍 实现过程 插件安装 引用组件 初始化组件 实现效果 简单理解 使用d3创建一个svg 在svg中提添 ...
- js循环动态绑定带参数函数遇到的问题及解决方案[转]
今天写原生javascript时,想利用绑定事件实现类似jquery中on方法的功能:于是有了for循环里绑定事件,无意中发现定义类能解决好多问题! 例如:一个不确定长度的列表,在鼠标经过某一条的时候 ...
- JS调用后台带参数的方法
JS调用后台带参数的方法 对于前台调用后台的方法,我们想到最多的就是用AJAX,这个是毋庸置疑的, 我就不再这里多说了.我今天主要想说的是用JS调用后台的方法. 对于后台往前台传值,用这种<%= ...
- js setTimeout 传递带参数的函数的2种方式
js setTimeout 传递带参数的函数的2种方式 Created by Marydon on 2018年9月14日 1.准备工作 function sayYourName(param) {ale ...
- SQLAlchemy中模糊查询;JS中POST带参数跳转;JS获取url参数
SQLAlchemy中模糊查询,如何like多个关键字 JS中POST带参数跳转 一个项目中要跳转到另外一个项目,还需要带参数 考虑到安全性的问题,最好是用POST跳转,不能再URL中拼参 所以找到了 ...
- vue项目中主要文件的加载顺序(index.html、App.vue、main.js)
先后顺序: index.html > App.vue的export外的js代码 > main.js > App.vue的export里面的js代码 > Index.vue的ex ...
- Vue中的Js动画与Velocity.js 的结合
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...
最新文章
- 计算机vb2级知识点,二级考试(VB)知识点细化(针对浙江省计算机等级考试)
- 工业电脑中PCI、CPCI、PXI插槽的区别
- mysql触发器和存储过程_MySql的存储过程和触发器
- 深度学习模型之各种caffe版本(Linux和windows)的网址和配置
- 6.Maven聚合和继承,相关案例配置
- html flash 动画效果代码大全,flash动作代码大全
- zoj 3640 概率dp
- css 浮动和清除浮动
- 关于Windowsn 7因验证未通过被视为“非正版”出现“黑屏”的应急处理预案
- SQL允许你用EXECUTE执行一个变量中定义的SQL语句,并且允许你在被执行的SQL语句中,再次嵌套入一个变量定义的语句,并且再次在其中用EXECUTE执行它...
- Android 网络HTML查看器
- 关于idea中运行maven项目报错显示找不到包或符号的问题——终极方案
- 将两个PCB文件合并成一个文件
- 20道你必须要背会的微服务面试题,面试一定会被问到
- uniapp 使用本地数据库
- svn图标不显示的问题
- 高尔顿钉板仿真模拟 MATLAB
- Cocos技术派 | TS版属性面板定义高级篇
- 抽奖活动的奖品怎么设置?
- 搞死SAP系统系列 让系统无法连接数据库