无法将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
相关产品推荐
相关产品推荐

