我想记录用户的麦克风5秒长的段并将其分别上传到服务器。我尝试使用MediaRecorder并以5秒的时间间隔调用了start()和stop()方法,但是当我串联这些记录时,它们之间会发出“滴”声。因此,我尝试使用start()方法的timelice参数记录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秒)。
谢谢!
答案 0 :(得分:4)
您必须了解媒体文件的构建方式。
不仅一些原始数据可以直接转换为音频或视频。
这取决于选择的格式,但是基本情况是您拥有称为 metadata 的东西,就像描述文件结构的字典一样。
这些元数据对于随后读取文件的软件来说是必需的,以了解该文件应如何解析文件中包含的实际数据。
MediaRecorder API在这里处于一个奇怪的位置,因为它必须能够同时写入这些元数据,并且还添加不确定的数据(这是 live < / em>记录器)。
因此,发生的情况是浏览器将主要的 metadata 放置在文件的开头,从而可以将新数据简单地推送到文件中,并且仍然是有效文件(即使某些信息(例如持续时间也会丢失)。
现在,您在datavailableEvent.data
中得到的只是正在生成的整个文件的一部分。
第一个通常包含 metadata 和其他一些数据,具体取决于事件被告知何时触发,但是接下来的部分不一定包含任何元数据。
因此,您不能仅将这些部分作为独立文件来获取,因为生成的唯一文件是由所有这些部分组成的文件,它们被合并到一个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的工具。