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

你看,时间、线程、位置,一目了然。我排查问题时,第一件事就是看时间戳,确认问题发生的时刻。

小技巧: 如果你在 Android 或 iOS 上调试,可以用 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 实战:如何用它定位问题

我举个例子。假设用户反馈视频卡顿,你该怎么查?

  1. 打开 chrome://webrtc-internals
  2. 找到对应的 PeerConnection(如果有多个,看连接 ID)
  3. Video Receiver 的统计:
    • packetsLost:丢包数,如果持续增长,说明网络不好
    • jitter:抖动,超过 50ms 就可能卡顿
    • framesDecoded:解码帧率,如果低于 15fps,画面就不流畅了
  4. 再看 ICE 部分:
    • rtt:往返时间,超过 300ms 就会有明显延迟
    • availableOutgoingBitrate:可用带宽,如果低于视频码率,就会降质

我记得有一次,用户说视频模糊。我一看 webrtc-internals,发现 availableOutgoingBitrate 只有 200kbps,但视频码率设了 1Mbps。说白了,带宽不够,WebRTC 自动降分辨率了。后来我们优化了码率自适应算法,问题就解决了。

重点: webrtc-internals 的数据是实时刷新的,你可以点击 "Save" 按钮导出 JSON 文件。我建议你在问题复现时立刻保存一份,方便事后分析。

21.3 常见问题定位思路

下面我列几个我工作中遇到最多的问题,以及定位方法。

21.3.1 连接建立失败

症状:两端始终无法建立通话,或者一方看不到对方。

排查步骤:

  1. 检查 ICE 状态:在 webrtc-internals 中看 ICE 是否变成 "connected" 或 "completed"。如果一直是 "checking",说明候选者没配对成功。
  2. 检查 STUN/TURN 服务器:用 chrome://webrtc-internals 看候选者类型。如果只有 "host" 类型的候选者,说明 STUN 没生效。如果连 "host" 都没有,那可能是网络配置问题。
  3. 检查 SDP 交换:看日志中是否有 "Failed to set remote offer" 之类的错误。我遇到过一种情况,是两端 SDP 中的编解码器不匹配导致的。
注意: 我曾经踩过一个坑——TURN 服务器的认证过期了。结果连接一直失败,日志里只显示 "ICE failed"。后来我抓包才发现,TURN 服务器返回了 401 未授权。所以,别忘了检查 TURN 的时效性。

21.3.2 音视频不同步

症状:声音和画面对不上,比如嘴型对不上。

原因:音频和视频的 RTP 时间戳不同步,或者接收端的缓冲策略有问题。

定位方法:

  • 在 webrtc-internals 中看 audiovideojitterBufferDelay。如果两者差异很大,说明缓冲不一致。
  • 检查 NTP 时间戳:WebRTC 会用 NTP 时间来同步音视频。如果发送端没有正确设置 NTP,就会不同步。

21.3.3 频繁重连

症状:通话过程中,画面突然黑掉,几秒后又恢复。

原因:网络切换(比如 WiFi 切 4G)、ICE 连接超时、或者对端崩溃。

排查:

  1. 看 webrtc-internals 中的 ICE connection state 变化。如果频繁出现 "disconnected" -> "connected",说明网络不稳定。
  2. 看日志中的 ICE restart 事件。如果触发了 ICE restart,说明连接真的断了。
  3. 检查 RTT 是否突然飙升。我见过一种情况,是用户进了电梯,RTT 从 20ms 跳到 2000ms,然后连接就断了。

21.4 知识体系总览

下面这张图,帮你把本章的核心逻辑串起来:

WebRTC 日志与调试知识体系 RTC_LOG 内部日志 级别控制 · 模块过滤 · 格式解析 chrome://webrtc-internals 实时统计 · ICE状态 · 事件日志 常见问题定位 连接失败 · 音视频不同步 · 重连 日志级别:VERBOSE / INFO / WARNING / ERROR 命令行参数:--v / --vmodule 日志格式:[级别][时间][线程][位置] Stats 图表:比特率 / 丢包率 / 延迟 ICE 连接:候选者 / 状态 / RTT RTP 流:包数 / NACK / 帧率 连接失败:ICE / STUN / SDP 音视频不同步:NTP / 缓冲 频繁重连:网络切换 / 超时 核心思路:日志定位 → 工具验证 → 问题修复

21.5 我的调试习惯

最后,分享几个我个人的小习惯:

  • 日志先开起来:不管什么问题,先把 RTC_LOG 开到 INFO 级别。很多时候,错误就藏在日志的最后几行。
  • webrtc-internals 常开:我开发时,这个页面永远开着。就像开车要看仪表盘一样,实时数据能帮你提前发现问题。
  • 保存现场:问题复现后,立刻导出 webrtc-internals 的 JSON 文件。我吃过亏,当时没保存,后来想分析却找不到数据了。
  • 不要只看一个指标:比如丢包率高,不一定就是网络差。也可能是发送端码率太高,或者接收端处理不过来。要综合看比特率、延迟、帧率等多个指标。

调试 WebRTC,说白了就是跟数据打交道。日志给你线索,工具给你证据,剩下的就是推理了。多练几次,你也能成为排查问题的高手。


公众号:蓝海资料掘金营,微信deep3321