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

使用Peer.js发送/接收视频文件数据失败问题求助

问题分析与修复方案

核心问题点

  1. 跨房间消息推送错误:服务端使用全局广播推送新用户加入通知,导致非目标dashboard的用户也收到连接请求。
  2. PeerJS入站连接未处理:仅主动发起连接但未监听其他peer的连接请求,导致接收方无法感知连接,自然收不到数据。
  3. 发送逻辑耦合过紧:发送按钮事件绑定在单个连接的回调中,无法向多个已连接节点发送数据,且重复绑定会引发异常。

修复后的代码

服务端代码

// Creating a express server
const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server); // Passing the server created to socket.io 
const { v4: uuidV4 } = require('uuid')

// Set up Express.js
app.set('view engine', 'ejs');
app.use(express.static('public'));

app.get('/', (req, res) => {
  res.redirect(`/${uuidV4()}`)
});

app.get('/:dashboard', (req, res) => {
  res.render('dashboard', { dashboardId: req.params.dashboard })
})

// Set up Socket.io
io.on('connection', socket => {
  socket.on('join', (dashboardId, userId) => {
    socket.join(dashboardId)
    // 仅向当前dashboard内的其他用户推送新用户加入通知
    socket.to(dashboardId).emit('userJoined', { userId: userId })
  })
})

// Start the server
const port = 3000;
server.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

客户端代码

const socket = io('/');
const peer = new Peer(undefined, {
  host: '/',
  port: '3001'
});

// 存储所有已建立的Peer连接
const activeConnections = [];
const video = document.getElementById('videoPlayer');
const fileInput = document.getElementById('fileInput');
const sendButton = document.getElementById('sendButton');
const CHUNK_SIZE = 5120; // 5KB

// 处理数据接收的通用逻辑
function handlePeerData(conn) {
  let videoData = new Uint8Array();
  conn.on('data', function (data) {
    console.log('Received chunk ' + (data.chunkIndex + 1) + ' of ' + data.totalChunks);
    // 扩容数组以容纳新数据
    if (videoData.length < (data.chunkIndex + 1) * CHUNK_SIZE) {
      const newBuffer = new Uint8Array((data.chunkIndex + 1) * CHUNK_SIZE);
      newBuffer.set(videoData);
      videoData = newBuffer;
    }
    videoData.set(data.chunk, data.chunkIndex * CHUNK_SIZE);
    if (data.chunkIndex + 1 === data.totalChunks) {
      const videoBlob = new Blob([videoData], { type: 'video/mp4' });
      const videoURL = URL.createObjectURL(videoBlob);
      video.src = videoURL;
      video.play();
    }
  });
}

// 发送文件到所有已连接的Peer
function sendFileToPeers(file) {
  const fileReader = new FileReader();
  fileReader.readAsArrayBuffer(file);
  fileReader.onload = function (event) {
    const arrayBuffer = event.target.result;
    const totalChunks = Math.ceil(arrayBuffer.byteLength / CHUNK_SIZE);
    
    activeConnections.forEach(conn => {
      let offset = 0;
      let chunkIndex = 0;
      while (offset < arrayBuffer.byteLength) {
        const chunk = arrayBuffer.slice(offset, offset + CHUNK_SIZE);
        const data = { chunk, name: file.name, totalChunks, chunkIndex };
        console.log('Sending chunk ' + (chunkIndex + 1) + ' of ' + totalChunks + ' to ' + conn.peer);
        conn.send(data);
        offset += CHUNK_SIZE;
        chunkIndex += 1;
      }
    });
  };
}

// 初始化Peer连接
peer.on('open', function (id) {
  socket.emit('join', DASHBOARD_ID, id);
  
  // 监听新用户加入,主动发起连接
  socket.on('userJoined', (userData) => {
    console.log('User joined:', userData.userId);
    const conn = peer.connect(userData.userId);
    conn.on('open', function () {
      console.log('Connected to peer: ' + conn.peer);
      activeConnections.push(conn);
      handlePeerData(conn);
    });
  });

  // 监听其他Peer发起的入站连接
  peer.on('connection', (conn) => {
    console.log('Incoming connection from: ' + conn.peer);
    conn.on('open', () => {
      activeConnections.push(conn);
      handlePeerData(conn);
    });
  });

  // 绑定发送按钮事件(仅绑定一次)
  sendButton.addEventListener('click', function () {
    const file = fileInput.files[0];
    if (!file) return;
    sendFileToPeers(file);
  });
});

额外说明

  • 新增activeConnections数组管理所有已建立的Peer连接,支持向多个节点同时发送视频。
  • 优化videoData的扩容逻辑,避免因初始数组长度不足导致的数据截断。
  • 将数据接收和发送逻辑抽离为通用函数,提升代码复用性和可维护性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 12:32:13