Flutter &引用;无法RTPeerConnection::setRemoteDescription:无法设置远程应答sdp:在错误状态下调用:kStable“;

Flutter &引用;无法RTPeerConnection::setRemoteDescription:无法设置远程应答sdp:在错误状态下调用:kStable“;,flutter,webrtc,Flutter,Webrtc,我正在使用Flatter_webrtc连接到用户点对点。我在报价方面遇到了这个错误。我一直在互联网上寻找解决方案,但找不到解决方案 class Webrtc { bool _offer = false; RTCPeerConnection _peerConnection; MediaStream _localStream; RTCVideoRenderer _localRenderer = new RTCVideoRenderer();

我正在使用Flatter_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;
  }
}
类Webrtc{
bool_offer=false;
RTPEERCONNECTION\u peerConnection;
MediaStream localStream;
RTCDeorenderer_localRenderer=新的RTCDeorenderer();
RTCDeorenderer_remoteRenderer=新的RTCDeorenderer();
获取本地资源
NDER=>\u本地渲染器;
获取remoteRenderer=>\u remoteRenderer;
//最终sdpController=TextEditingController();
Webrtc(){
initrenders();
_createPeerConnection()。然后((pc){
_peerConnection=pc;
});
}
initrenders()异步{
等待_localRenderer.initialize();
等待_remoteRenderer.initialize();
}
createOffer()异步{
_报价=真实;
RTCSessionDescription描述=
wait _peerConnection.createOffer({'offerToReceiveVideo':1});
//var session=parse(description.sdp);
//打印(json.encode(会话));
//_offer=true;
var roomDef=Firestore.instance.collection(“房间”).document(“测试”);
风险值数据={
“要约”:{
“sdp”:description.sdp.toString(),
“类型”:description.type.toString(),
}
};
等待roomDef.setData(数据,合并:true);
wait_peerConnection.setLocalDescription(描述);
Firestore.instance.collection(“rooms”).document(“test”).snapshots().listen((事件){
if(event.data[“answer”]!=null){
_setRemoteDescription(事件数据[“应答]);
}
});
}
createAnswer()异步{
//Firestore.instance.collection(“rooms”).document(“test”).snapshots().listen((事件){
//if(event.data[“offer”]!=null){
//_setRemoteDescription(事件数据[“要约]);
//   }
// });
var doc=await Firestore.instance.collection(“rooms”).document(“test”).get();
打印(文档数据[“报价”]);
等待_setRemoteDescription(文档数据[“报价]);
RTCSessionDescription描述=
wait _peerConnection.createAnswer({'offerToReceiveVideo':1});
//var session=parse(description.sdp);
//打印(json.encode(会话));
wait_peerConnection.setLocalDescription(描述);
风险值数据={
“答复”:{
“sdp”:description.sdp.toString(),
“类型”:description.type.toString(),
}
};
Firestore.instance
.收集(“房间”)
.文件(“测试”)
.setData(数据,合并:true);
}
_setRemoteDescription(doc)异步{
//字符串jsonString=doc.toString();
//动态会话=等待jsonDecode(“$jsonString”);
//字符串sdp=write(会话,null);
//RTCSessionDescription描述=
//新的RTCSessionDescription(会话['sdp'],会话['type']);
RTCSessionDescription描述=
新的RTCSessionDescription(文档[“sdp”]、文档[“类型”]);
打印(description.toMap());
wait_peerConnection.setRemoteDescription(描述);
}
void\u addCandidate(数据)异步{
动态会话=数据;
动态候选对象=新的候选对象(
会话['candidate',会话['sdpMid',会话['sdpMlineIndex']);
等待对等连接。添加候选(候选);
}
_createPeerConnection()异步{
映射配置={
“ICEServer”:[
{“url”:“stun:stun.l.google.com:19302”},
]
};
最终映射offerSdpConstraints={
“强制性”:{
“OfferToReceiveAudio”:正确,
“OfferToReceiveVideo”:正确,
},
“可选”:[],
};
_localStream=await_getUserMedia();
RTPEERCONNECTION pc=
等待createPeerConnection(配置、offerSdpConstraints);
//如果(pc!=null)打印(pc);
pc.addStream(_localStream);
pc.onIceCandidate=(e){
如果(_offer&&e.candidate!=null){
Firestore.instance.collection(“调用者”).add({
'candidate':e.candidate.toString(),
“sdpMid”:e.sdpMid.toString(),
“sdpMlineIndex”:例如sdpMlineIndex,
});
Firestore.instance.collection(“被调用方”).snapshots().listen((事件){
event.documentChanges.forEach((元素){
打印(元素、文档、数据);
_addCandidate(元素、文档、数据);
});
});
}
如果(!\u报价和e.candidate!=null){
Firestore.instance.collection(“被调用方”).add({
'candidate':e.candidate.toString(),
“sdpMid”:e.sdpMid.toString(),
“sdpMlineIndex”:例如sdpMlineIndex,
});
Firestore.instance.collection(“调用方”).snapshots().listen((事件){
event.documentChanges.forEach((元素){
打印(元素、文档、数据);
_addCandidate(元素、文档、数据);
});
});
}
//如果(例如,候选者!=null){
//打印(json.encode)({
//'candidate':e.candidate.toString(),
//“sdpMid”:e.sdpMid.toString(),
//“sdpMlineIndex”:例如sdpMlineIndex,
//   }));
// }
};
pc.onIceConnectionState=(e){
印刷品(e);
};
pc.onAddStream=(流){
打印('addStream:'+stream.id);
_remoteRenderer.srcObject=流;
};
返回pc;
}
_getUserMedia()异步{
最终映射媒体约束={
“音频”:正确,
“视频”:{
“facingMode”:“用户”,
},
};
MediaStream=await navigator.getUserMedia(mediaConstraints);
//_localStream=流;
_localRenderer.srcObject=stream;
_localRenderer.mirror=true;
//_peerConnection.addStream(流);
回流;
}
}

我尝试切换SetLocalDesction和SetRemoteDesction,但没有用。提供按钮调用从ui创建提供和应答按钮调用创建应答功能。

我还不能在你的帖子下发表评论,但我遇到了这个问题
  flutter_webrtc: ^0.2.7