在网上找到关于HTML5的录音教程,但是发现转成Vue的时候报错了。所以写一下解决方法。
本文是在此文的基础上进行修改的,使用了recorder.js和worker.js。同时因为Vue找不到worker.js文件,所以修改了部分源码,最终实现。其中坑多多,各位注意踩坑。
首先是Vue的文件。
进行说明:recordercopy为修改后的recorder.js,由于是父子组件关系,所以按钮是通过isStart的true和false来实现触发点击事件的。limit 是限制加载时候直接进入导致报错。同时,返回blobx文件到父组件。
<template>
<div>
</div>
</template>
<script>
import Recorder from '../../js/recordercopy'
export default {
name: "audioState",
props: {
isStart: {
type: Boolean,
default: false,
},
},
data() {
return {
recorder: {},
limit: 0
};
},
methods: {
github() {
if (this.recorder.start) {
let blobx = {}
if(this.isStart){
this.recorder.start()
this.limit = 1
}else{
if(this.limit == 0) return
this.recorder.stop()
new Promise((resolve, reject) => {
// 一段耗时的异步操作
this.recorder.getBlob(function (blob) {
blobx = blob
let download = document.createElement("a");
download.href = URL.createObjectURL(blob);
download.download = `视频对话录音.mp3`;
download.click();
console.log('打印结束:',blobx)
resolve(blobx) // 数据处理完成
});
// reject('失败') // 数据处理出错
}
).then(
(res) => {
this.$emit("wavHref", res);
}, // 成功
(err) => {console.log(err)} // 失败
)
}
}else{
this.github()
}
}
},
watch: {
isStart(x) {
this.github();
},
},
mounted() {
this.recorder = new Recorder({
sampleRate: 44100, //采样频率,默认为44100Hz(标准MP3采样率)
bitRate: 128, //比特率,默认为128kbps(标准MP3质量)
success: function () { //成功回调函数
},
error: function (msg) { //失败回调函数
alert(msg);
},
fix: function (msg) { //不支持H5录音回调函数
alert(msg);
}
})
this.github();
},
};
</script>
<style scoped>
</style>
父组件调用:
根据这个修改了方法:
修改后的recorder.js文件。
// var MyWorker = new Worker(require("./my.worker.js"));
var blobx = new Blob([document.querySelector('#MyWorker').textContent]);
var url = window.URL.createObjectURL(blobx);
var MyWorker = new Worker(url);
console.log(MyWorker)
//公共方法
var localMediaStream
var Util = {
//初始化
init: function() {
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
window.AudioContext = window.AudioContext ||
window.webkitAudioContext;
},
//日志
log: function() {
console.log.apply(console, arguments);
}
};
//构造函数
var Recorder = function(config) {
var _this = this;
config = config || {}; //初始化配置对象
config.sampleRate = config.sampleRate || 44100; //采样频率,默认为44100Hz(标准MP3采样率)
config.bitRate = config.bitRate || 128; //比特率,默认为128kbps(标准MP3质量)
Util.init();
if (navigator.getUserMedia) {
navigator.getUserMedia({
audio: true //配置对象
},
function(stream) { //成功回调
localMediaStream = stream.getTracks()[0]
var context = new AudioContext(),
microphone = context.createMediaStreamSource(stream), //媒体流音频源
processor = context.createScriptProcessor(16384, 1, 1), //js音频处理器
successCallback, errorCallback;
config.sampleRate = context.sampleRate;
processor.onaudioprocess = function(event) {
//监听音频录制过程
var array = event.inputBuffer.getChannelData(0);
realTimeWorker.postMessage({ cmd: 'encode', buf: array });
};
// var realTimeWorker = new Worker('./my.worker.js'); //开启后台线程
var realTimeWorker = MyWorker; //开启后台线程
realTimeWorker.onmessage = function(e) { //主线程监听后台线程,实时通信
console.log('进来这边')
console.log(e.data.cmd)
switch (e.data.cmd) {
case 'init':
Util.log('初始化成功');
if (config.success) {
config.success();
}
break;
case 'end':
if (successCallback) {
console.log('执行recorder')
var blob = new Blob(e.data.buf, { type: 'audio/mp3' });
successCallback(blob);
Util.log('MP3大小:' + blob.size + '%cB', 'color:#0000EE');
}
break;
case 'error':
Util.log('错误信息:' + e.data.error);
if (errorCallback) {
errorCallback(e.data.error);
}
break;
default:
Util.log('未知信息:' + e.data);
}
};
//接口列表
//开始录音
_this.start = function() {
if (processor && microphone) {
microphone.connect(processor);
processor.connect(context.destination);
Util.log('开始录音');
}
};
//结束录音
_this.stop = function() {
if (processor && microphone) {
microphone.disconnect();
processor.disconnect();
localMediaStream.stop()
Util.log('录音结束');
}
};
//获取blob格式录音文件
_this.getBlob = function(onSuccess, onError) {
successCallback = onSuccess;
errorCallback = onError;
console.log('这是blob')
realTimeWorker.postMessage({ cmd: 'finish' });
};
realTimeWorker.postMessage({
cmd: 'init',
config: {
sampleRate: config.sampleRate,
bitRate: config.bitRate
}
});
},
function(error) { //失败回调
var msg;
switch (error.code || error.name) {
case 'PermissionDeniedError':
case 'PERMISSION_DENIED':
case 'NotAllowedError':
msg = '用户拒绝访问麦克风';
break;
case 'NOT_SUPPORTED_ERROR':
case 'NotSupportedError':
msg = '浏览器不支持麦克风';
break;
case 'MANDATORY_UNSATISFIED_ERROR':
case 'MandatoryUnsatisfiedError':
msg = '找不到麦克风设备';
break;
default:
msg = '无法打开麦克风,异常信息:' + (error.code || error.name);
break;
}
Util.log(msg);
if (config.error) {
config.error(msg);
}
});
} else {
Util.log('当前浏览器不支持录音功能');
if (config.fix) {
config.fix('当前浏览器不支持录音功能');
}
}
};
//模块接口
export default Recorder;
// import a from './worker'
修改后的worker.js,采用放到了全局,作为一个属性方法,MyWorker。
<!-- 视频监控 - 录制声音 需要的方法,其他没办法录入耳机里的声音,只录入了麦克风的声音,采用这种方法进行 -->
<!-- 这种方法的弊端是导致lamejs方法引入不了,导致只能直接放源码来引入lame,如果有更好的办法,请直接改进 -->
<script id="MyWorker" type="app/worker">
console.log('worker123')
var mp3Encoder, maxSamples = 1152, samplesMono, lame, config, dataBuffer;
var clearBuffer = function(){
dataBuffer = [];
};
var appendToBuffer = function(mp3Buf){
dataBuffer.push(new Int8Array(mp3Buf));
};
var init = function(prefConfig){
console.log('初')
config = prefConfig || {};
console.log('lamejs:', lamejs)
lame = new lamejs();
mp3Encoder = new lame.Mp3Encoder(1, config.sampleRate || 44100, config.bitRate || 128);
clearBuffer();
self.postMessage({
cmd: 'init'
});
console.log('消息')
};
var floatTo16BitPCM = function(input, output){
for(var i = 0; i < input.length; i++){
var s = Math.max(-1, Math.min(1, input[i]));
output[i] = (s < 0 ? s * 0x8000 : s * 0x7FFF);
}
};
var convertBuffer = function(arrayBuffer){
var data = new Float32Array(arrayBuffer);
var out = new Int16Array(arrayBuffer.length);
floatTo16BitPCM(data, out);
return out;
};
var encode = function(arrayBuffer){
samplesMono = convertBuffer(arrayBuffer);
var remaining = samplesMono.length;
for(var i = 0; remaining >= 0; i += maxSamples){
var left = samplesMono.subarray(i, i + maxSamples);
var mp3buf = mp3Encoder.encodeBuffer(left);
appendToBuffer(mp3buf);
remaining -= maxSamples;
}
};
var finish = function(){
console.log('worker-end')
appendToBuffer(mp3Encoder.flush());
self.postMessage({
cmd: 'end',
buf: dataBuffer
});
clearBuffer();
};
self.onmessage = function(e){
switch(e.data.cmd){
case 'init':
init(e.data.config);
break;
case 'encode':
encode(e.data.buf);
break;
case 'finish':
finish();
break;
}
};
function lamejs(){
//这边放lamejs的源码
}
</script>
备注:要放入lamejs的文件