有没有办法以编程方式获取有关WebRTC中使用的连接类型的信息?
例如,在我的应用程序中,我使用本地连接以及STUN和TURN。如果候选者的类型是主机或中继,我可以从ICE候选者收集,并且在服务器上,我可以看到是否通过STUN(连接启动)或TURN(连接期间的稳定流)尝试连接。
到目前为止,我找不到一种方法来访问浏览器中最终使用的连接类型的信息。有候选人,浏览器停止收集,然后有一个工作连接。透过这些事件我找不到任何信息。
我知道Chrome在peerconnection上支持getStats(),这允许我访问chrome:// webrtc-internals中的大部分信息,但我也没有在那里找到这些信息。
有没有办法从JavaScript访问此信息?
非常感谢你。
根据the specification(目前在Firefox中实现但不在Chrome中),您确实可以从候选对的统计数据中找出活跃的候选者,这些候选对包括:
dictionary RTCIceCandidatePairStats : RTCStats {
DOMString transportId;
DOMString localCandidateId;
DOMString remoteCandidateId;
RTCStatsIceCandidatePairState state;
unsigned long long priority;
boolean nominated;
boolean writable;
boolean readable;
unsigned long long bytesSent;
unsigned long long bytesReceived;
double roundTripTime;
double availableOutgoingBitrate;
double availableIncomingBitrate;
};
结合候选人的统计数据:
dictionary RTCIceCandidateAttributes : RTCStats {
DOMString ipAddress;
long portNumber;
DOMString transport;
RTCStatsIceCandidateType candidateType;
long priority;
DOMString addressSourceUrl;
};
使用peerConnection.getStats()
寻找既被提名又成功的冰候选对:
pc.getStats(null))
.then(function(stats) {
return Object.keys(stats).forEach(function(key) {
if (stats[key].type == "candidatepair" &&
stats[key].nominated && stats[key].state == "succeeded") {
var remote = stats[stats[key].remoteCandidateId];
console.log("Connected to: " + remote.ipAddress +":"+
remote.portNumber +" "+ remote.transport +
" "+ remote.candidateType);
}
});
})
.catch(function(e) { console.log(e.name); });
这可能会输出如下内容:
Connected to: 192.168.1.2:49190 udp host
你可以测试对LAN range。如果相反它返回如下:
Connected to: 24.57.143.7:61102 udp relayed
然后你有一个TURN连接。
这是一个显示这个的jsfiddle(出于其他原因需要Firefox Developer Edition)。
感谢@DavidP和more in-depth answer,我编写了下面的代码来获得ICE Candidates类型。
更新的代码:使用conncectionStats获取ICE候选人
function getCandidateIds(stats) {
let ids = {}
stats.forEach(report => {
if (report.type == "candidate-pair" && report.nominated && report.state == "succeeded") {
//console.log("Found IDs")
ids = {
localId: report.localCandidateId,
remoteId: report.remoteCandidateId
}
}
});
return ids
}
function getCandidateInfo(stats, candidateId) {
let info = null
stats.forEach(report => {
if (report.id == candidateId) {
console.log("Found Candidate")
info = report
}
})
return info
}
async function conncectionStats() {
const stats = await this.pc.getStats(null)
const candidates = await this.getCandidateIds(stats)
console.log("candidates: ", candidates)
if (candidates !== {}) {
const localCadidate = await this.getCandidateInfo(stats, candidates.localId)
const remoteCadidate = await this.getCandidateInfo(stats, candidates.remoteId)
if (localCadidate !== null && remoteCadidate !== null) {
return [localCadidate, remoteCadidate]
}
}
// we did not find the candidates for whatever reeason
return [null, null]
}
读出IP:
let myAddress = ""
let peerAddress = ""
if (localCadidate.hasOwnProperty("ip")){
myAddress = localCadidate.ip
peerAddress = remoteCadidate.ip
} else {
myAddress = localCadidate.address
peerAddress = remoteCadidate.address
}
旧版:
function getConnectionDetails(pc){
pc.getStats(null)
.then(function(stats) {
stats.forEach(report => {
if (report.type == "candidate-pair"
&& report.nominated
&& report.state == "succeeded")
{
console.log( "Local ICE:", report.localCandidateId)
console.log( "Remote ICE:",report.remoteCandidateId)
getCandidates(pc, report.localCandidateId, report.remoteCandidateId)
}
});
})
.catch(function(e) { console.log(e.name); });
};
function getCandidates(pc, localId, remoteId){
//console.log("looking for candidates")
pc.getStats(null)
.then(function(stats) {
stats.forEach(report => {
if (report.id == localId) {
console.log("Local: Type:", report.candidateType," IP:", report.ip)
} else if (report.id == remoteId){
console.log("Remote: Type:", report.candidateType," IP:", report.ip)
}
})
})
.catch(function(e) { console.log(e.name); });
}
根据应提取的信息,您可能不需要两个候选人。
jib从2015年3月开始的答案非常有用,但在2019年3月不适用于Firefox v65或Chrome v72(在Windows上)。需要两个更新:
1)“stats”值现在在两个浏览器中都有RTCStatsReport类型,它是一个没有键的可迭代对象。因此,使用forEach(report => {...})迭代它,“report”将是一个对象,其中的键就像jib为“stats”显示的那样。
2)“candidatepair”不是report.type的有效值,而是“候选对”。