基于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
相关产品推荐
相关产品推荐

