前端js调用浏览器录音,实现前端录音
if (navigator.mediaDevices.getUserMedia) {
const constraints = {
audio: true
};
let chunks = [];
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
this.recorder = new MediaRecorder(stream);
this.recorder.onstop = () => {
const blob = new Blob(chunks, {
type: 'audio/ogg; codecs=opus'
});
chunks = [];
const audioURL = URL.createObjectURL(blob);
this.audio.src = audioURL;
this.audio.oncanplay = function(e) {
console.error(this.duration, e);
this.play();
};
this.submitRecord(blob);
};
this.recorder.ondataavailable = function(e) {
chunks.push(e.data);
};
})
.catch((err) => {
this.cantRecord = false;
console.error('您的设备不能录音', err);
});
} else {
this.cantRecord = false;
console.error('您的设备不能录音');
}
但是这样写会遇到问题,我们在获取获取audio的duration时候会发现 duration 是Infinity? 这是如果我们动态的展示录音时间时候就会有问题。首先明确一下这是chrome浏览器自己的存在的一个bug,因为我们拿到的录音数据流没有定义长度,所以浏览器无法解析出当前音频的时长。
如何解决
formatePlayerDuration() {
this.player.onloadedmetadata = e => {
const audio = e.target;
const audioDuration = audio.duration;
if (audioDuration === Infinity) {
audio.currentTime = 1e101;
audio.ontimeupdate = function () {
this.ontimeupdate = () => {
return;
};
// 不重新设置currtTime,会直接触发audio的ended事件,因为之前将currentTime设置成了一个比音频时长还大的值。所以要将currentTime重置为初始状态。
// 注: 这里有一个问题,直接设置为0 是不起作用的。需要重新设置一下audio.currentTime = 1e101;然后再设置为0
audio.currentTime = 1e101;
audio.currentTime = 0;
};
}
};
}
完整代码
const recorder = {
init() {
this.initRecordPlayer();
this.initRecorder();
this.formatePlayerDuration();
},
initRecordPlayer() {
this.player = document.createElement('audio');
},
formatePlayerDuration() {
this.player.onloadedmetadata = e => {
const audio = e.target;
const audioDuration = audio.duration;
if (audioDuration === Infinity) {
audio.currentTime = 1e101;
audio.ontimeupdate = function () {
this.ontimeupdate = () => {
return;
};
// 不重新设置currtTime,会直接触发audio的ended事件,因为之前将currentTime设置成了一个比音频时长还大的值。
// 注: 这里有一个问题,直接设置为0 是不起作用的。需要重新设置一下audio.currentTime = 1e101;然后再设置为0
audio.currentTime = 1e101;
audio.currentTime = 0;
};
}
};
},
initRecorder() {
if (navigator.mediaDevices.getUserMedia) {
const constraints = {
audio: true
};
let chunks = [];
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
this.recorder = new MediaRecorder(stream);
this.recorder.onstop = () => {
const blob = new Blob(chunks, {
type: 'audio/ogg; codecs=opus'
});
chunks = [];
const audioURL = URL.createObjectURL(blob);
this.audio.src = audioURL;
// 录完自动播放
this.audio.oncanplay = function (e) {
this.play();
};
};
this.recorder.ondataavailable = function (e) {
chunks.push(e.data);
};
})
.catch((err) => {
console.error('您的设备不能录音', err);
});
} else {
console.error('您的设备不能录音');
}
}
}
这就是相关的简单例子,实现方案大体就是这样,(代码我没跑啊,直接是从业务中粘贴粘贴攒的),但是思路就是这样,自测业务没有问题,大家有问题可以留言,一起解决纠正