如何解决使用mediarecorder API的播放确实很奇怪:不同的设备在不同的设备上丢失了
我正在开发一个在浏览器中运行的应用程序,用户可以在其中记录自己的声音。使用MediaRecorder API,我可以获取记录并将其发布到我的服务器上。如果用户暂停并重新开始录制,则会出现问题。发生这种情况时,他们第一次从服务器上获得播放效果很好,但是当重播时,仅播放最后一段。如果我重新加载网页并重试,则第一次获取完整的录音时,再一次,它只是最后一个片段。
它正在使用opus编解码器,因此我尝试在VLC中播放它。在那里,我仅获得第一段,而随后的任何段都没有。最后,我尝试了转换为MP3,当我这样做时-MP3拥有整个录音!所以整个事情都被保存了,但是不知何故,这些段似乎存储在文件中并弄乱了重播。在每种情况下,只有一小段正在播放。我不得不说我对如何攻击这个感到茫然。玩家显示的时间是第一段的时间,无论播放的是第一段,第二段还是整段。有什么想法吗?
已编辑以提供可行的示例
如何测试:将此代码放在可以提供服务的地方并打开它(我使用基于chrome的浏览器)。单击开始以开始录制,然后单击暂停,然后再次单击开始以继续录制,然后再次暂停以停止。然后单击设置以加载录音,并收听录音。第一次收听时,我会得到完整的录音,尽管播放计时器只显示第一段。随后的播放仅播放最后一段。再次按下设置按钮将使其播放整个录音,但是仅第一次播放。
<!doctype html>
<html>
<head>
<script>
var audio = null;
function init() {
audio = new Recording();
audio.prepareAudio();
}
class Recording {
recordButton;
pauseButton;
recorder;
mimeType;
audioChunks;
constructor() {
this.mimeType = this.recorder = null;
this.recordButton = this.pauseButton = null;
this.audioChunks = [];
}
getRecorder() {
return new Promise(async resolve => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream);
var _this = this;
mediaRecorder.addEventListener('dataavailable',event => {
_this.audioChunks.push(event.data);
});
const start = () => {
mediaRecorder.start();
};
const pause = () =>
new Promise(resolve => {
mediaRecorder.addEventListener('stop',() => {
resolve(_this.audioChunks);
});
mediaRecorder.stop();
_this.mimeType = mediaRecorder.mimeType;
});
resolve({ start,pause });
});
}
get codec() {
if (!this.mimeType) return null;
let split = this.mimeType.split('=');
return (split.length > 1) ? split[1] : split;
}
prepareAudio() {
this.recordButton = document.querySelector('#record');
this.pauseButton = document.querySelector('#pause');
var _this = this;
this.recordButton.addEventListener('click',async () => {
_this.recordButton.setAttribute('disabled',true);
_this.pauseButton.removeAttribute('disabled');
if (!_this.recorder) {
_this.recorder = await this.getRecorder();
}
_this.recorder.start();
});
this.pauseButton.addEventListener('click',async () => {
_this.recordButton.removeAttribute('disabled');
_this.pauseButton.setAttribute('disabled',true);
await _this.recorder.pause();
});
}
data() {
return new Promise((resolve,reject) => {
const reader = new FileReader();
let codec = this.audioChunks[0].type;
let audioBlob = new Blob(this.audioChunks,{type: this.codec || codec});
reader.readAsDataURL(audioBlob);
reader.onload = () => resolve({codec: codec,data: reader.result.split(',')[1]});
});
}
blobUrl() {
let codec = this.audioChunks[0].type;
let audioBlob = new Blob(this.audioChunks,{type: this.codec || codec});
let blobUrl = URL.createObjectURL(audioBlob);
let player = document.getElementById('play-blob');
player.src = blobUrl;
player.disabled = false;
return blobUrl;
}
}
</script>
</head>
<body onload="init()">
<div>
<button id="record" class="button fill" >Start</button>
<br />
<button id="pause" class="button fill" >Pause</button>
<br />
<button class="button fill" onclick="audio.blobUrl()">setup</button>
</div>
<audio id="play-blob" controls></audio>
</body>
</html>
解决方法
这不是一个完整的答案,但是我对正在发生的事情了解得更多。音频播放器(至少对于我正在使用的Chrome和Firefox版本(最新))似乎无法正确处理流音频。当源被加载时,它不知道长度(当然)。当创建具有多个片段( new Blob([segment1,segment2,...]))的Blob时,第一次将持续时间设为无穷大,并播放整个剪辑。在随后的播放中,剪辑时间以最长片段的长度给出,仅播放最后一个片段。音频对象将持续时间作为最长片段的长度。
我还通过使用howler更换音频设备解决了眼前的问题。就像我反复期望的那样播放整个剪辑。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。