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

flutter_webrtc客户端无法重新加入已离开频道的问题排查

问题修复:Flutter WebRTC客户端重新加入频道黑屏问题

问题根源

  1. 客户端退出时未清理PeerConnection、Firestore监听、媒体流等资源,导致重新加入时旧资源冲突
  2. 服务端信令监听逻辑因已存在RemoteDescription,跳过新客户端的Answer处理
  3. 客户端重新加入时未重置媒体流和渲染器绑定关系

具体修复方案

1. 客户端添加退出清理逻辑

在客户端StateNotifier中新增退出函数,彻底释放资源:

Future<void> leaveStream() async {
  await Wakelock.disable();
  
  // 关闭PeerConnection
  await peerConnection?.close();
  peerConnection = null;
  
  // 停止并释放远程流
  remoteStream?.getTracks().forEach((track) => track.stop());
  remoteStream = null;
  
  // 重置渲染器
  if (remoteVideo != null) {
    await remoteVideo?.dispose();
    remoteVideo = null;
  }
  
  state = ProcessState.notInitialized;
}

2. 修复服务端RemoteDescription监听逻辑

修改服务端_createRoom中的快照监听,移除旧的判断条件,确保新客户端的Answer能被处理:

roomRef.snapshots().listen((snapshot) async {
  final data = snapshot.data();
  if (data != null && data['answer'] != null) {
    final answer = data['answer'] as Map<String, dynamic>;
    final description = RTCSessionDescription(
      answer['sdp'] as String?,
      answer['type'] as String?,
    );
    
    final currentRemoteDesc = peerConnection?.getRemoteDescription();
    // 仅当新Answer与当前RemoteDescription不同时更新
    if (currentRemoteDesc == null || 
        currentRemoteDesc.sdp != description.sdp) {
      await peerConnection?.setRemoteDescription(description);
    }
  }
});

3. 客户端重新加入前先清理旧资源

在客户端startStream开头调用清理函数,避免资源冲突:

Future<bool> startStream(String? roomId, RTCVideoRenderer remoteVideo) async {
  if (roomId == null || roomId.isEmpty) {
    return false;
  }

  // 先清理旧资源
  await leaveStream();

  state = ProcessState.loading;
  final result = await _joinRoom(roomId, remoteVideo);

  if (result) {
    state = ProcessState.working;
    await Wakelock.enable();
  } else {
    state = ProcessState.notInitialized;
  }

  return result;
}

4. 客户端直接绑定流到渲染器

修改客户端_joinRoom中的onTrack回调,直接将流设置到渲染器,避免间接赋值导致的延迟或失效:

peerConnection?.onTrack = (RTCTrackEvent event) {
  final stream = event.streams[0];
  remoteVideo.srcObject = stream;
  remoteStream = stream;
};

5. 可选:清理Firestore中的旧Answer数据

客户端退出时删除房间中的Answer字段,确保后续新客户端能正常发起连接:

// 在leaveStream中添加
if (roomId != null) {
  final roomRef = FirebaseFirestore.instance.collection('rooms').doc(roomId);
  await roomRef.update({'answer': FieldValue.delete()});
}

内容的提问来源于stack exchange,提问作者Kasymbek R. Tashbaev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 04:50:24