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

Flutter WebRTC视频通话黑屏问题排查与解决求助

排查Flutter WebRTC视频通话黑屏问题

一、本地媒体流初始化检查

  • 确认摄像头权限配置到位:Web端要在web/index.html里加权限声明,移动端要在AndroidManifest.xml(Android)或Info.plist(iOS)配置摄像头、麦克风权限。代码里必须确保getUserMedia调用成功,示例:
    final mediaConstraints = {'audio': true, 'video': {'facingMode': 'user'}};
    try {
      _localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
      // 绑定本地Renderer前必须先初始化
      await _localRenderer.initialize();
      _localRenderer.srcObject = _localStream;
    } catch (e) {
      print('获取媒体流失败: $e');
    }
    
  • 本地RTCVideoRenderer必须先调用initialize()再设置srcObject,且组件已经挂载到页面。

二、信令消息传递完整性

  • SDP Offer/Answer要完整转发:信令服务器必须把SDP的type和sdp字段完整传给对方,不能截断。比如Signalling类发送SDP的代码要确保字段齐全:
    void sendSdp(RTCSessionDescription sessionDescription) {
      final data = {
        'type': 'sdp',
        'sdp': sessionDescription.sdp,
        'sdpType': sessionDescription.type.toString(),
        'from': _userId,
        'to': _targetUserId
      };
      _socket.send(jsonEncode(data));
    }
    
  • ICE Candidate不能丢:每个生成的ICE Candidate都要及时发对方,接收方要正确添加到PeerConnection:
    发送端:
    void onIceCandidate(RTCIceCandidate candidate) {
      sendIceCandidate(candidate);
      _peerConnection.addCandidate(candidate);
    }
    
    接收端:
    if (message['type'] == 'ice') {
      final candidate = RTCIceCandidate(
        message['candidate'],
        message['sdpMid'],
        message['sdpMLineIndex'],
      );
      await _peerConnection.addCandidate(candidate);
    }
    

三、PeerConnection配置与状态检查

  • 配置有效的ICE服务器:至少加一个STUN服务器,比如stun:stun.l.google.com:19302,内网测试可能需要TURN服务器。示例:
    final configuration = {
      'iceServers': [
        {'urls': 'stun:stun.l.google.com:19302'},
      ]
    };
    _peerConnection = await createPeerConnection(configuration);
    
  • 正确处理onTrack事件:远端流必须通过这个事件获取,不能用信令直接传流对象。示例:
    _peerConnection.onTrack.listen((event) {
      if (event.streams.isNotEmpty) {
        final remoteStream = event.streams[0];
        await _remoteRenderer.initialize();
        _remoteRenderer.srcObject = remoteStream;
      }
    });
    
  • 本地流必须添加到PeerConnection:调用addStream或addTrack把本地流加入连接,否则对方收不到你的流:
    await _peerConnection.addStream(_localStream);
    

四、渲染组件问题

  • 确认RTCVideoView绑定正确的Renderer:组件的renderer属性要指向已经初始化、且设置了srcObject的RTCVideoRenderer实例:
    RTCVideoView(_localRenderer, mirror: true),
    RTCVideoView(_remoteRenderer),
    
  • 移动端要确认用户已授予权限:如果用户没同意摄像头/麦克风权限,getUserMedia会静默失败,自然没有流。

五、调试技巧

  • 加日志打印:在媒体流获取、信令收发、PeerConnection状态变化(比如onConnectionStateChange、onIceGatheringStateChange)处打日志,确认每个步骤是否正常执行。
  • Web端用Chrome调试:打开chrome://webrtc-internals/查看WebRTC的详细状态,包括ICE连接情况、流的传输统计,快速定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:22:50