29、推流器测试与调试:推流测试工具(OBS、VLC)、日志系统、性能分析工具(Systrace、Profiler)

推流器写完了,代码编译通过,能跑起来——但这只是万里长征第一步。

说实话,我见过太多同学在模拟器上点一下“开始推流”,看到日志里打出几行“connected”就欢呼雀跃,结果一上真机,画面卡成PPT,延迟飙到十几秒。嗯,推流器的测试与调试,才是真正考验功力的地方。

这一章,我就把压箱底的调试三板斧拿出来。咱们从推流测试工具讲起,再到日志系统怎么搭,最后聊性能分析工具怎么用。你跟着走一遍,以后遇到推流问题,心里就有底了。

推流器测试与调试知识体系 推流器调试三板斧 推流测试工具 OBS 模拟推流 VLC 拉流验证 日志系统 分级日志输出 关键节点埋点 性能分析工具 Systrace 帧分析 Profiler 内存/CPU 目标:稳定推流 + 低延迟 + 低功耗

一、推流测试工具:OBS 和 VLC 怎么搭

先说说测试环境怎么搭。我个人习惯用 OBS 做推流模拟端,VLC 做拉流验证端。这两个工具免费、跨平台,而且社区活跃,遇到问题搜一搜就有答案。

1.1 用 OBS 模拟推流端

OBS 本身是个直播推流软件,但我们拿它来干什么?模拟一个“标准推流器”。

