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

Flutter+Firebase+WebRTC视频通话:主叫方无法查看被叫方视频

Flutter WebRTC 视频通话:发起方无法看到接收方视频的排查与修复

以下是针对你遇到的「用户A发起通话后能听到B的音频,但看不到B的视频,B能正常看到A」问题的常见排查点和修复方案:

1. 接收方(B)未将本地视频轨道添加到PeerConnection

这是最常见的原因:B端成功获取本地摄像头流,但未将视频轨道注入到WebRTC的PeerConnection中,导致A端无法收到B的视频媒体数据。

  • 排查:检查B端代码,确认在获取localStream后,是否调用了peerConnection.addStream(localStream) 或 peerConnection.addTrack(videoTrack, localStream)。
  • 修复:在B端初始化本地媒体流后,立即执行轨道添加操作,且要在创建Answer SDP之前完成:
    // 获取本地媒体流后
    final localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
    // 添加所有轨道到PeerConnection
    for (final track in localStream.getTracks()) {
      await peerConnection.addTrack(track, localStream);
    }
    // 再创建Answer
    final answer = await peerConnection.createAnswer();
    await peerConnection.setLocalDescription(answer);
    

2. SDP交换时未启用视频接收/发送

如果SDP中缺失视频媒体描述,A端无法识别B的视频轨道。

  • 排查:检查两端创建Offer/Answer时的约束,是否设置了offerToReceiveVideo: true;同时确认媒体约束中包含视频请求。
  • 修复:
    1. 统一两端的媒体约束:
      final mediaConstraints = {
        'audio': true,
        'video': {
          'facingMode': 'user', // 前置摄像头
          'width': 640,
          'height': 480
        }
      };
      
    2. 创建Offer/Answer时明确启用视频接收:
      // A端创建Offer
      final offer = await peerConnection.createOffer({
        'offerToReceiveAudio': true,
        'offerToReceiveVideo': true,
      });
      await peerConnection.setLocalDescription(offer);
      
      // B端创建Answer(也建议显式设置)
      final answer = await peerConnection.createAnswer({
        'offerToReceiveAudio': true,
        'offerToReceiveVideo': true,
      });
      await peerConnection.setLocalDescription(answer);
      

3. 发起方(A)未正确处理远程视频轨道

A端可能未监听WebRTC的轨道回调,导致收到B的视频轨道后无法挂载到渲染组件。

  • 排查:检查A端是否设置了onTrack或onAddStream回调,且正确处理了视频轨道。
  • 修复:
    使用WebRTC推荐的onTrack回调处理远程轨道:
    peerConnection.onTrack = (RTCTrackEvent event) {
      // 区分视频和音频轨道
      if (event.track.kind == 'video') {
        // 将远程流绑定到视频渲染器
        remoteVideoRenderer.srcObject = event.streams.first;
      }
    };
    
    若使用旧版API,同时保留onAddStream兼容:
    peerConnection.onAddStream = (MediaStream stream) {
      remoteVideoRenderer.srcObject = stream;
    };
    

4. 接收方(B)摄像头权限异常

虽然音频正常,但B端可能未获取到摄像头权限,导致无法生成视频轨道。

  • 排查:检查设备权限设置,确认B端APP已获得摄像头访问权限;同时检查代码中是否主动请求了权限。
  • 修复:
    1. 配置平台权限:
      • Android(android/app/src/main/AndroidManifest.xml):
        <uses-permission android:name="android.permission.CAMERA" />
        <uses-feature android:name="android.hardware.camera" />
        
      • iOS(ios/Runner/Info.plist):
        <key>NSCameraUsageDescription</key>
        <string>需要访问摄像头进行视频通话</string>
        
    2. 代码中主动请求权限(需依赖permission_handler插件):
      import 'package:permission_handler/permission_handler.dart';
      
      // 获取媒体流前先请求权限
      final cameraStatus = await Permission.camera.request();
      final micStatus = await Permission.microphone.request();
      if (cameraStatus != PermissionStatus.granted || micStatus != PermissionStatus.granted) {
        // 提示用户开启权限
        return;
      }
      // 再获取本地媒体流
      final localStream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
      

5. 信令通道(Firebase)丢失视频相关数据

Firebase传递SDP或ICE Candidate时,可能因异步逻辑或数据格式问题,导致A端未收到完整的视频媒体信息。

  • 排查:在信令发送/接收处添加日志,确认B的Answer SDP中包含m=video条目,且所有ICE Candidate都已传递到A端。
  • 修复:
    • 确保SDP以字符串形式完整传递,避免JSON序列化/反序列化时丢失字段;
    • ICE Candidate要实时发送,不要批量延迟传递,确保A端能及时添加所有Candidate:
      // B端监听ICE Candidate生成事件,实时发送到Firebase
      peerConnection.onIceCandidate = (RTCIceCandidate candidate) {
        // 通过Firebase发送candidate到A端
        firebaseFirestore.collection('calls').doc(callId).update({
          'candidates': FieldValue.arrayUnion([candidate.toMap()])
        });
      };
      
      // A端监听Firebase的candidates更新,及时添加到PeerConnection
      firebaseFirestore.collection('calls').doc(callId).snapshots().listen((snapshot) {
        final candidates = snapshot.data()?['candidates'] ?? [];
        for (final candidateMap in candidates) {
          final candidate = RTCIceCandidate.fromMap(candidateMap);
          peerConnection.addCandidate(candidate);
        }
      });
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 06:17:00