javascript - Webrtc 媒体流正在工作,但数据通道关闭(根本不启动)
问题描述
我正在尝试启动从本机客户端到 Web 浏览器的桌面屏幕流式传输。当我开始连接时,sdp 交换正常并且媒体流按它应该开始。但是数据通道会立即触发“关闭”事件。据我了解,数据通道应该在 sdp 交换之前创建,并且我将协商设置为 false。所以它应该自动通知其他对等方这个通道并启动数据通道。但这不是我的情况。
我尝试了许多不同的方法,例如使用选项设置数据通道或使用或不使用选项的对等连接。
我错过了什么吗?
以下是来自 Web 浏览器的启动器代码。
var pcConstraints = {};
var servers = {
//iceTransportPolicy: 'relay', // force turn
iceServers:
[
{ url: 'stun:stun.l.google.com:19302' },
{ url: 'stun:stun.stunprotocol.org:3478' },
{ url: 'stun:stun.anyfirewall.com:3478' }
]
};
var offerOptions = {
offerToReceiveAudio: 0,
offerToReceiveVideo: 1,
trickle: false
};
function startStream() {
console.log("startStream...");
remotestream = new RTCPeerConnection(servers, pcConstraints);
if (localstream) {
remotestream.addStream(localstream);
}
// optional data channel
dataChannel = remotestream.createDataChannel('testchannel', {});
setDataChannel(dataChannel);
remotestream.onaddstream = function (e) {
try {
console.log("remote media connection success!");
var vid2 = document.getElementById('vid2');
vid2.srcObject = e.stream;
vid2.onloadedmetadata = function (e) {
vid2.play();
};
var t = setInterval(function () {
if (!remotestream) {
clearInterval(t);
}
else {
Promise.all([
remotestream.getStats(null).then(function (o) {
var rcv = null;
var snd = null;
o.forEach(function (s) {
if ((s.type == "inbound-rtp" && s.mediaType == "video" && !s.isRemote) ||
(s.type == "ssrc" && s.mediaType == "video" && s.id.indexOf("recv") >= 0))
{
rcv = s;
}
else if((s.type == "outbound-rtp" && s.mediaType == "video" && !s.isRemote) ||
(s.type == "ssrc" && s.mediaType == "video" && s.id.indexOf("send") >= 0))
{
snd = s;
}
});
return dumpStat(rcv, snd);
})
]).then(function (s) {
statsdiv.innerHTML = "<small>" + s + "</small>";
});
}
}, 100);
} catch (ex) {
console.log("Failed to connect to remote media!", ex);
socket.close();
}
};
remotestream.onicecandidate = function (event) {
if (event.candidate) {
var ice = parseIce(event.candidate.candidate);
if (ice && ice.component_id == 1 // skip RTCP
//&& ice.type == 'relay' // force turn
&& ice.localIP.indexOf(":") < 0) { // skip IP6
console.log('onicecandidate[local]: ' + event.candidate.candidate);
var obj = JSON.stringify({
"command": "onicecandidate",
"candidate": event.candidate
});
send(obj);
localIce.push(ice);
}
else {
console.log('onicecandidate[local skip]: ' + event.candidate.candidate);
}
}
else {
console.log('onicecandidate: complete.')
if (remoteAnswer) {
// fill empty pairs using last remote ice
//for (var i = 0, lenl = localIce.length; i < lenl; i++) {
// if (i >= remoteIce.length) {
// var c = remoteIce[remoteIce.length - 1];
// var ice = parseIce(c.candidate);
// ice.foundation += i;
// c.candidate = stringifyIce(ice);
// remotestream.addIceCandidate(c);
// }
//}
}
}
};
remotestream.createOffer(function (desc) {
console.log('createOffer: ' + desc.sdp);
remotestream.setLocalDescription(desc, function () {
var obj = JSON.stringify({
"command": "offer",
"desc": desc
});
send(obj);
},
function (errorInformation) {
console.log('setLocalDescription error: ' + errorInformation);
});
},
function (error) {
alert(error);
},
offerOptions);
}
function setDataChannel(dc) {
dc.onerror = function (error) {
alert("DataChannel Error:", error);
};
dc.onmessage = function (event) {
alert("DataChannel Message:", event.data);
};
dc.onopen = function () {
dataChannel.send("Hello World!");
};
dc.onclose = function (error) {
alert("DataChannel is Closed");
alert(error.data)
};
}
解决方案
推荐阅读
- javascript - 避免Angular组件中的许多if语句调用特定函数的最佳方法是什么?
- r - 如何将数字序列转换为列
- java - 对于带有 ArrayList 的每个循环
- css - 如何使用实用程序优先方法(例如引导程序)使用 STATIC HTML 创建动态布局
- java - 如何传递一个接受浮点数并将浮点数返回给另一个函数的函数?
- python - Django过滤器选择字段显示正确的值但不会过滤
- docker - Kubernetes Persistent Volume Claims 创建一个新的 Persistent Volume,而不是绑定到可用的 Persistent Volume
- swift - SwiftUI:如何从核心数据中的 TextField 中保存值
- python - 如何实现有效的算法来计算大型数据集的多个不同值?
- php - 传递密钥并在函数内部使用数组