繁体   English   中英

WebRTC 从不触发 IceCandidate

[英]WebRTC never fires onIceCandidate

我从 WebRTC 开始开发,但那个东西从来没有给我 ICE 候选人。 我设置了所有内容,我正在交换描述和内容,我还制作了一个超级丑陋的 function 以确保一切正常运行,一个接一个。 信号 state 对于两者都是稳定的,永远不会触发onError (如预期的那样),但 onIceCandidate 也会(如预期的那样),当我想发送随机的空 MediaStream object 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);

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

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

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

{
    mandatory: {
        OfferToReceiveAudio: true
    }
}

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


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=audio”线取决于是否有任何音轨附加到 PeerConnection。

什么没有改变:

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

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

正如 Rob 正确指出的那样:

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

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

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

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

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

并像这样修改最后一行

},onError,mediaConstraints);

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

文档页面应用作参考: https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer

const offerOptions = {
    offerToReceiveAudio: true,
    offerToReceiveVideo: true
}

myPeerConnection.createOffer ( offerOptions )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM