首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >[InvalidStateError:"setRemoteDescription需要先调用addIceCandidate“代码: 11

[InvalidStateError:"setRemoteDescription需要先调用addIceCandidate“代码: 11
EN

Stack Overflow用户
提问于 2017-08-08 22:58:47
回答 3查看 1.6K关注 0票数 2

我使用web Rtc和websockets创建了一个简单的视频通话应用程序。但是当我运行代码时,出现了以下错误。

DOMException [InvalidStateError:"setRemoteDescription需要在addIceCandidate之前调用“代码: 11

我不知道如何解决这个错误。下面是我的代码:

代码语言:javascript
运行
复制
enter code here

var localVideo;
var remoteVideo;
var peerConnection;
var uuid;
var localStream;
var peerConnectionConfig = {
'iceServers': [
    {'urls': 'stun:stun.services.mozilla.com'},
    {'urls': 'stun:stun.l.google.com:19302'},
]
};

function pageReady() {
    uuid = uuid();
    console.log('Inside Page Ready');
    localVideo = document.getElementById('localVideo');
    remoteVideo = document.getElementById('remoteVideo');

   serverConnection = new WebSocket('wss://' + window.location.hostname + 
   ':8443');
   serverConnection.onmessage = gotMessageFromServer;

   var constraints = {
       video: true,
       audio: true,
   };

   if(navigator.mediaDevices.getUserMedia) {

   navigator.mediaDevices.getUserMedia(constraints)
   .then(getUserMediaSuccess).catch(errorHandler);
   }else
   {
       alert('Your browser does not support getUserMedia API');
   }
   }

   function getUserMediaSuccess(stream) {
        localStream = stream;
        localVideo.src = window.URL.createObjectURL(stream); 
   }

   function start(isCaller) {
       console.log('Inside isCaller');
       peerConnection = new RTCPeerConnection(peerConnectionConfig);
       peerConnection.onicecandidate = gotIceCandidate;
       peerConnection.onaddstream = gotRemoteStream;
       peerConnection.addStream(localStream);

       if(isCaller) {
            console.log('Inside Caller to create offer');
            peerConnection.createOffer().
            then(createdDescription).catch(errorHandler);
       }
      }

   function gotMessageFromServer(message) {
   console.log('Message from Server');
   if(!peerConnection) 
   {
        console.log('Inside !Peer Conn');
        start(false);
   }

   var signal = JSON.parse(message.data);

   // Ignore messages from ourself
   if(signal.uuid == uuid) return;

   if(signal.sdp) {
        console.log('Inside SDP');
        peerConnection.setRemoteDescription(new 
        RTCSessionDescription(signal.sdp)).then(function() {
        // Only create answers in response to offers
        if(signal.sdp.type == 'offer') {
            console.log('Before Create Answer');
            peerConnection.createAnswer().then(createdDescription)
            .catch(errorHandler);
        }
     }).catch(errorHandler);
     } else if(signal.ice) {
           console.log('Inside Signal Ice');
           peerConnection.addIceCandidate(new 
           RTCIceCandidate(signal.ice)).catch(errorHandler);
     }

    }

    function gotIceCandidate(event) {
         console.log('Inside Got Ice Candi');
         if(event.candidate != null) {
         serverConnection.send(JSON.stringify({'ice': event.candidate, 
         'uuid': uuid}));
    }
  }

  function createdDescription(description) {
  console.log('got description');

    peerConnection.setLocalDescription(description).then(function() {
    console.log('Inside Setting ');
    serverConnection.send(JSON.stringify({'sdp': 
    peerConnection.localDescription, 'uuid': uuid}));
   }).catch(errorHandler);
  }

  function gotRemoteStream(event) {
  console.log('got remote stream');
  remoteVideo.src = window.URL.createObjectURL(event.stream);
  }

  function errorHandler(error) {
     console.log(error);
  }

  // Taken from http://stackoverflow.com/a/105074/515584
  // Strictly speaking, it's not a real UUID, but it gets the job done here
  function uuid() {
      function s4() {
      return Math.floor((1 + Math.random()) * 
      0x10000).toString(16).substring(1);
      }

  return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + 
  s4() + s4();
  }

这是我的代码,我不知道如何安排addIceCandidate和addRemoteDescription函数。

EN

回答 3

Stack Overflow用户

发布于 2018-06-01 16:48:55

您需要确保在设置description之后调用peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice))。您可能会遇到这样的情况:在peerConnection完成设置说明之前,您收到ice候选对象并尝试将其添加到peerConnection中。

我也遇到过类似的情况,我创建了一个数组来存储在设置description之前到达的候选对象,并创建了一个变量来检查是否设置了description。如果设置了description,我会将候选对象添加到peerConnection,否则会将它们添加到数组中。(当您将变量设置为true时,还可以遍历数组并将所有存储的候选对象添加到peerConnection。

票数 1
EN

Stack Overflow用户

发布于 2018-06-01 16:14:28

WebRTC的工作方式(据我所知)是,你必须让两个对等体就如何彼此交流达成协议,顺序是向你的对等体发出要约,让你的对等体回答,然后选择一个ICE候选进行交流,然后如果你想发送媒体流进行视频对话

为了让你有一个很好的例子来看看如何实现这些功能,以及你可以按照什么顺序访问https://github.com/alexan1/SignalRTC,他对如何做到这一点有很好的理解。

你现在可能已经有了问题的解决方案,但我会在你没有的情况下回复你。

票数 0
EN

Stack Overflow用户

发布于 2020-06-11 23:14:19

:据我所知,这个解决方案是一种反模式,您不应该以这种方式实现它。更多关于我如何在保持合理流程的情况下解决这个问题的信息,请关注这个回答和评论部分:https://stackoverflow.com/a/57257449/779483

TLDR:不是在信令信息到达时立即调用addIceCandidate,而是将候选对象添加到队列中。在调用setRemoteDescription之后,遍历候选人队列,并对每个候选人调用addIceCandidate

--

this answer中我了解到,在添加冰候选数据之前,我们必须调用setRemoteDescription(offer)

因此,在@Luxior答案的基础上展开,我做了以下工作:

当带有候选的信令消息到达时远程检查:远程检查是否设置了远程(通过布尔标志,例如:remoteIsReady)

  • If it if,调用addIceCandidate

  • If it‘t, to aa queue

调用setRemoteDescription后的

  • (在应答信号或应答客户端操作中):setRemoteDescription
  • 调用一个方法来遍历候选队列并对每个候选队列调用addIceCandidate
  • 将布尔标志(remoteIsReady)设置为true
  • 空queue

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45571768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档