You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何分析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:当前网络往返时延(单位秒)

码率与时间戳对应图绘制方法

码率为增量统计值,无法直接使用累计字节字段计算,步骤如下:

  1. 按timestamp升序排列所有统计快照,计算相邻两个快照的时间差deltaT = (t2 - t1)/1e6,单位转换为秒
  2. 对应码率计算公式:
    • 上行发送码率:(bytesSent2 - bytesSent1) * 8 / deltaT,计算结果单位为bps,转换为Mbps除以1e6即可
    • 下行接收码率:(bytesReceived2 - bytesReceived1) * 8 / deltaT
  3. 以每个快照相对于统计起始点的相对时间为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:06:02