安装依赖
npm install benz-amr-recorder
html
<template>
<div class="voice_view">
<p class="voice_view_star_tip" v-show="voice.type === 0">点击录音</p>
<van-divider class="voice_view_ing_tip" dashed :hairline="false" :style="{padding: '0',margin: '0' }" v-show="voice.type >= 1">
<span v-if="voice.type === 3">{{voice.playLength | secondFormat}}/</span>
<span>{{voice.length | secondFormat}}</span>
</van-divider>
<div class="voice_star">
<!--off on stop play-->
<div class="off" @click="offVoiceChange" v-if="voice.type === 0"></div>
<div class="on" @click="onVoiceChange" v-else-if="voice.type === 1"></div>
<div class="stop" @click="stopVoiceChange" v-else-if="voice.type === 2"></div>
<div class="play" @click="playVoiceChange" v-else-if="voice.type === 3"></div>
</div>
<div class="voice_send van-slide-up" v-if="voice.type >= 2">
<div class="voice_send_cancel" @click="onCancelVoice">取消</div>
<div class="voice_send_ok" @click="onSendVoice">发送</div>
</div>
</div>
</template>
js
import BenzAMRRecorder from 'benz-amr-recorder'
export default {
name: 'chatroom',
data () {
return {
voice: {
interval: null, // 录音定时器
playInterval: null, // 播放录音定时器
type: 0, // 0未录音 1录音中 2录音完毕 3回放录音
length: 0, // 录音长度
playLength: 0,// 当前播放长度
src: null // 录音资源
},
amrRec: null, // 录音对象
playRec: null // 播放对象
}
},
filters: {
secondFormat(val){
let minute = Math.floor(val / 60),
second = val % 60;
return minute + ':'+ (second < 10 ? '0' + second : second)
}
},
methods: {
// 录音面板操作-开始录音
offVoiceChange(){
this.amrRec = new BenzAMRRecorder();
this.amrRec.initWithRecord().then(() => {
this.amrRec.startRecord();
this.voice.interval = setInterval(() => {
this.voice.length++
}, 1000)
this.voice.type = 1
}).catch((e) => {
alert(e)
this.$notify('录音失败,请检查相关权限和设备')
})
},
// 录音面板操作-结束录音
onVoiceChange(){
clearInterval(this.voice.interval)
// 当前不是在录音,可能快速点击开始并且同时快速点击了结束
if (!this.amrRec.isRecording()) {
return this.$notify('操作频繁')
}
this.amrRec.finishRecord().then(() => {
if (this.voice.length === 0) {
this.voice.type = 0
this.voice.length = 0
// 放弃录音
this.amrRec.cancelRecord()
this.$notify({
type: 'warning',
message: '录音时间较短'
})
} else {
// 获取音频时长
this.voice.length = Math.ceil(this.amrRec.getDuration())
// 获取音频文件
this.voice.src = this.amrRec.getBlob()
this.voice.type = 2
}
}).catch(() => {
this.$notify('录音失败,请检查相关权限')
})
},
// 录音面板操作-播放录音
stopVoiceChange() {
// 先停止正在播放的音频
if (this.playRec !== null) {
this.stopPlayVoice()
}
this.voice.playInterval = setInterval(() => {
if (this.voice.playLength === this.voice.length) {
this.playVoiceChange()
} else {
this.voice.playLength++
}
}, 1000)
this.playRec = new BenzAMRRecorder();
this.playRec.initWithBlob(this.voice.src).then(()=> {
this.playRec.play();
}).catch((e) => {
alert(e)
this.$notify('播放录音失败')
});
this.voice.type = 3
},
// 录音面板操作-停止播放
playVoiceChange() {
clearInterval(this.voice.playInterval);
this.voice.playLength = 0;
this.voice.type = 2;
this.stopPlayVoice();
},
// 发送语音
onSendVoice(){
},
// 取消语音
onCancelVoice(){
clearInterval(this.voice.playInterval)
this.voice.playLength = 0
this.voice.type = 0
this.voice.length = 0
this.voice.src = null
this.stopPlayVoice()
},
// 停止播放
stopPlayVoice(){
if (this.playRec.isPlaying()){
this.playRec.stop()
}
}
}
}
less
/*语音*/
&>.voice_view{
height: 220px;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&>p{
color: #bababa;
line-height: 10px;
}
.voice_view_ing_tip{
width: 120px;
/*border-width: 2px;*/
}
&>.voice_star{
width: 90px;
height: 90px;
border-radius: 100%;
padding: 10px;
box-shadow: rgba(0, 0, 0, 0.1) 0 3px 3px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
&>div{
transition: all 400ms;
}
&>.off{
width: 100%;
height: 100%;
background: linear-gradient(right, #ff1315, #ff5356);
border-radius: 100%;
}
&>.on{
width: 50%;
height: 50%;
background: linear-gradient(right,#ff1315, #ff5356);
border-radius: 10%;
}
&>.stop{
display: inline-block;
font-size: 0;
overflow: hidden;
transform: translateX(5px);
&:before{
content: "";
position: relative;
display: inline-block;
border: 20px solid transparent;
}
position: relative;
right: 2px;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
&:before{
left: 2px;
border-right-width: 0;
border-left-width: 40px;
border-left-color: #5c5f5e;
}
}
.play{
width: 50%;
height: 50%;
background: linear-gradient(right, #4a4b4b, #5f5f61);
border-radius: 10%;
}
&:active{
opacity: 0.8;
}
}
/*发送*/
&>.voice_send{
width: 100%;
height: 35px;
margin-top: 10px;
display: flex;
justify-content: center;
&>div{
width: 40%;
height: 100%;
border-radius: 5px;
text-align: center;
line-height: 35px;
&:active{
opacity: 0.8;
}
}
&>.voice_send_cancel{
background: #d1d1d1;
margin-right: 2%;
}
&>.voice_send_ok{
color: #ffffff;
background: #0CAAED;
margin-right: 2%;
}
}
}
注意点
1.van-divider是vant的组件,改为div即可,这个不多说
2.this.$notify(’’)这是vant的提示组件,改为alert即可,这个不多说
3.benz-amr-recorder中的api,不能通过if,switch去判断再执行,必须每个事件写一个方法,如有if一定要用‘卫语句‘,否则报错 语法不执行等一系列问题
4.描述第三点的坑:前后对比
5.benz-amr-recorder官方文档
https://www.npmjs.com/package/benz-amr-recorder