直接上源码,注意由于浏览器权限问题,只可在HTTPS下录音
一、封装录音插件
<template>
<div class="recorder">
</div>
</template>
<script>
export default {
data() {
return {
isUserMedia: false,
stream: null,
audio: null,
recorder: null,
chunks: [],
startTime: 0,
isRecord: false, //是否在录音
volume: 0, //当前音量
}
},
mounted() {
/**
* error 事件的返回状态
* 100: 请在HTTPS环境中使用
* 101: 浏览器不支持
* 201: 用户拒绝授权
* 500: 未知错误
* */
if (origin.indexOf('https') === -1) {
this.$emit('error', '100')
throw '请在 https 环境中使用本插件。'
}
if (!navigator.mediaDevices || !window.MediaRecorder) {
this.$emit('error', '101')
throw '当前浏览器不支持'
}
this.getRecorderManager()
},
methods: {
getRecorderManager() {
this.audio = document.createElement('audio')
navigator.mediaDevices.getUserMedia({
audio: true
}).then(stream => {
this.isUserMedia = true
stream.getTracks().forEach((track) => {
track.stop()
})
}).catch(err => {
this.onErrorHandler(err)
})
},
start() {
if (!this.isUserMedia) return console.log('设备不支持')
navigator.mediaDevices.getUserMedia({
audio: true
}).then(stream => {
this.isRecord = true
this.beginDetect(stream)
console.log(stream, '52');
this.startTime = new Date().getTime()
this.stream = stream
this.recorder = new MediaRecorder(stream)
this.recorder.ondataavailable = this.getRecordingData
this.recorder.onstop = this.saveRecordingData
this.recorder.start()
}).catch(err => {
this.onErrorHandler(err)
})
},
// 麦克风音量检测
beginDetect(stream) {
let audioContext = new(window.AudioContext || window.webkitAudioContext)()
let mediaStreamSource = null
let scriptProcessor = null
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
// 将麦克风的声音输入这个对象
mediaStreamSource = audioContext.createMediaStreamSource(stream)
// 创建一个音频分析对象,采样的缓冲区大小为4096,输入和输出都是单声道
scriptProcessor = audioContext.createScriptProcessor(4096, 1, 1)
// 将该分析对象与麦克风音频进行连接
mediaStreamSource.connect(scriptProcessor)
// 此举无甚效果,仅仅是因为解决 Chrome 自身的 bug
scriptProcessor.connect(audioContext.destination)
// 开始处理音频
scriptProcessor.onaudioprocess = (e) => {
// 获得缓冲区的输入音频,转换为包含了PCM通道数据的32位浮点数组
let buffer = e.inputBuffer.getChannelData(0)
// 获取缓冲区中最大的音量值
let maxVal = Math.max.apply(Math, buffer)
// 显示音量值
if (this.isRecord) {
this.$emit('getVolume', Math.round(maxVal * 10))
};
}
} else {
console.log('不支持获取媒体接口');
}
},
stop() {
this.recorder.stop()
this.stream.getTracks().forEach((track) => {
console.log(track, '66');
track.stop()
})
},
getRecordingData(e) {
console.log(e, '71');
this.chunks.push(e.data)
},
saveRecordingData() {
const blob = new Blob(this.chunks, {
'type': 'audio/mpeg'
}),
localUrl = URL.createObjectURL(blob)
const endTime = new Date().getTime()
let duration = (endTime - this.startTime).toString().split('')
duration.splice(duration.length - 2)
duration.splice(duration.length - 1, 0, '.')
duration = parseFloat(duration.join(''))
const recorder = {
data: blob,
duration: duration,
localUrl: localUrl
}
this.$emit('success', recorder)
this.isRecord = false
},
onErrorHandler(err) {
console.log(err)
if (err.name === 'NotAllowedError') {
this.$emit('error', '201')
// throw '用户拒绝了当前的浏览器实例的访问请求'
}
if (err.name === 'NotReadableError') {
this.$emit('error', '101')
// throw '当前浏览器不支持'
}
this.$emit('error', '500')
// throw '调用失败,原因不详'
}
},
destroyed() {
this.stop()
}
}
</script>
<style>
</style>
二、调用插件
<template>
<!-- HTML -->
<div>
<audio :src='recorder.localUrl' v-if='recorder' name='本地录音' controls="true"></audio>
<button @click='handlerOnCahnger'>{{!status?'开始录音':'结束录音'}}</button>
当前音量:{{volume}}
<mumu-recorder ref='recorder' @success='handlerSuccess' @error='handlerError' @getVolume="getVolume"></mumu-recorder>
</div>
</template>
<script>
import MumuRecorder from '@/uni_modules/recorder/components/mumu-recorder/mumu-recorder.vue'
export default {
components: {
MumuRecorder
},
data() {
return {
status: false,
recorder: null,
volume:0,//实时音量大小
}
},
onLoad() {
},
methods: {
getVolume(volume){//获取实时音量大小
this.volume = volume
},
handlerSave() {
let tag = document.createElement('a')
tag.href = this.recorder.localUrl
tag.download = '录音'
tag.click()
},
handlerOnCahnger() {
if (this.status) {
this.$refs.recorder.stop()
} else {
this.$refs.recorder.start()
}
this.status = !this.status
},
handlerSuccess(res) {//返回的音频
this.recorder = res
console.log(res, '48');
},
handlerError(code) {
switch (code) {
case '101':
uni.showModal({
content: '当前浏览器版本较低,请更换浏览器使用,推荐在微信中打开。'
})
break;
case '201':
uni.showModal({
content: '麦克风权限被拒绝,请刷新页面后授权麦克风权限。'
})
break
default:
uni.showModal({
content: '未知错误,请刷新页面重试'
})
break
}
}
}
}
</script>
<style lang="less">
</style>