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

WebRTC项目故障:关闭自身视频通话致所有连接断开,求代码修复

问题原因与解决方案

你的代码核心问题是用了单个myPeerConnection变量存储连接,在多客户端房间场景里,每个其他客户端都需要对应独立的RTCPeerConnection实例,而不是共用一个。所以挂断时会把唯一的连接关掉,导致所有通话断开。下面是具体修改方案:

核心修改思路

  1. 用连接映射表替代单个连接变量,每个用户对应独立的连接实例
  2. 让挂断逻辑只针对指定用户的连接,而非全部关闭
  3. 只有当所有连接都断开时,才停止本地摄像头(避免影响其他活跃通话)

修改后的代码示例

// 替换单个myPeerConnection为连接映射表,键是对方用户名,值是对应RTCPeerConnection实例
let peerConnections = {};
// 跟踪活跃连接数量,用来判断是否需要停止本地摄像头
let activeConnectionsCount = 0;

/* 关闭与指定用户的视频通话,而非全部 */
function closeVideoCall(targetUsername) {
  const localVideo = document.getElementById("local_video");
  log(`Closing call with ${targetUsername}`);

  // 获取对应目标的连接实例,不存在则直接返回
  const peerConnection = peerConnections[targetUsername];
  if (!peerConnection) return;

  log(`--> Closing peer connection with ${targetUsername}`);

  // 移除该连接的所有事件监听
  peerConnection.ontrack = null;
  peerConnection.onnicecandidate = null;
  peerConnection.oniceconnectionstatechange = null;
  peerConnection.onsignalingstatechange = null;
  peerConnection.onicegatheringstatechange = null;
  peerConnection.onnotificationneeded = null;

  // 停止该连接的所有收发器
  peerConnection.getTransceivers().forEach(transceiver => {
    transceiver.stop();
  });

  // 关闭连接并从映射表中移除
  peerConnection.close();
  delete peerConnections[targetUsername];
  activeConnectionsCount--;

  // 只有当所有连接都关闭时,才停止本地摄像头预览
  if (activeConnectionsCount === 0) {
    if (localVideo.srcObject) {
      localVideo.pause();
      localVideo.srcObject.getTracks().forEach(track => {
        track.stop();
      });
      webcamStream = null;
    }
    // 没有活跃连接时禁用挂断按钮
    document.getElementById("hangup-button").disabled = true;
  }
}

/* 处理来自指定用户的挂断消息 */
function handleHangUpMsg(msg) {
  const senderUsername = msg.name;
  log(`*** Received hang up notification from ${senderUsername}`);
  closeVideoCall(senderUsername);
}

/* 挂断与指定用户的通话 */
function hangUpCall(targetUsername) {
  if (!targetUsername || !peerConnections[targetUsername]) return;
  
  closeVideoCall(targetUsername);
  sendToServer({
    name: myUsername,
    target: targetUsername,
    type: "hang-up"
  });
  this.targetUsername = null;
}

配套调整说明

  • 建立连接时:不要把新创建的RTCPeerConnection赋值给单个变量,而是存入peerConnections[目标用户名],同时执行activeConnectionsCount++
  • 界面交互:挂断按钮需要明确针对当前选中的用户(比如点击某个用户的视频窗口后,挂断按钮仅对该用户生效),或者给每个用户的视频窗口单独添加挂断按钮

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:55:12