如何获得有关WebRTC PeerConnection的连接类型的信息?

Dug*_*lum 5 javascript browser webrtc

有什么方法可以通过编程方式获取有关WebRTC中使用的连接类型的信息?

例如,在我的应用程序中,我使用本地连接以及STUN和TURN。从ICE候选对象中,我可以收集候选对象的类型是主机还是中继,并且在服务器上,我可以查看是通过STUN(连接启动)还是TURN(连接期间的稳定流)尝试连接。

到目前为止,我还没有找到一种方法来访问有关浏览器中最终使用的连接类型的信息。有候选人,浏览器停止收集,然后存在有效的连接。通过事件查看我找不到任何信息。

我知道Chrome在对等连接上支持getStats(),这使我可以访问chrome:// webrtc-internals中找到的大多数信息,但是我也没有在此找到此信息。

有什么办法可以从javascript访问此信息?

非常感谢你。

jib*_*jib 6

根据目前在 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;
};
Run Code Online (Sandbox Code Playgroud)

结合个别候选人的统计数据:

dictionary RTCIceCandidateAttributes : RTCStats {
    DOMString                ipAddress;
    long                     portNumber;
    DOMString                transport;
    RTCStatsIceCandidateType candidateType;
    long                     priority;
    DOMString                addressSourceUrl;
};
Run Code Online (Sandbox Code Playgroud)

使用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); });
Run Code Online (Sandbox Code Playgroud)

这可能会输出如下内容:

Connected to: 192.168.1.2:49190 udp host
Run Code Online (Sandbox Code Playgroud)

您可以针对LAN 范围进行测试。如果相反,它返回如下内容:

Connected to: 24.57.143.7:61102 udp relayed
Run Code Online (Sandbox Code Playgroud)

那么你就有了一个 TURN 连接。

这是一个显示这一点的jsfiddle(由于其他原因需要 Firefox Developer Edition)。


小智 5

jib 在 2015 年 3 月的回答非常有帮助,但不适用于 2019 年 3 月的 Firefox v65 或 Chrome v72(在 Windows 上)。需要两个更新:

1) 现在,“stats”值在两个浏览器中的类型均为 RTCStatsReport,并且它是一个没有键的可迭代对象。因此,使用 forEach(report => {...}) 迭代它,“report”将是一个对象,其键类似于 jib 显示的“stats”键。

2)“candidatepair”不是report.type的有效值,但“candidate-pair”是。


Jes*_*end 5

我花了很长时间才弄对,所以希望这对某人有所帮助。

新方式

您现在可以从RTCPeerConnection没有 stats api的情况下获取选定的候选对:

const pair = rtcConnection.sctp.transport.iceTransport.getSelectedCandidatePair();
console.log(pair.remote.type);
Run Code Online (Sandbox Code Playgroud)

在撰写本文时(2020 年 10 月 2 日),这仅适用于 Chromium。您仍然可以将 stats api 用于其他浏览器。还要注意jib下面的评论,这仅在您有 DataChannel 时才有效。

对于没有 getSelectedCandidatePair() 支持的浏览器

根据https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidatePairStats (在selected属性页面的底部。

确定所选候选对的符合规范的方法是查找传输类型的 stats 对象,它是一个 RTCTransportStats 对象。该对象的 selectedCandidatePairId 属性指示指定的传输是否是正在使用的传输。

因此,尝试使用找到选定的对stat.nominated && stats.state == "succeeded"不是正确的方法。

相反,您可以通过查看transport统计信息中的选定对来获得它。Firefox 不支持这一点,但幸运的是selected,firefox 的候选对中有一个非标准属性。

const stats = await rtcConnection.getStats();
if(stats){
    let selectedPairId = null;
    for(const [key, stat] of stats){
        if(stat.type == "transport"){
            selectedPairId = stat.selectedCandidatePairId;
            break;
        }
    }
    let candidatePair = stats.get(selectedPairId);
    if(!candidatePair){
        for(const [key, stat] of stats){
            if(stat.type == "candidate-pair" && stat.selected){
                candidatePair = stat;
                break;
            }
        }
    }

    if(candidatePair){
        for(const [key, stat] of stats){
            if(key == candidatePair.remoteCandidateId){
                return stat.candidateType;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)