我想记录5秒长的用户麦克风段,并将每个段上传到服务器.我尝试使用MediaRecorder并且我以5秒的时间间隔调用了start()和stop()方法,但是当我连接这些录音时,它们之间会发出“掉落”的声音.所以我尝试使用start()方法的timeslice参数记录5秒段:
navigator.mediaDevices.getUserMedia({ audio: { channelCount: 2, volume: 1.0, echoCancellation: false, noiseSuppression: false } }).then(function(stream) {
const Recorder = new MediaRecorder(stream, { audioBitsPerSecond: 128000, mimeType: "audio/ogg; codecs=opus" });
Recorder.start(5000);
Recorder.addEventListener("dataavailable", function(event) {
const audioBlob = new Blob([event.data], { type: 'audio/ogg' });
upload(audioBlob);
});
});
但只有第一段是可玩的.我该怎么做,或者我怎样才能使所有blob都可玩?
我必须记录然后上传每个段.我不能制作一个blob数组(因为用户可以记录24小时的数据甚至更多,并且数据需要在用户录制时上传到服务器上 – 延迟5秒).
谢谢!
解决方法:
您必须了解媒体文件的构建方式.
不仅可以将一些原始数据直接转换为音频或视频.
它将取决于所选择的格式,但基本情况是您拥有所谓的元数据,就像描述文件结构的字典一样.
这些元数据对于软件来说是必需的,然后软件将读取文件以了解它应如何解析文件中包含的实际数据.
MediaRecorder API在这里处于一个奇怪的位置,因为它必须能够同时写入这些元数据,并且还要添加未确定的数据(它是一个实时记录器).
那么接下来会发生的是,浏览器会将主要元数据放在文件的开头,以便他们能够简单地将新数据推送到文件中,并且仍然是一个有效的文件(即使有些信息如持续时间也会失踪).
现在,您在datavailableEvent.data中获得的内容只是生成的整个文件的一部分.
第一个通常包含元数据和一些其他数据,具体取决于事件被告知触发的时间,但下一部分不一定包含任何元数据.
因此,您不能仅将这些部分作为独立文件获取,因为生成的唯一文件是由所有这些部分组成的文件,在单个Blob中连接在一起.
那么,对于你的问题,你有不同的方法:
>您可以在一个时间间隔内向服务器发送从录像机获得的最新切片,并合并这些服务器端.
const recorder = new MediaRecorder(stream);
const chunks = [];
recorder.ondataavailable = e => chunks.push(e.data);
recorder.start(); // you don't need the timeslice argument
setInterval(()=>{
// here we both empty the 'chunks' array, and send its content to the server
sendToServer(new Blob(chunks.splice(0,chunks.length)))
}, 5000);
在服务器端,您可以将新发送的数据附加到正在记录的文件中.
>另一种方法是生成许多小型独立文件,为此,您只需在一个时间间隔内生成一个新的MediaRecorder:
function record_and_send(stream) {
const recorder = new MediaRecorder(stream);
const chunks = [];
recorder.ondataavailable = e => chunks.push(e.data);
recorder.onstop = e => sendToServer(new Blob(chunks));
setTimeout(()=> recorder.stop(), 5000); // we'll have a 5s media file
recorder.start();
}
// generate a new file every 5s
setInterval(record_and_send, 5000);
这样做,每个文件将是独立的,持续时间约为5秒,您将能够逐个播放这些文件.
现在,如果你只希望在服务器上存储一个文件,仍然使用这种方法,你可以很好地在服务器端将这些文件合并在一起,例如使用像ffmpeg这样的工具.