【问题标题】:Get ReadableStream from Webcam in Browser从浏览器中获取从网络摄像头中的readableStream
【发布时间】:2021-06-29 16:28:06
【问题描述】:

我想在浏览器中将网络摄像头输入作为 ReadableStream 以管道传输到 WritableStream。我曾尝试使用 MediaRecorder API,但该流被分块成单独的 blob,而我想要一个连续的流。我认为解决方案可能是将 MediaRecorder 块通过管道传输到统一缓冲区并作为连续流从中读取,但我不确定如何使该中间缓冲区正常工作。

mediaRecorder = new MediaRecorder(stream, recorderOptions);
mediaRecorder.ondataavailable = handleDataAvailable;

mediaRecorder.start(1000);

async function handleDataAvailable(event) {
  if (event.data.size > 0) {
    const data: Blob = event.data;
    // I think I need to pipe to an intermediate stream? Not sure how tho 
    data.stream().pipeTo(writable);
  }
}

【问题讨论】:

    标签: javascript webcam mediastream mediarecorder-api


    【解决方案1】:

    目前我们无法真正访问 MediaStream 的原始数据,最接近视频的是 MediaRecorder API,但这将对数据进行编码,并按块而不是流的形式工作。

    但是,有一个新的 MediaCapture Transform W3C 小组正在开发一个 MediaStreamTrackProcessor 界面,可以完全按照您的要求进行操作,并且该界面已经在 Chrome 中的 chrome://flags/#enable-experimental-web-platform-features 标志下可用。
    在读取结果流时,根据您通过的曲目类型,您将获得对 VideoFramesAudioFrames 的访问权限,这些都是由新的 WebCodecs API 添加的。

    if( window.MediaStreamTrackProcessor ) {
      const track = getCanvasTrack();
      const processor = new MediaStreamTrackProcessor( track );
      const reader = processor.readable.getReader();
      readChunk();
      function readChunk() {
        reader.read().then( ({ done, value }) => {
          // value is a VideoFrame
          // we can read the data in each of its planes into an ArrayBufferView
          const channels = value.planes.map( (plane) => {
            const arr = new Uint8Array(plane.length);
            plane.readInto(arr);
            return arr;
          });
          value.close(); // close the VideoFrame when we're done with it
    
          log.textContent = "planes data (15 first values):\n" +
            channels.map( (arr) => JSON.stringify( [...arr.subarray(0,15)] ) ).join("\n");
          if( !done ) {
            readChunk();
          }
        });
      }
    }
    else {
      console.error("your browser doesn't support this API yet");
    }
    
    function getCanvasTrack() {
      // just some noise...
      const canvas = document.getElementById("canvas");
      const ctx = canvas.getContext("2d");
      const img = new ImageData(300, 150);
      const data = new Uint32Array(img.data.buffer);
      const track = canvas.captureStream().getVideoTracks()[0];
    
      anim();
      
      return track;
      
      function anim() {
        for( let i=0; i<data.length;i++ ) {
          data[i] = Math.random() * 0xFFFFFF + 0xFF000000;
        }
        ctx.putImageData(img, 0, 0);
        if( track.readyState === "live" ) {
          requestAnimationFrame(anim);
        }
      }
      
    }
    <pre id="log"></pre>
    <p>
    Source<br>
    <canvas id="canvas"></canvas>
    </p>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多