Justin Uberti发布了对StackOverflow问题的回复,该问题涉及WebRTC连接如何工作:
why doesn't "onicecandidate" work?
现在我花了一周的时间来设置一个转弯服务器,当谈到设置连接时,它们会告诉你将对象作为由JSON.stringify构成的字符串发送(描述) )
现在,对于我的生活,我不能在他的JS示例中使用它,我在这里已经改变了:
var pc1, pc2, offer, answer, offer_str, offer_prsd, answer_str, answer_prsd;
pc1 = new webkitRTCPeerConnection(getServerOptionsFromUsername("mr_boombosstik"));
pc2 = new webkitRTCPeerConnection(getServerOptionsFromUsername("countdracula"));
pc1.onicecandidate = function(candidate) {
pc2.addIceCandidate(candidate);
};
pc2.onicecandidate = function(candidate) {
pc1.addIceCandidate(candidate);
};
//PC1 KICKS OFF THE PROCESS WITH AN OFFER!!
pc1.createOffer(onOfferCreated, onError);
function onError(err) {
window.alert(err.message);
}
function onOfferCreated(description) {
offer = description;
//HERE IS THE OFFER CREATED!!!
pc1.setLocalDescription(offer, onPc1LocalDescriptionSet, onError);
offer_str = JSON.stringify(offer);
//WE SET IT AS "OUR LOCAL DESCRIPTIION
}
function onPc1LocalDescriptionSet() {
offer_prsd = JSON.parse(offer_str);
console.log(offer_prsd.sdp);
// after this function returns, pc1 will start firing icecandidate events
pc2.setRemoteDescription(offer_prsd, onPc2RemoteDescriptionSet, onError);
}
function onPc2RemoteDescriptionSet() {
pc2.createAnswer(onAnswerCreated, onError);
}
function onAnswerCreated(description) {
answer = description;
pc2.setLocalDescription(answer, onPc2LocalDescriptionSet, onError);
}
function onPc2LocalDescriptionSet() {
// after this function returns, you'll start getting icecandidate events on pc2
pc1.setRemoteDescription(answer, onPc1RemoteDescriptionSet, onError);
}
function onPc1RemoteDescriptionSet() {
window.alert('Yay, we finished signaling offers and answers');
}
所以有人能告诉我为什么这不起作用?如果我无法在本地设置会话描述,我将如何通过某种信令服务完成它?
答案 0 :(得分:2)
我在谷歌搜索这个确切的问题时发现了这个问题。我99%肯定这里的原因是JSON字符串化/解析描述。
这里有证据。在http://simpl.info/rtcpeerconnection/
处获取简单的RTCPeerConnection示例在main.js中,在第87行之前插入此行:
description = JSON.parse(JSON.stringify(description));
[因此,它会在函数remotePeerConnection.setRemoteDescription(description);
中的gotLocalDescription(description)
行之前插入。]
这将导致以下错误:
Uncaught TypeMismatchError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': The 1st argument provided is either null, or an invalid RTCSessionDescription object.
显然,Javascript的字符串/ JSON处理非常糟糕,无法在将描述对象转换为JSON和从JSON转换时更改描述对象。我花了很多时间认为问题出在我的信号代码上,但是这个JSON转换是罪魁祸首。
编辑:我收回了针对Javascript的不友善和诽谤性言论。在当下的热度中,我的情绪变得更好。这是解决方案。
似乎JSON stringify / parse无法处理具有嵌入式方法的对象,这是有道理的。描述对象嵌入了_proto_
方法,您不需要通过信令传输给对等方。您只需要提供对象的sdp部分。实际上,我不知道所有这些是否完全正确,但无论如何,它都有效。
来自同行A的例子:
var msg = description.sdp;
...transmit message to peer B...
同行B:
...receive message from peer A...
remote_descr = new RTCSessionDescription();
remote_descr.type = "offer";
remote_descr.sdp = msg
如果需要,可以使用JSON stringify / parse并将type和sdp一起发送到一个对象中,而不是手动设置类型。
答案 1 :(得分:0)
您是指Google,W3C和IETF标准委员会成员的WebRTC项目的技术主管/经理,之前是Google+环聊,Google视频聊天和AOL Instant Messenger的Justin Uberti的技术负责人吗?
答案 2 :(得分:0)
我在代码中发现了一些错误。我将在下面重点介绍它们。以下代码在Chrome中添加了所有必需的描述和ICE候选项(显然是因为webkit
前缀)。
STUN = {'stun:stun.l.google.com:19302'};
iceServers = { iceServers: [STUN] };
DtlsSrtpKeyAgreement = { DtlsSrtpKeyAgreement: true };
optional = { optional: [{ DtlsSrtpKeyAgreement: true}] };
var pc1, pc2, offer, answer, offer_str, offer_prsd, answer_str, answer_prsd;
pc1 = new webkitRTCPeerConnection(iceServers, optional);
pc2 = new webkitRTCPeerConnection(iceServers, optional);
pc1.onicecandidate = function (evt) { //this callback returns an ICE EVENT not a candidate
if (pc2.remoteDescription !== null && evt.candidate !== null) //want to make sure remote description is set and that the candidate is not null(the last one will be null to indicate it being the last candidate for that signalling period)
pc2.addIceCandidate(evt.candidate, function () { console.log("added ice", evt.candidate); }, function () { console.log("failed to addice"); }); //handle the callback functions here to be sure ice is set
};
pc2.onicecandidate = function (evt) { //SAME HERE, the last candidate is always NULL
if (pc1.remoteDescription !== null && evt.candidate !== null)
pc1.addIceCandidate(evt.candidate, function () { console.log("added ice", evt.candidate); }, function () { console.log("failed to addice"); });
};
//PC1 KICKS OFF THE PROCESS WITH AN OFFER!!
pc1.createOffer(onOfferCreated, onError);
function onError(err) {
window.alert(err.message);
}
function onOfferCreated(description) {
offer = description;
//HERE IS THE OFFER CREATED!!!
offer_str = JSON.stringify(offer); //stringify and set before calling the call back. Yes, callbacks are asynchronous but you want to be sure and not get strange errors by things being called out of order
pc1.setLocalDescription(offer, onPc1LocalDescriptionSet, onError);
//WE SET IT AS "OUR LOCAL DESCRIPTIION
}
function onPc1LocalDescriptionSet() {
offer_prsd = JSON.parse(offer_str);
//console.log(offer_prsd.sdp);
var desc = new RTCSessionDescription(offer_prsd); //create a SessionDescription object given the parsed object
// after this function returns, pc1 will start firing icecandidate events
pc2.setRemoteDescription(desc, onPc2RemoteDescriptionSet, onError);
}
function onPc2RemoteDescriptionSet() {
pc2.createAnswer(onAnswerCreated, onError);
}
function onAnswerCreated(description) {
answer = description;
pc2.setLocalDescription(answer, onPc2LocalDescriptionSet, onError);
}
function onPc2LocalDescriptionSet() {
// after this function returns, you'll start getting icecandidate events on pc2
pc1.setRemoteDescription(answer, onPc1RemoteDescriptionSet, onError);
}
function onPc1RemoteDescriptionSet() {
window.alert('Yay, we finished signaling offers and answers');
}