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

基于PeerJS与WebRTC的视频聊天应用无法显示其他用户视频求助

PeerJS视频聊天无法显示其他用户视频流排查

问题背景

使用PeerJS构建视频聊天网站,自身视频流可正常显示,但从另一个标签页登录后,无法看到其他用户的视频流。以下是客户端与服务端代码:

客户端代码

const socket = io();
const myPeer = new Peer(userID, {
  host: "/",
  port: 3001,
});

myPeer.on("open", (id) => {
  socket.emit("join-room", roomID, userID);
});

// Video wala part
const videoGrid = document.querySelector(".videoGrid");
const myVideo = document.createElement("video");
myVideo.muted = true;
navigator.mediaDevices
  .getUserMedia({
    audio: true,
    video: true,
  })
  .then((stream) => {
    addVideoStream(myVideo, stream);

    myPeer.on("call", (call) => {
      call.answer(stream);
      const userVideo = document.createElement("video");
      call.on("stream", (userVideoStream) => {
        console.log("User Video: ", userVideoStream);
        addVideoStream(userVideo, userVideoStream);
      });
    });
    socket.on("user-connected", (userID) => {
      console.log("user Connected", userID);
      connectToNewUser(userID, stream);
    });
  });

function connectToNewUser(userId, stream) {
  const call = myPeer.call(userId, stream);
  const video = document.createElement("video");
  call.on("stream", (userVideoStream) => {
    console.log("User Video: ", userVideoStream);
    addVideoStream(video, userVideoStream);
  });
  call.on("close", () => {
    video.remove();
  });
}

function addVideoStream(video, stream) {
  video.srcObject = stream;
  video.addEventListener("loadedmetadata", () => {
    video.play();
  });
  videoGrid.append(video);
}

服务端代码

io.on("connection", (socket) => {
  socket.on("join-room", (roomId, userId) => {
    socket.join(roomId);
    socket.broadcast.to(roomId).emit("user-connected", userId);
  });
});

参考某YouTube教程实现。

排查与修复方案

1. 解决PeerJS用户ID冲突问题

当前代码手动指定userID初始化Peer实例,若两个标签页使用相同userID,PeerJS服务器无法区分连接,导致呼叫失败。

  • 修改Peer初始化逻辑,让系统自动生成唯一ID:
const myPeer = new Peer({
  host: "/",
  port: 3001,
});
  • 更新join-room事件的用户标识,使用Peer自动生成的ID:
myPeer.on("open", (id) => {
  socket.emit("join-room", roomID, id);
});

2. 补充房间用户列表同步逻辑

当前服务端仅在新用户加入时广播连接事件,但新用户无法获取房间内已存在的用户,导致无法主动发起连接。

  • 修改服务端代码,向新用户发送房间内已有用户列表:
io.on("connection", (socket) => {
  socket.on("join-room", (roomId, userId) => {
    socket.join(roomId);
    // 向房间内其他用户通知新用户加入
    socket.broadcast.to(roomId).emit("user-connected", userId);
    // 获取房间内已存在的用户ID(排除当前用户)
    const existingUsers = Array.from(io.sockets.adapter.rooms.get(roomId) || []).filter(id => id !== socket.id);
    // 向新用户发送已有用户列表
    socket.emit("existing-users", existingUsers);
  });
});
  • 客户端新增监听existing-users事件,主动连接已存在的用户:
    在navigator.mediaDevices.getUserMedia的then回调中添加:
socket.on("existing-users", (userIds) => {
  userIds.forEach(userId => {
    connectToNewUser(userId, stream);
  });
});

3. 添加错误监听排查连接问题

为Peer实例和呼叫添加错误监听,便于定位问题:

// Peer实例错误监听
myPeer.on("error", (err) => {
  console.error("PeerJS错误:", err);
});

// 呼叫错误监听
function connectToNewUser(userId, stream) {
  const call = myPeer.call(userId, stream);
  const video = document.createElement("video");
  call.on("stream", (userVideoStream) => {
    console.log("User Video: ", userVideoStream);
    addVideoStream(video, userVideoStream);
  });
  call.on("error", (err) => {
    console.error("呼叫失败:", err);
    video.remove();
  });
  call.on("close", () => {
    video.remove();
  });
}

4. 确认PeerJS服务器运行状态

确保PeerJS服务器已在3001端口启动,本地测试可通过以下命令启动官方PeerJS服务器:

peerjs --port 3001

5. 注意浏览器环境限制

非localhost环境下,浏览器要求使用HTTPS协议才能正常使用WebRTC和媒体设备,线上部署需配置HTTPS。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:40:15