WebRTC永远不会触发onCandidate

时间:2014-12-15 17:42:15

标签: javascript webrtc

我开始使用WebRTC开发,但那件事从来没有给我ICE候选人。我设置了所有内容,我正在交换描述和内容,我还在那里缩小了一个超级丑陋的功能,以确保一切都正常运行,一个接一个。信号状态对两者都是稳定的, onError 永远不会被触发(如预期的那样),但onIceCandidate也是(不是预期的),当我想发送一个随机的空MediaStream对象pc1.addStream(new webkitMediaStream());时,它总是触发 onNegotiationNeeded

有没有人知道我的代码到底有什么问题?我花了几个小时浏览Stack Overflow,HTML5 Rocks和W3C文档,但我不明白。这是我的整个代码:

var config={
  'iceServers':[{
    'url':'stun:stun.l.google.com:19302'
  },{
    'url':'stun:stun1.l.google.com:19302'
  },{
    'url':'stun:stun2.l.google.com:19302'
  },{
    'url':'stun:stun3.l.google.com:19302'
  },{
    'url':'stun:stun4.l.google.com:19302'
  }]
};
var pc1=new webkitRTCPeerConnection(config);
var pc2=new webkitRTCPeerConnection(config);

var onError=function(error)
{
  console.error(error);
}

pc1.onicecandidate=function()
{
  console.log('PC1 onIceCandidate (finally) fired!');
}
pc2.onicecandidate=function()
{
  console.log('PC2 onIceCandidate (finally) fired!');
}

pc1.oniceconnectionstatechange=function()
{
  console.log('PC1 oniceconnectionstatechange fired!');
}
pc2.oniceconnectionstatechange=function()
{
  console.log('PC2 oniceconnectionstatechange fired!');
}
pc1.onnegotiationneeded=function()
{
  console.log('PC1 onnegotiationneeded fired!');
}
pc2.onnegotiationneeded=function()
{
  console.log('PC2 onnegotiationneeded fired!');
}

pc1.createOffer(function(offer){
  pc1.setLocalDescription(offer,function(){
    pc2.setRemoteDescription(new RTCSessionDescription(offer),function(){
      pc2.createAnswer(function(answer){
        pc2.setLocalDescription(answer,function(){
          pc1.setRemoteDescription(new RTCSessionDescription(answer),new Function()/*I don't need you, bro*/,onError);
        },onError);
      },onError);
    },onError);
  },onError);
},onError);

BTW我正在使用Google Chrome进行开发。我会确保它也在Firefox中运行,但是现在问题应该是跨浏览器。我想在之前使用数据通道...(但我没有反对使用Firefox或跨浏览器代码的工作解决方案)

4 个答案:

答案 0 :(得分:10)

在Chrome 38及更早版本中,OfferToReceiveAudio默认为true。从Chrome 39开始,OfferToReceiveAudio默认为false,正如WebRTC工程师在PSA: Behavior change to PeerConnection.createOffer constraint OfferToReceiveAudio所宣布的那样(引用如下)。 由于此更改,createOffer返回的SDP不包含任何媒体,因此ICE收集过程永远不会启动。您可以通过观察永远不会触发ICE事件,并且PeerConnection的iceGatheringStateiceConnectionState保持" new"来注意到此更改的后果。

要确保ICE收集的开始和完成,您必须在商品中添加媒体,例如通过在以下约束中为您的商品设置OfferToReceiveAudio:true(作为PeerConnection constructor的参数,或作为peerConnection.createOffer方法的参数):

{
    mandatory: {
        OfferToReceiveAudio: true
    }
}

(在SDP中获取媒体的其他方式包括设置OfferToReceiveVideo:true,或使用您从getUserMedia获得的媒体流调用peerConnection.addStream


webrtc-discuss:PSA: Behavior change to PeerConnection.createOffer constraint OfferToReceiveAudio

  

我将提交更改(https://webrtc-codereview.appspot.com/16309004/)以更改RTCPeerConnection.createOffer的行为。   预计此更改将包含在Chrome M39中。

     

发生了什么变化:

     

目前,如果未在PeerConnection.createOffer中指定OfferToReceiveAudio约束,则生成的商品SDP将具有" m = audio"即使没有连接到PeerConnection的音频轨道也行。换句话说,OfferToReceiveAudio默认为true。

     

我的更改后,OfferToReceiveAudio不再默认为true。提供SDP是否具有" m = audio" line取决于是否已将任何音轨附加到PeerConnection。

     

未更改的内容:

     

为OfferToReceiveAudio设置显式值的行为保持不变,即OfferToReceiveAudio:true将导致" m = audio"无论音轨是否存在,都行; OfferToReceiveAudio:false将导致no" m = audio"除非使用包含" m = audio"的SDP调用setLocalDescription,否则无论音轨是否存在都行。在这种情况下,新商品SDP会将音频内容标记为无效,而不是删除音频内容。

答案 1 :(得分:3)

2015年1月3日Rob W的v2 Samples解决方案最初为我工作但导致了另一个问题。
 我在{'offerToReceiveAudio':true,'offerToReceiveVideo':true}createOffer来电中加入createAnswer,并按照说明调用了onIceCandidate
但是,如果我做对了,offerToReceive...表示接收但不发送流。我认为这是因为sdp报价中的a=recvonly和sdp答案中的a=sendonly。因此,只有来电者可以看到被调查者的视频,反之亦然。反之亦然。

Rob正确地说:

  

在SDP中获取媒体的其他方法包括使用a调用peerConnection.addStream   您从getUserMedia获得的媒体流

添加流是我最初做过的事情。但是,我发送的sdp发生在添加之前,因为我的逻辑流程混乱了。把它带到正确的顺序(addStream -> sdp = getLocalDescription -> send(sdp))并删除offerOptions对我来说很有用 希望这对任何人都有帮助。

答案 2 :(得分:2)

2020年的解决方案

您必须做两件事:

  • 在创建offerToReceiveAudio时包括offerToReceiveVideoRTCPeerConnection
  • 添加addTrack

示例代码:

const peerConnection= new RTCPeerConnection({
  configuration: {
    offerToReceiveAudio: true,
    offerToReceiveVideo: true
  },
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
})

localStream.getTracks().forEach(track => {
  peerConnection.addTrack(track, localStream)
})

const offer = await peerConnection.createOffer()
await peerConnection.setLocalDescription(offer)

peerConnection.onicecandidate = event => {
  if (event.candidate) {
    console.log('Ice candidate: ', event.candidate)

  }
}

... other codes

答案 3 :(得分:0)

我找到了解决方案。如果在配置声明后添加此代码:

var mediaConstraints = {
  optional: [],
  mandatory: {
    OfferToReceiveAudio: true,
    OfferToReceiveVideo: true
  }
};

并像这样修改最后一行

},onError,mediaConstraints);

它只是有效。不要问我为什么。