You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法将MediaStream对象发送至NodeJS服务器,服务器接收内容为空

问题分析与解决方案

你遇到的核心问题是:MediaStream对象无法直接通过socket.io序列化传输。浏览器的媒体流对象包含大量不可序列化的底层资源引用(比如硬件设备句柄、实时数据流指针),socket.io在尝试序列化这类对象时,会自动丢弃那些无法转化为JSON格式的属性,最终服务器收到的就是空对象{}。

下面是不依赖WebRTC的纯socket.io传输方案:

解决方案:将MediaStream转为可传输的Blob数据

我们可以使用浏览器的MediaRecorderAPI把实时媒体流录制成小的Blob片段,然后将这些Blob数据发送给Node.js服务器。

修改后的客户端代码

if (navigator.mediaDevices.getUserMedia) { 
  navigator.mediaDevices.getUserMedia({ video: true, audio: true }) 
  .then( (stream) => { 
    video.srcObject = stream; 
    // 创建MediaRecorder实例,指定编码格式
    const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp9' });
    
    // 每捕获到一段数据就发送给服务器
    mediaRecorder.ondataavailable = (event) => {
      if (event.data.size > 0) {
        // socket.io支持直接传输Blob对象
        socket.emit('streamVideoEvent', event.data);
      }
    };
    
    // 开始录制,每1秒生成一个片段(可根据需求调整时间间隔)
    mediaRecorder.start(1000);
  }) 
  .catch(function (error) { 
    console.log("Something went wrong!"); 
    console.log(error) 
  }); 
}

修改后的服务器端代码

const fs = require('fs');
// 提前创建可追加的文件写入流(避免重复创建)
const videoWriteStream = fs.createWriteStream('received_video.webm', { flags: 'a' });

socket.on('streamVideoEvent', (videoBlob) => { 
  console.log('收到媒体片段,大小:', videoBlob.size);
  // 将Blob数据写入本地文件(也可根据需求存储到数据库或转发)
  videoBlob.stream().pipe(videoWriteStream);
  
  socket.emit('recieveVideoElement', '已成功接收媒体片段');
})

关键说明

  • MediaRecorder支持多种编码格式,比如video/webm、video/mp4等,你可以根据浏览器兼容性和需求选择
  • 如果需要更高的实时性,可以调整start()方法的时间间隔(比如500ms),但会相应增加网络传输压力
  • 服务器端接收的Blob片段可以持续拼接成完整的媒体文件,也可以根据业务需求做其他处理

内容的提问来源于stack exchange,提问作者MJ007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:33:16