如何分析WebRTC内部转储文件并绘制视频质量、码率与时间戳关系图
WebRTC internals JSON转储分析与绘图指南
转储文件核心结构与常用字段含义
chrome://webrtc-internals导出的JSON文件顶层包含PeerConnections字段,每个PeerConnection实例下的stats数组存储全量时间序列统计快照,每个快照自带timestamp字段,单位为微秒,转换为秒直接除以1e6即可。
常用统计字段按类型分类如下:
- 发送端视频轨道(统计项类型为
outbound-rtp,关联video媒体类型)bytesSent:累计发送的视频字节数,用于计算实时发送码率framesEncoded:累计编码完成的视频帧数framesPerSecond:当前编码输出帧率qpSum:所有编码帧的QP值总和,用于计算平均编码质量nackCount:接收端发来的丢包重传请求总次数firCount:接收端发来的关键帧请求总次数
- 接收端视频轨道(统计项类型为
inbound-rtp,关联video媒体类型)bytesReceived:累计接收的视频字节数,用于计算实时接收码率framesDecoded:累计解码完成的视频帧数frameWidth/frameHeight:当前解码输出的视频分辨率freezeCount/totalFreezeDuration:视频卡顿次数与累计卡顿总时长(单位毫秒)jitterBufferDelay:抖动缓冲区累计延迟总时长(单位秒)packetsLost:累计视频丢包数
- 传输层通用字段(统计项类型为
transport)availableOutgoingBitrate:WebRTC内核预估的上行可用带宽(单位bps)availableIncomingBitrate:WebRTC内核预估的下行可用带宽(单位bps)roundTripTime:当前网络往返时延(单位秒)
码率与时间戳对应图绘制方法
码率为增量统计值,无法直接使用累计字节字段计算,步骤如下:
- 按
timestamp升序排列所有统计快照,计算相邻两个快照的时间差deltaT = (t2 - t1)/1e6,单位转换为秒 - 对应码率计算公式:
- 上行发送码率:
(bytesSent2 - bytesSent1) * 8 / deltaT,计算结果单位为bps,转换为Mbps除以1e6即可 - 下行接收码率:
(bytesReceived2 - bytesReceived1) * 8 / deltaT
- 上行发送码率:
- 以每个快照相对于统计起始点的相对时间为X轴,计算得到的码率为Y轴绘制折线图即可
视频质量相关指标绘制方法
可按需选择以下常用视频质量指标绘制时间序列图:
- 实时帧率:直接取每个快照的
framesPerSecond为Y轴,通常低于15fps用户会感知明显卡顿 - 平均QP值:相邻快照的
qpSum增量除以framesEncoded(发送端)/framesDecoded(接收端)增量,得到该时间段平均QP,通常QP高于35用户会感知画质明显下降 - 卡顿占比:按固定时间窗口(如10秒)计算窗口内
totalFreezeDuration增量除以窗口时长,得到该窗口内卡顿时间占比 - 实时丢包率:相邻快照
packetsLost增量除以(packetsReceived增量+packetsLost增量),通常丢包率高于2%就会对画质和流畅度产生明显影响
快速处理示例代码
以下是Python处理转储文件并绘图的最小示例:
import json import matplotlib.pyplot as plt # 加载WebRTC转储文件 with open("webrtc_dump.json", "r") as f: dump_data = json.load(f) # 取出第一个PeerConnection的统计数据 first_pc = list(dump_data["PeerConnections"].values())[0] all_stats = first_pc["stats"] # 筛选接收端视频统计项并按时间排序 inbound_video_stats = [s for s in all_stats if s["type"] == "inbound-rtp" and s.get("mediaType") == "video"] inbound_video_stats.sort(key=lambda x: x["timestamp"]) rel_time_list = [] bitrate_list = [] framerate_list = [] for i in range(1, len(inbound_video_stats)): prev_stat = inbound_video_stats[i-1] curr_stat = inbound_video_stats[i] delta_t = (curr_stat["timestamp"] - prev_stat["timestamp"]) / 1e6 if delta_t <= 0: continue # 计算下行码率,单位转Mbps byte_delta = curr_stat["bytesReceived"] - prev_stat["bytesReceived"] curr_bitrate = (byte_delta * 8) / delta_t / 1e6 # 计算相对于统计起始点的时间,单位秒 rel_time = (curr_stat["timestamp"] - inbound_video_stats[0]["timestamp"]) / 1e6 rel_time_list.append(rel_time) bitrate_list.append(curr_bitrate) framerate_list.append(curr_stat["framesPerSecond"]) # 绘制图表 plt.figure(figsize=(12, 6)) plt.plot(rel_time_list, bitrate_list, label="下行码率(Mbps)") plt.plot(rel_time_list, framerate_list, label="解码帧率(fps)") plt.xlabel("时间(秒)") plt.ylabel("数值") plt.legend() plt.show()
部分旧版本Chrome导出的统计项没有mediaType字段,可替换为kind字段判断媒体类型,或者通过统计项id的前缀区分。
内容的提问来源于stack exchange,提问作者Keshav Gambhir
相关产品推荐
相关产品推荐

