【问题标题】:How to get stream data from (web) MediaRecorder based on size instead of time?如何根据大小而不是时间从(网络)MediaRecorder 获取流数据?
【发布时间】:2021-11-02 12:06:47
【问题描述】:

我目前正在使用MediaRecorder 从用户的网络摄像头/麦克风中获取视频流的块,如下所示:

navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then((stream) => {
      var mediaRecorder = new MediaRecorder(stream);
      mediaRecorder.start(5000);

      mediaRecorder.ondataavailable = (blobEvent) => {
        console.log('got 5 seconds of stream', blobEvent);
      }
    })

这会每 5 秒发出一段视频流,但是,我想要特定大小的块,而不是长度。似乎没有一个明确的方法可以做到这一点,因为我无法在不开始新块的情况下检查当前块的大小,而且事后我也无法将它们组合起来。这是我想出的解决方法,使用 2 个媒体记录器:

  const MIN_BLOB_SIZE = 5000000;
  var partSize = 0;
  navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then((stream) => {
      var mediaRecorder = new MediaRecorder(stream);
      var mediaRecorder2 = new MediaRecorder(stream)
      mediaRecorder.start();
      mediaRecorder2.start(5000)

      mediaRecorder2.ondataavailable = (blobEvent) => {
          console.log('got 5 seconds of data', blobEvent)
          const blob = blobEvent.data
          partSize += blob.size;
          if (partSize >= MIN_BLOB_SIZE) {
              partSize = 0;
              mediaRecorder.requestData();
          }
      }

      mediaRecorder.ondataavailable = (blobEvent) => {
        console.log('got a chunk at least 5mb', blobEvent);
      };
    });

但这感觉很麻烦,提供不精确的块,需要我确保这两个记录器完全同步,使错误处理/边缘情况复杂化,而且我担心使用 2 个媒体记录器的性能影响。会接受使用一个媒体记录器完成此任务的答案,或者,如果这不可能,如果有人可以说服我 2 个媒体记录器在性能方面表现良好,我也会接受并处理它带来的复杂性。

【问题讨论】:

    标签: javascript typescript navigator web-mediarecorder


    【解决方案1】:

    组合块

    可以在事后将块与new Blob(blobArray) 合并。如果您绝对需要处理特定大小的 blob,可以使用Blob.slice。它可能看起来像这样:

    const MIN_BLOB_SIZE = 5000000;
    var partSize = 0, parts = [];
    navigator.mediaDevices
      .getUserMedia({audio: true, video: true})
      .then((stream) => {
        var mediaRecorder = new MediaRecorder(stream);
        mediaRecorder.start(5000);
        mediaRecorder.ondataavailable = (blobEvent) => {
            console.log('got 5 seconds of data', blobEvent);
            const blob = blobEvent.data;
            partSize += blob.size;
            parts.push(blob);
            if (partSize >= MIN_BLOB_SIZE) {
                let bigBlob = new Blob(parts, { type: blob.type });
                // if the blob size doesn't need to be precise:
                partSize = 0;
                parts = [];
                // do something with bigBlob
    
                // or if the blob size needs to be precise:
                // let sizedBlob = bigBlob.slice(0, MIN_BLOB_SIZE, blob.type);
                // parts = [ bigBlob.slice(MIN_BLOB_SIZE, bigBlob.size, blob.type) ];
                // partSize = parts[0].size;
                // do something with sizedBlob
    
            }
        };
        mediaRecorder.onstop = (blobEvent) => {
            console.log('Recording Stopped');
            const blob = blobEvent.data;
            partSize += blob.size;
            parts.push(blob);
            let bigBlob = new Blob(parts, { type: blob.type });
            // do something with bigBlob, which may be smaller than MIN_BLOB_SIZE
        };
    });
    

    使用比特率调整 Blob 大小

    您还可能对MediaRecorder API 中的bitsPerSecond(以及audioBitsPerSecondvideoBitsPerSecond)选项感兴趣,这可能会在给定的记录时间内为您提供更多可预测的blob 大小。不过,这可能会影响视频和音频质量。

    【讨论】:

    • 感谢您的回答,我将对此进行测试,看看它是否符合我的要求。斑点的精度不是很重要。更高兴拥有。
    猜你喜欢
    • 2019-02-28
    • 1970-01-01
    • 2011-11-02
    • 2017-10-14
    • 2016-03-09
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    相关资源
    最近更新 更多