首页 > 解决方案 > “无法 RTCPeerConnection::setRemoteDescription:无法设置远程应答 sdp:在错误状态下调用:kStable”

问题描述

我正在使用 flutter_webrtc 连接到点对点的用户。我在报价方面收到此错误。我一直在互联网上寻找解决方案,但找不到解决方案。

class Webrtc {
      bool _offer = false;
      RTCPeerConnection _peerConnection;
      MediaStream _localStream;
      RTCVideoRenderer _localRenderer = new RTCVideoRenderer();
          RTCVideoRenderer _remoteRenderer = new RTCVideoRenderer();
        
          get localRe

nderer => _localRenderer;
      get remoteRenderer => _remoteRenderer;

  //final sdpController = TextEditingController();

  Webrtc() {
    initRenderers();
    _createPeerConnection().then((pc) {
      _peerConnection = pc;
    });
  }

  initRenderers() async {
    await _localRenderer.initialize();
    await _remoteRenderer.initialize();
  }

  createOffer() async {
    _offer = true;
    RTCSessionDescription description =
        await _peerConnection.createOffer({'offerToReceiveVideo': 1});
    // var session = parse(description.sdp);
    // print(json.encode(session));
    // _offer = true;
    var roomDef = Firestore.instance.collection("rooms").document("test");

    var data = {
      "offer": {
        'sdp': description.sdp.toString(),
        'type': description.type.toString(),
      }
    };
    await roomDef.setData(data, merge: true);
    await _peerConnection.setLocalDescription(description);
    Firestore.instance.collection("rooms").document("test").snapshots().listen((event) {
      if(event.data["answer"] != null){
        _setRemoteDescription(event.data["answer"]);
      }
    });
  }

  createAnswer() async {
    //  Firestore.instance.collection("rooms").document("test").snapshots().listen((event) {
    //   if(event.data["offer"] != null){
    //     _setRemoteDescription(event.data["offer"]);
    //   }
    // });
    var doc = await Firestore.instance.collection("rooms").document("test").get();
    print(doc.data["offer"]);
    await _setRemoteDescription(doc.data["offer"]);
    RTCSessionDescription description =
        await _peerConnection.createAnswer({'offerToReceiveVideo': 1});
    
    //var session = parse(description.sdp);
    //print(json.encode(session));
 

    await _peerConnection.setLocalDescription(description);

       var data = {
      "answer": {
        'sdp': description.sdp.toString(),
        'type': description.type.toString(),
      }
    };
    Firestore.instance
        .collection("rooms")
        .document("test")
        .setData(data, merge: true);
  }

   _setRemoteDescription(doc) async {
    // String jsonString = doc.toString();
    // dynamic session = await jsonDecode('$jsonString');
    //String sdp = write(session, null);

    // RTCSessionDescription description =
    //     new RTCSessionDescription(session['sdp'], session['type']);
    RTCSessionDescription description =
        new RTCSessionDescription(doc["sdp"],doc["type"]);
    print(description.toMap());

    await _peerConnection.setRemoteDescription(description);
  }

  void _addCandidate(data) async {
    dynamic session = data;
    dynamic candidate = new RTCIceCandidate(
        session['candidate'], session['sdpMid'], session['sdpMlineIndex']);
    await _peerConnection.addCandidate(candidate);
  }

  _createPeerConnection() async {
    Map<String, dynamic> configuration = {
      "iceServers": [
        {"url": "stun:stun.l.google.com:19302"},
      ]
    };

    final Map<String, dynamic> offerSdpConstraints = {
      "mandatory": {
        "OfferToReceiveAudio": true,
        "OfferToReceiveVideo": true,
      },
      "optional": [],
    };

    _localStream = await _getUserMedia();

    RTCPeerConnection pc =
        await createPeerConnection(configuration, offerSdpConstraints);
    // if (pc != null) print(pc);
    pc.addStream(_localStream);

    pc.onIceCandidate = (e) {
      if (_offer && e.candidate != null) {
        Firestore.instance.collection("caller").add({
          'candidate': e.candidate.toString(),
          'sdpMid': e.sdpMid.toString(),
          'sdpMlineIndex': e.sdpMlineIndex,
        });

        Firestore.instance.collection("callee").snapshots().listen((event) {
          event.documentChanges.forEach((element) {
            print(element.document.data);
            _addCandidate(element.document.data);
          });
        });
      }
      if (!_offer && e.candidate != null) {
        Firestore.instance.collection("callee").add({
          'candidate': e.candidate.toString(),
          'sdpMid': e.sdpMid.toString(),
          'sdpMlineIndex': e.sdpMlineIndex,
        });
        Firestore.instance.collection("caller").snapshots().listen((event) {
          event.documentChanges.forEach((element) {
            print(element.document.data);
            _addCandidate(element.document.data);
          });
        });
      }
      // if (e.candidate != null) {
      //   print(json.encode({
      //     'candidate': e.candidate.toString(),
      //     'sdpMid': e.sdpMid.toString(),
      //     'sdpMlineIndex': e.sdpMlineIndex,
      //   }));
      // }
    };

    pc.onIceConnectionState = (e) {
      print(e);
    };

    pc.onAddStream = (stream) {
      print('addStream: ' + stream.id);
      _remoteRenderer.srcObject = stream;
    };

    return pc;
  }

  _getUserMedia() async {
    final Map<String, dynamic> mediaConstraints = {
      'audio': true,
      'video': {
        'facingMode': 'user',
      },
    };

    MediaStream stream = await navigator.getUserMedia(mediaConstraints);

    // _localStream = stream;
    _localRenderer.srcObject = stream;
    _localRenderer.mirror = true;

    // _peerConnection.addStream(stream);

    return stream;
  }
}

我尝试切换 setlocaldescption 和 setremotedescption 但没有用。报价按钮调用从 ui 和应答按钮调用 createanswer 函数创建报价。

标签: flutterwebrtc

解决方案


我还不能在你的帖子下发表评论,但我对最新版本的 flutter_webrtc 有这个问题。三天后挠头,我使用了:

  flutter_webrtc: ^0.2.7

在第一次尝试中工作。干杯。


推荐阅读