21、日志与调试:WebRTC 内部日志(RTC_LOG)、常用调试工具(chrome://webrtc-internals)、常见问题定位
调试 WebRTC,说难不难,说简单也不简单。我见过不少同事,一遇到音视频卡顿就慌了神,到处乱翻代码。其实,WebRTC 内部早就给你准备好了调试武器,只是很多人不知道怎么用。
这一章,我就带你把这些武器摸透。从日志系统到浏览器内置工具,再到实战中的问题定位,咱们一条龙讲清楚。
21.1 WebRTC 内部日志:RTC_LOG 的秘密
先说说日志。WebRTC 的日志系统叫 RTC_LOG,它不像你平时用的 printf 或者 console.log 那么简单。它是有级别的,而且可以精细控制。
21.1.1 日志级别
RTC_LOG 定义了以下几个级别:
| 级别 | 宏 | 说明 |
|---|---|---|
| LS_VERBOSE | RTC_LOG(LS_VERBOSE) | 最详细的日志,一般用于调试 |
| LS_INFO | RTC_LOG(LS_INFO) | 常规信息,比如连接建立 |
| LS_WARNING | RTC_LOG(LS_WARNING) | 警告,不影响运行但值得注意 |
| LS_ERROR | RTC_LOG(LS_ERROR) | 错误,功能可能受损 |
| LS_NONE | 不输出 | 关闭所有日志 |
我个人习惯,开发阶段开到 LS_VERBOSE,线上环境只开 LS_WARNING 以上。为什么呢?因为 Verbose 级别的日志量太大了,每秒能刷出几百行,磁盘都扛不住。
21.1.2 如何开启日志
在 Chrome 浏览器中,你可以通过命令行参数来控制日志输出:
chrome --enable-logging --v=1 --vmodule="*=3,rtp_rtcp*=4"
解释一下:
--enable-logging:开启日志功能--v=1:全局日志级别,1 对应 LS_INFO--vmodule:模块级别的精细控制,这里把 rtp_rtcp 模块开到 4(LS_VERBOSE)
我曾经遇到过一个诡异的问题:视频偶尔花屏。全局日志看不出什么,但把 rtp_rtcp 模块的日志开到 Verbose 后,发现是某个包的序列号跳变导致的。嗯,这种问题,不细看日志根本找不到。
21.1.3 日志输出格式
RTC_LOG 的输出格式是这样的:
[级别][时间][线程ID][文件名:行号] 消息内容
举个例子:
[INFO][2024-01-15 10:23:45][12345][peerconnection.cc:256] ICE connection state changed: connected
你看,时间、线程、位置,一目了然。我排查问题时,第一件事就是看时间戳,确认问题发生的时刻。
RTC_LOG 配合 adb logcat 或 Xcode 的控制台。我一般会在关键路径上埋几个日志点,比如 "ICE 候选者收集完成"、"DTLS 握手成功" 这些。
21.2 chrome://webrtc-internals:调试神器
这个工具,我愿称之为 WebRTC 调试的瑞士军刀。你只要在 Chrome 地址栏输入 chrome://webrtc-internals,就能打开一个实时监控面板。
21.2.1 核心功能
这个页面会展示所有活跃的 PeerConnection 的详细信息,包括:
- Stats 图表:实时绘制比特率、丢包率、延迟等指标
- ICE 连接状态:候选者类型、连接对、状态变化
- RTP 流统计:发送/接收的包数、字节数、NACK 数
- 编解码器信息:当前使用的编码器、分辨率、帧率
- 事件日志:所有关键事件的记录,比如 createOffer、setLocalDescription
说白了,这就是 WebRTC 的黑匣子。飞机失事要找黑匣子,WebRTC 出问题就要找 webrtc-internals。
21.2.2 实战:如何用它定位问题
我举个例子。假设用户反馈视频卡顿,你该怎么查?
- 打开
chrome://webrtc-internals - 找到对应的 PeerConnection(如果有多个,看连接 ID)
- 看 Video Receiver 的统计:
packetsLost:丢包数,如果持续增长,说明网络不好jitter:抖动,超过 50ms 就可能卡顿framesDecoded:解码帧率,如果低于 15fps,画面就不流畅了- 再看 ICE 部分:
rtt:往返时间,超过 300ms 就会有明显延迟availableOutgoingBitrate:可用带宽,如果低于视频码率,就会降质
我记得有一次,用户说视频模糊。我一看 webrtc-internals,发现 availableOutgoingBitrate 只有 200kbps,但视频码率设了 1Mbps。说白了,带宽不够,WebRTC 自动降分辨率了。后来我们优化了码率自适应算法,问题就解决了。
21.3 常见问题定位思路
下面我列几个我工作中遇到最多的问题,以及定位方法。
21.3.1 连接建立失败
症状:两端始终无法建立通话,或者一方看不到对方。
排查步骤:
- 检查 ICE 状态:在 webrtc-internals 中看 ICE 是否变成 "connected" 或 "completed"。如果一直是 "checking",说明候选者没配对成功。
- 检查 STUN/TURN 服务器:用
chrome://webrtc-internals看候选者类型。如果只有 "host" 类型的候选者,说明 STUN 没生效。如果连 "host" 都没有,那可能是网络配置问题。 - 检查 SDP 交换:看日志中是否有 "Failed to set remote offer" 之类的错误。我遇到过一种情况,是两端 SDP 中的编解码器不匹配导致的。
21.3.2 音视频不同步
症状:声音和画面对不上,比如嘴型对不上。
原因:音频和视频的 RTP 时间戳不同步,或者接收端的缓冲策略有问题。
定位方法:
- 在 webrtc-internals 中看 audio 和 video 的
jitterBufferDelay。如果两者差异很大,说明缓冲不一致。 - 检查 NTP 时间戳:WebRTC 会用 NTP 时间来同步音视频。如果发送端没有正确设置 NTP,就会不同步。
21.3.3 频繁重连
症状:通话过程中,画面突然黑掉,几秒后又恢复。
原因:网络切换(比如 WiFi 切 4G)、ICE 连接超时、或者对端崩溃。
排查:
- 看 webrtc-internals 中的 ICE connection state 变化。如果频繁出现 "disconnected" -> "connected",说明网络不稳定。
- 看日志中的 ICE restart 事件。如果触发了 ICE restart,说明连接真的断了。
- 检查 RTT 是否突然飙升。我见过一种情况,是用户进了电梯,RTT 从 20ms 跳到 2000ms,然后连接就断了。
21.4 知识体系总览
下面这张图,帮你把本章的核心逻辑串起来:
21.5 我的调试习惯
最后,分享几个我个人的小习惯:
- 日志先开起来:不管什么问题,先把 RTC_LOG 开到 INFO 级别。很多时候,错误就藏在日志的最后几行。
- webrtc-internals 常开:我开发时,这个页面永远开着。就像开车要看仪表盘一样,实时数据能帮你提前发现问题。
- 保存现场:问题复现后,立刻导出 webrtc-internals 的 JSON 文件。我吃过亏,当时没保存,后来想分析却找不到数据了。
- 不要只看一个指标:比如丢包率高,不一定就是网络差。也可能是发送端码率太高,或者接收端处理不过来。要综合看比特率、延迟、帧率等多个指标。
调试 WebRTC,说白了就是跟数据打交道。日志给你线索,工具给你证据,剩下的就是推理了。多练几次,你也能成为排查问题的高手。
公众号:蓝海资料掘金营,微信deep3321