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