【问题标题】:Live-streaming video by connecting ArrayBuffers client-side通过连接 ArrayBuffers 客户端实时流式传输视频
【发布时间】:2026-02-19 09:45:02
【问题描述】:

我正在尝试制作一个简单的实时网络摄像头流式传输(1 个流传输到多个客户端),但在客户端显示视频时遇到了问题。

我的基本系统是使用MediaRecorder将网络摄像头录制成1000ms的块,使用WebSocket发送到服务器,然后广播该记录所有其他用户,并且这些ArrayBuffers被转换并在用户网页上连续播放.这是我的代码:

//recieve video chunks from server
socket.on('video-stream', (stream) => {
  console.log(stream);
  createVideo(URL.createObjectURL(new Blob(stream)), 1);
});

//record video in chunks, send over websocket
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream) => {
  setInterval(function () {
    record(stream, 1000).then((recording) => {
      socket.emit('video-stream', {
        stream: recording,
        room: window.location.pathname.split('/')[0] || '/',
        cam: 1,
      });
    });
  }, 1000);
});

var record = (stream, ms) => {
  var rec = new MediaRecorder(stream),
    data = [];
  rec.ondataavailable = (e) => data.push(e.data);
  rec.start();
  var stopped = new Promise(
    (y, n) => ((rec.onstop = y), (rec.onerror = (e) => n(e.error || e.name)))
  );
  return Promise.all([stopped, wait(ms).then(() => rec.stop())]).then(() => data);
};

var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

function createVideo(stream, cam) {
  var video = document.getElementById('cam-' + cam + '-embed');
  video.src = stream;
  //video.addEventListener('click', () => {
  //  if (video.volume != 0) video.volume = 0;
  //  else video.volume = 1;
  //});
}

问题在于,这需要每 1000 毫秒更改一次页面上视频元素的 src,这使得视频不断闪烁并且不流畅。我需要一些方法来合并客户端的传入视频缓冲区,而不是不断更改视频元素。我一直在试图弄清楚如何在没有运气的情况下做到这一点。有人可以帮我将传入的数据合并为 1 个视频吗?

我也试过: -RTC - 不起作用,因为流媒体用户需要大量带宽。 - 在服务器端对视频进行编码和连接,然后将其作为可读流传输到响应中。这也没有奏效。

【问题讨论】:

    标签: node.js socket.io stream video-streaming mediarecorder


    【解决方案1】:

    您需要 mediasource 和 sourcebuffer。像这样的:

    var video = document.querySelector("#video");
    video.src = URL.createObjectURL(mediaSource)
    
    socket.on('onChunk', (d) => {          
      if(mediaSource.readyState == 'open') {
        sourceBuffer.appendBuffer(d);
      }
    })
    var mediaSource = new MediaSource();
    var sourceBuffer = null;
    mediaSource.addEventListener("sourceopen", function()
    {
      sourceBuffer = mediaSource.addSourceBuffer("video/webm;codecs=vp8,opus");
    });
    
    

    更多信息:HTML5 Video: Streaming Video with Blob URLs

    【讨论】:

    • 这当然有帮助,但现在我的视频在第一块之后就冻结了。客户端仍在接收下一个块,并且似乎它们已成功添加到 sourceBuffer,但我仍然不明白为什么它只播放第一个剪辑然后冻结。有什么帮助吗?
    最近更新 更多