vlcj MediaStatistics无法展示完整统计数据 摄像头推流仅demuxBitrate正常
1 解码/播放类字段为0的原因
你当前使用的是VLC的sout(流输出)推流模式,媒体数据完成解复用后直接进入转码、推流链路,不会触发本地解码、音频播放、视频渲染流程,因此audioBuffersPlayed、decodedAudio、decodedVideo、picturesDisplayed等本地播放相关字段返回0属于正常现象,无需特殊处理。
2 demuxBytesRead负数异常修复
该问题是类型映射溢出导致:VLC底层该字段为无符号64位整数,Java侧默认按有符号长整型解析,数值超过有符号上限后就会出现负数,转换为无符号类型即可拿到正确值:
val correctDemuxBytes = Long.toUnsignedString(mediaStatistics.demuxBytesRead())
3 输入/发送类统计为0的修复方案
默认的MediaStatistics仅统计解复用环节的基础数据,输入、推流相关指标属于sout输出模块,默认未开启采集,需要做三处修改:
3.1 修正MediaPlayerFactory初始化逻辑
你原代码中初始化MediaPlayerFactory时传入了媒体地址dshow://,属于错误用法:MediaPlayerFactory构造参数仅接收VLC全局启动参数,媒体地址应该在mediaPlayer.media().play()时传入,该错误也可能导致统计模块初始化异常。
同时需要传入sout统计开启参数,初始化代码修正为:
// 仅传入启动参数,开启流输出统计 mediaPlayerFactory = MediaPlayerFactory("--sout-statistics") mediaPlayer = mediaPlayerFactory.mediaPlayers().newMediaPlayer() // 媒体地址在play时传入 if (isHttpProtocol) { mediaPlayer.media().play( "dshow://", streamOptions, ) } else { mediaPlayer.media().play( "dshow://", streamOptions, ":no-sout-rtp-sap", ":no-sout-standard-sap", ":sout-all", ":sout-keep", ) }
3.2 更换统计数据获取方式
不要通过media().info().statistics()拉取数据,改为监听统计更新事件,可以拿到完整的全链路统计:
在init块中初始化mediaPlayer后添加事件监听即可:
mediaPlayer.events().addMediaStatisticsEventListener { _, statistics -> // 此处拿到的statistics包含sout模块的输入、发送统计 println("输入比特率: ${statistics.inputBitrate()}") println("发送比特率: ${statistics.sendBitrate()}") println("已发送字节数: ${statistics.sentBytes()}") }
补充说明
如果需要更高精度的推流带宽统计,也可以自行定时计算发送字节数的差值:间隔1秒读取两次sentBytes,差值乘以8就是当前的实际推流比特率,比SDK返回的sendBitrate数值更稳定。
内容的提问来源于stack exchange,提问作者CalmPerson

