[英]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 的iceGatheringState
和iceConnectionState
保持“新”来注意到此更改的后果。
为了确保 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 日的上述解决方案起初对我有用,但导致了另一个问题。
我在createOffer
和createAnswer
调用中包含了{'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年解决方案
你必须做两件事:
offerToReceiveAudio
和offerToReceiveVideo
创建时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.