通过Socket.io从浏览器发送音视频:Buffer接收处理方案咨询
Socket.io传输音视频收到Buffer数据的处理方案
嘿,这问题我熟!Socket.io传输音视频时收到Buffer完全是正常情况——因为二进制数据在Node.js端就是以Buffer形式存在的,浏览器端则对应ArrayBuffer,我们只需要把这些二进制数据转换成能被浏览器音视频标签识别的格式就行。下面我结合你的代码一步步调整:
一、服务端优化(可选,但更稳妥)
你的服务端代码其实没啥大问题,不过可以明确开启二进制支持(虽然Socket.io默认已经开启),避免潜在的兼容问题:
const http = require('http').createServer(); const io = require('socket.io')(http, { transports: ['websocket'], // 优先用WebSocket传输,更适配二进制数据 binary: true // 明确开启二进制传输支持 }); io.on('connection', function (socket) { socket.on('radio', function (bufferData) { // 直接转发二进制数据即可,无需额外处理 socket.broadcast.emit('radio-reciver', {count: 1, buff: bufferData}); }) }) const port = 3000; http.listen(port, function () { console.log(`Server started on port ${port}!`) });
二、客户端发送端调整(正确捕获音视频数据)
我补全你未写完的loadCam函数,用MediaRecorder来捕获标准的音视频片段,这样发送的是浏览器能识别的媒体二进制数据:
const socket = io(); // 获取摄像头和麦克风流 navigator.mediaDevices.getUserMedia({ video: true, audio: true }) .then(loadCam) .catch(loadFail); function loadCam(stream) { // 初始化MediaRecorder,用于分段捕获音视频数据 const mediaRecorder = new MediaRecorder(stream); // 每捕获到一段有效数据就发送给服务端 mediaRecorder.ondataavailable = function(e) { if (e.data.size > 0) { // 把Blob转成ArrayBuffer再发送,Socket.io会自动处理传输细节 e.data.arrayBuffer().then(buffer => { socket.emit('radio', buffer); }); } }; // 每100ms发送一段数据,平衡延迟和播放流畅度 mediaRecorder.start(100); } function loadFail(err) { console.error('获取摄像头/麦克风权限失败:', err); }
三、客户端接收端处理(把Buffer转成可播放的音视频)
收到Buffer后,我们用MediaSource来拼接二进制片段,让video标签可以连续播放:
首先在页面添加播放远程视频的标签:
<video id="remote-video" autoplay playsinline></video>
然后编写接收处理逻辑:
const video = document.getElementById('remote-video'); const mediaSource = new MediaSource(); video.src = URL.createObjectURL(mediaSource); let sourceBuffer; // 等MediaSource初始化完成后创建SourceBuffer mediaSource.addEventListener('sourceopen', function() { // MIME类型要和MediaRecorder录制的格式完全匹配,你可以在发送端打印mediaRecorder.mimeType获取准确值 // 常用兼容格式:video/webm; codecs="vp8,opus" sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp8,opus"'); }); // 接收服务端转发的音视频数据 socket.on('radio-reciver', function(data) { // 统一把Buffer/ArrayBuffer转换成标准ArrayBuffer格式 const arrayBuffer = data.buff instanceof Buffer ? data.buff.buffer.slice(data.buff.byteOffset, data.buff.byteOffset + data.buff.byteLength) : data.buff; // 如果SourceBuffer正在更新,等待更新结束再添加新数据 if (sourceBuffer.updating) { sourceBuffer.addEventListener('updateend', function addNewBuffer() { sourceBuffer.removeEventListener('updateend', addNewBuffer); sourceBuffer.appendBuffer(arrayBuffer); }); } else { sourceBuffer.appendBuffer(arrayBuffer); } });
关键注意点
- MIME类型必须匹配:一定要保证
MediaRecorder的录制格式和SourceBuffer的MIME类型完全一致,否则视频会无法播放。你可以在发送端打印mediaRecorder.mimeType获取准确值。 - 数据顺序问题:WebSocket是可靠传输,一般不会出现数据乱序,但如果遇到播放卡顿,可以给每个数据包加序号,排序后再拼接。
内容的提问来源于stack exchange,提问作者Vladimir Djukic
相关产品推荐
相关产品推荐

