WebRTC永远不会触发onCandidate

Dee*_*w97 3 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);
Run Code Online (Sandbox Code Playgroud)

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

Rob*_*b W 10

在Chrome 38及更早版本中,OfferToReceiveAudio默认为true.从Chrome 39开始,OfferToReceiveAudio默认为false,正如PSA的WebRTC工程师所宣布的:行为更改为PeerConnection.createOffer约束OfferToReceiveAudio(引用如下).
由于此更改,返回的SDP createOffer不包含任何媒体,因此ICE收集过程永远不会启动.你可以通过观察永远不会触发ICE事件和PeerConnection iceGatheringStateiceConnectionState保持"新" 来注意这种变化的后果.

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

{
    mandatory: {
        OfferToReceiveAudio: true
    }
}
Run Code Online (Sandbox Code Playgroud)

(在SDP中获取媒体的其他方式包括设置OfferToReceiveVideo:truepeerConnection.addStream使用您获得的媒体流进行呼叫getUserMedia)


webrtc-discuss:PSA:行为更改为PeerConnection.createOffer约束OfferToReceiveAudio:

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

改变了什么:

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

更改后,OfferToReceiveAudio不再默认为true.提议SDP是否具有"m =音频"线取决于是否已将任何音轨附加到PeerConnection.

什么没有改变:

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

  • 请注意,这个答案已[过时](http://stackoverflow.com/a/30982333/918910)。正确的语法是“{offerToReceiveAudio: true}”(无“强制”,且小写“o”)。 (2认同)

Dan*_*anD 6

Rob W 于2015 年1 月 3 日的上述解决方案起初对我有用,但导致了另一个问题。
我包括{'offerToReceiveAudio':true,'offerToReceiveVideo':true}createOffercreateAnswer调用中,onIceCandidate并按照描述被调用。
但是,如果我猜对了,则offerToReceive...意味着接收而不发送流。我想通了,因为a=recvonly在 sdp 报价和a=sendonlysdp 答案中。结果,只有呼叫者可以看到被呼叫者的视频,反之亦然。

正如 Rob 正确指出的那样:

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

添加流是我首先已经完成的。但是,我的 sdp 发送发生在添加之前,因为我的逻辑流程混淆了。将其放入正确的顺序 ( addStream -> sdp = getLocalDescription -> send(sdp)) 并删除 offerOptions 对我来说很有效。
希望这可以帮助任何人。


Duc*_*Mai 5

2020年解决方案

你必须做两件事:

  • 包括offerToReceiveAudioofferToReceiveVideo在创建时RTCPeerConnection
  • 添加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
Run Code Online (Sandbox Code Playgroud)