javascript - 使用 MediaRecorder 录制 5 秒的音频片段,然后上传到服务器

标签 javascript blob mediarecorder web-mediarecorder

我想记录用户的麦克风 5 秒长的片段并将每个片段上传到服务器。我尝试使用 MediaRecorder 并以 5 秒的时间间隔调用 start() 和 stop() 方法,但是当我连接这些录音时,它们之间会出现“滴”的声音。所以我尝试使用 start() 方法的时间片参数记录 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 这样的工具.
  • 关于javascript - 使用 MediaRecorder 录制 5 秒的音频片段,然后上传到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51325136/

    相关文章:

    javascript - 即使设置了 key,在 React 中也会收到 key prop 警告

    javascript - 检测 360 度视频 youtube 支持

    javascript - 在浏览器中替换文件 blob?

    sql - 甲骨文10 : Using HEXTORAW to fill in blob data

    android - 使用 MediaRecorder 录制屏幕特定 View

    Android - MediaRecorder 的回调开始录制

    electron - MediaRecorder Blob 在 Electron 应用程序中归档

    javascript - 如何忽略 XmlHttpRequest 中的自签名证书

    javascript - CSS Transition 不适用于可见性 :hidden

    javascript - Blob 图像无法使用 JavaScript 进入 Canvas