你想想看,如果你的 Android 推流器出了问题,你总得有个参照物吧?OBS 就是那个参照物。我一般这样操作:

  • 在 OBS 里设置好推流地址(rtmp://your_server/live/streamkey)
  • 用 OBS 推流,然后在 VLC 里拉流,确认服务器和网络没问题
  • 再用你的 Android 推流器推同样的地址,对比效果
小技巧: OBS 的日志文件里会记录每一帧的编码耗时、丢帧数。如果 OBS 推流正常但你的 App 推流卡顿,问题大概率出在编码或网络模块上。

1.2 用 VLC 拉流验证

VLC 不只是个播放器,它还是个强大的流媒体调试工具。打开 VLC,按 Ctrl+N,输入 RTMP 地址,就能看到实时画面。

我记得有一次调试,画面总是绿屏。我一开始怀疑是编码器参数配错了,折腾了半天。后来用 VLC 的“工具 -> 媒体信息 -> 编解码器”一看,发现是色彩空间设置不匹配。嗯,VLC 的媒体信息面板能显示视频的编码格式、分辨率、帧率、色彩空间,这些信息对排查问题太有用了。

注意: VLC 默认的缓存设置比较大(300ms-1000ms),拉流时看到的延迟会比实际大。调试低延迟场景时,记得在“工具 -> 偏好设置 -> 输入/编解码器”里把网络缓存调到 100ms 左右。

二、日志系统:推流器的“黑匣子”

推流器跑在手机上,你没法像调试 PC 程序那样打断点。日志系统就是你的眼睛。我见过很多同学日志打得满天飞,但真正出问题时,翻半天找不到关键信息。为什么?因为没有分级,没有结构。

2.1 日志分级:别什么都打

我建议把日志分成三级:

级别 标签 输出内容
ERROR RTMP_ERROR 连接失败、编码崩溃、丢包超阈值
WARN RTMP_WARN 网络抖动、缓冲区将满、丢帧
INFO RTMP_FLOW 连接建立、推流开始/结束、关键帧间隔

为什么要这么分?因为线上环境你不可能把所有日志都打开。我曾经在某个项目里,DEBUG 日志没关,结果用户手机一天写了几百 MB 日志,直接把存储撑爆了。所以,线上只保留 ERROR 和 WARN,INFO 只在调试阶段开启。

2.2 关键节点埋点

推流器的生命周期里,有几个节点必须打日志:

  • 连接阶段: DNS 解析耗时、TCP 握手耗时、RTMP 握手耗时
  • 推流阶段: 每帧编码耗时、发送耗时、当前发送缓冲区大小
  • 断开阶段: 断开原因(用户主动/网络超时/服务器拒绝)

代码里大概长这样:

// 连接阶段埋点
long dnsStart = System.currentTimeMillis();
// 执行 DNS 解析...
long dnsCost = System.currentTimeMillis() - dnsStart;
Log.i(TAG, "[RTMP_FLOW] DNS解析耗时: " + dnsCost + "ms");

// 推流阶段埋点
long encodeStart = System.nanoTime();
// 编码一帧...
long encodeCost = (System.nanoTime() - encodeStart) / 1000000;
Log.d(TAG, "[RTMP_PERF] 编码耗时: " + encodeCost + "ms, 缓冲区大小: " + bufferSize);
核心思路: 日志不是写给机器看的,是写给人看的。每个日志都要能回答一个问题:“当前推流器在干什么?花了多久?有没有异常?”

三、性能分析工具:Systrace 和 Profiler

日志能告诉你“发生了什么”,但性能分析工具能告诉你“为什么慢”。

3.1 Systrace:抓帧级别的性能瓶颈

Systrace 是 Android 自带的性能分析工具,它能记录系统各个进程的耗时情况,精确到微秒级别。对于推流器来说,我最常用它来排查“掉帧”问题。

操作步骤很简单:

  1. 打开开发者选项 -> 开启“GPU 渲染模式分析”
  2. 用命令行启动 Systrace:python systrace.py -t 10 -o trace.html sched gfx view
  3. 在手机上操作推流,持续 10 秒
  4. 打开生成的 trace.html,看渲染线程和编码线程的时间线

为什么会掉帧?说白了就是某个任务占用了太多时间,导致下一帧没赶上。在 Systrace 里,你会看到一条条彩色的长条,如果某个长条特别长,那就是瓶颈所在。

我记得有一次,Systrace 显示编码线程每 33ms 才处理一帧(目标 30fps 应该是 33ms 一帧),但渲染线程每 16ms 就提交一帧。这说明编码器跟不上渲染速度,缓冲区在堆积。后来我把编码器的码率控制模式从 CBR 改成了 VBR,问题就解决了。

3.2 Android Profiler:内存和 CPU 的“体检报告”

Profiler 是 Android Studio 自带的工具,比 Systrace 更直观。我一般用它看三样东西:

  • CPU 使用率: 推流时 CPU 是否飙到 80% 以上?如果是,说明编码器太耗资源,考虑降分辨率或换硬件编码
  • 内存分配: 有没有频繁的 GC(垃圾回收)?GC 会导致卡顿,尤其是 ART 虚拟机在 GC 时会暂停所有线程
  • 网络流量: 实际发送的字节数和预期是否一致?如果差距大,可能是协议封装有问题
我的习惯: 先用 Profiler 的“Record”功能录制一段 30 秒的推流过程,然后回放分析。重点关注“Memory”面板里的“Allocations”曲线,如果出现锯齿状波动,说明有大量临时对象被创建和回收,需要优化。

四、实战:一次完整的推流调试流程

说了这么多,咱们串起来走一遍。假设你现在遇到一个问题:推流出去的画面每隔几秒就卡一下。

第一步,用 OBS 推同样的流到服务器,VLC 拉流看是否卡顿。如果不卡,说明问题在 Android 端。

第二步,打开日志系统,看有没有 WARN 级别的日志。比如“缓冲区将满”或者“丢帧”。如果有,说明编码速度跟不上。

第三步,用 Systrace 抓 trace,看编码线程和渲染线程的时间线。如果编码线程每帧耗时超过 33ms,那就是编码器瓶颈。

第四步,用 Profiler 看 CPU 和内存。如果 CPU 使用率忽高忽低,或者 GC 频繁,那就是系统资源竞争导致的卡顿。

你看,这样一层层排查下来,问题基本就定位了。我当年第一次做推流器时,遇到卡顿问题,像个无头苍蝇一样乱改参数,改了一周都没解决。后来学会用这些工具,半天就找到了根因——是网络模块里一个锁竞争导致的线程阻塞。

避坑指南: 我曾经在调试时犯过一个低级错误——在 Release 包上打日志。Release 包默认关闭了日志输出,我折腾了两小时才发现。所以,调试时一定要用 Debug 包,或者手动在代码里控制日志开关。

好了,这一章的内容就到这里。工具和方法都给你了,剩下的就是多练。推流器的调试没有捷径,但有了这些工具,你至少不会在黑暗中摸索。


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