在浏览器中获取 WebRTC 的各种状态是一种非常有效的调试方法,本文介绍使用浏览器对 WebRTC 进行调试分析的一些经验和方法。
0x01 最小 WebRTC 环境
编辑一个 HTML 文件并使用浏览器打开即可构建一个最小的 WebRTC 环境。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>WebRTC Atomic</title>
<link rel="help" href="https://aggresss.github.io/playground-js/webrtc/atomic/src/atomic.html">
</head>
<body>
<video id="video" width="320" height="240" playsinline autoplay muted></video>
<script>
const video = document.getElementById("video");
const div = document.body.appendChild(document.createElement("div"));
const console = { log: msg => div.innerHTML += msg + "<br>" };
const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
const add = (pc, can) => can && pc.addIceCandidate(can).catch(e => console.log(e));
pc1.onicecandidate = e => add(pc2, e.candidate);
pc2.onicecandidate = e => add(pc1, e.candidate);
pc2.ontrack = async e => { video.srcObject = e.streams[0]; };
pc1.onnegotiationneeded = async e => {
try {
await pc1.setLocalDescription(await pc1.createOffer());
await pc2.setRemoteDescription(pc1.localDescription);
await pc2.setLocalDescription(await pc2.createAnswer());
await pc1.setRemoteDescription(pc2.localDescription);
} catch (e) { console.log(e); }
};
(async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: { height: 640 } });
const sender = pc1.addTrack(stream.getVideoTracks()[0], stream);
} catch (e) { console.log(e); }
})();
</script>
</body>
</html>
0x02 webrtc-internals 使用说明
Chrome 浏览器提供的 chrome://webrtc-internals 可以获取当前浏览器中运行的 WebRTC 实例的实时状态,如下图所示:
chrome://webrtc-internals 页面为每个 PeerConnection 建立了一个 Tab,如果有 getUserMida 或 getDisplayMedia 调用的话会附加一个 GetUserMedia Requests
Tab。
每个 PeerConnection 的 Tab 页面分成 4 个部分:
- RTCPeerConnection 的创建参数;
- PeerConnection API 的调用轨迹;
- 从 getStats() API 采集的实时数据;
- 由 getStats() API 计算产生的图表;
0x03 RTCPeerConnection.getStats()
WebRTC 标准接口定义了获取 PeerConnection 状态的接口 RTCPeerConnection.getStats()
其中 RTCStatsType 包括:
- candidate-pair
- certificate
- codec
- csrc
- data-channel
- inbound-rtp
- local-candidate
- outbound-rtp
- peer-connection
- receiver
- remote-candidate
- remote-inbound-rtp
- remote-outbound-rtp
- sender
- stream
- track
- transport
RTCPeerConnection.getStats()
的实例可以参考 WebRTC samples Constraints & statistics,对应源文件为
https://github.com/webrtc/samples/tree/gh-pages/src/content/peerconnection/constraints
0x05 其他调试工具
1. Chrome 浏览器
浏览器也是一个应用程序,当浏览器提供的 WebRTC 调试接口的信息仍然无法满足调试需求时,可以通过浏览器的调试信息来间接查看 WebRTC 的调试信息。
参考 https://www.chromium.org/for-testers/enable-logging 中提供的方式,通过参数方式启动浏览器,例如
chrome --enable-logging=stderr --v=0
或者开启同时保存到文件的方式:
chrome --enable-logging=stderr --v=0 > >(tee chrome_01.log) 2>&1
2. Firefox 浏览器
Fiirefox 可以通过在地址栏输入 about:webrtc
来调试,需要注意的是需要不断刷新页面来获取最新的 WebRTC 连接状态。
Firefox 也可以通过开启调试信息的方式通过浏览器调试信息间接查看 WebRTC 调试信息。
参考 https://wiki.mozilla.org/Media/WebRTC/Logging 中提供的方法,通过命令行方式启动浏览器,例如:
MOZ_LOG=webrtc_trace:5 MOZ_LOG_FILE=${PWD}/moz/moz_01.log firefox
3. Safari 浏览器
Safari 浏览器并没有提供类似 Chrome 中的 chrome://webrtc-internal
功能,但是它提供了 Allow Media Capture on Insecure Sites
和 Use Mock Capture Devices
功能可以与 Chrome 浏览器形成互补。
打开 Safari 开发者选项
- 选中 Preference → Advanced → Show Develop menu in menu bar
- 终端中输入
defaults write com.apple.Safari IncludeInternalDebugMenu 1
- 调试模式 -> Console -> Settings -> Console -> WebRTC Logging
上述操作完成后重新启动 Safari 会在 develop 菜单栏中看到 WebRTC 相关的选项,如下图所示。
Safari 的 Mock Devices
在测试 WebRTC RTT(Round-Trip Time) 时特别有用,可以不用再拿秒表对着屏幕了。
参考文档:
- New Tool for Debugging WebRTC
- The Missing chrome://webrtc-internals Documentation
- What Do The Parameters In webrtc-internals Really Mean?
- Reeling in Safari on WebRTC – A Closer Look at What’s Supported
- How to Enable Debug Menu in Safari in Mac OS X El Capitan
- WebRTC Externals – the cross-browser WebRTC debug extension
- A Closer Look Into WebRTC
- WebRTC内置debug工具,详细参数解读