Android 视频播放卡顿检测——帧率之外的第二战场

gfxinfo 显示 FPS = 60,UI 流畅度满分。但用户投诉:"视频播放时一顿一顿的"。

你查了半天帧耗时数据,全是正常帧。问题出在哪?

答案:视频帧和 UI 帧是两条完全独立的管线。gfxinfo 只统计 UI 帧,视频帧走的是 MediaCodec → Surface 的解码通道。你采的是 A 的数据,用户投诉的是 B 的问题。


一、视频帧 vs UI 帧:两条管线

Android 里有两种"帧",走不同的渲染通道,采集方式也完全不同:

css 复制代码
┌─────────────────────────────────────────────────────┐
│  UI 帧管线                                           │
│                                                     │
│  Choreographer → UI 线程 → RenderThread → Surface A  │
│                                                     │
│  帧率上限 = 屏幕刷新率(60/90/120Hz)                   │
│  数据源 = dumpsys gfxinfo                             │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│  视频帧管线                                           │
│                                                     │
│  网络/文件 → 解封装 → MediaCodec 解码 → Surface B      │
│                                                     │
│  帧率 = 视频源帧率(24/25/30/60fps)                   │
│  数据源 = SurfaceFlinger(通用)/ media.codec(辅助)   │
└─────────────────────────────────────────────────────┘

两个 Surface 最终都交给 SurfaceFlinger 合成到屏幕上。
                                  ↑
                 这是检测视频卡顿的关键切入点
维度 UI 帧 视频帧
触发方式 VSYNC 信号 + 界面变化 视频流的帧间隔
帧率上限 屏幕刷新率 视频编码帧率
渲染者 App 的 RenderThread MediaCodec 硬/软解码器
卡顿原因 布局复杂、主线程阻塞 解码慢、buffer 不足、网络卡、音画同步
采集工具 dumpsys gfxinfo SurfaceFlinger(最通用)
采集时机 始终采集 仅在视频播放场景启用

二、残酷的现实:主流 App 几乎绕过了标准播放器 API

很多文章推荐用 dumpsys media.player 来检测视频卡顿。但在实际测试中,这个命令对主流视频 App 无效

Android 标准路径

markdown 复制代码
App → android.media.MediaPlayer API → MediaPlayerService → 解码 → Surface
                                           ↑
                           dumpsys media.player 采数据的位置

主流 App 的实际路径

css 复制代码
抖音     → TTVideoEngine(字节自研引擎)→ MediaCodec → Surface
快手     → KSVideoPlayer(自研引擎)   → MediaCodec → Surface
爱奇艺   → 自研播放器引擎             → MediaCodec → Surface
腾讯视频 → TXLiteAVSDK(自研引擎)    → MediaCodec → Surface
B站      → IJKPlayer(FFmpeg 魔改)   → MediaCodec / FFmpeg → Surface
优酷     → 阿里自研引擎               → MediaCodec → Surface

这些 App 都绕过了 android.media.MediaPlayer APIdumpsys media.player 对它们无效。

但不管用什么播放器引擎,解码后的视频帧最终都必须提交给 SurfaceFlinger 合成上屏。SurfaceFlinger 是所有视频帧的必经之路:

markdown 复制代码
   任何播放器引擎
         │
    ┌────┴────┐
    │ 硬解码   │  软解码
    │MediaCodec│  FFmpeg
    └────┬────┘  ┘
         │      │
    ┌────┴──────┴────┐
    │    Surface     │ ← 所有视频帧必经之路
    └────────┬───────┘
             │
    ┌────────┴───────┐
    │ SurfaceFlinger │ ← 在这里截获帧时间戳
    └────────┬───────┘
             │
           屏幕

三、三种数据源:通用性对比

3.1 SurfaceFlinger --latency(主方案,通用)

原理:视频通过 SurfaceView 渲染时,SurfaceFlinger 记录每帧的上屏时间戳。通过分析相邻帧的时间差,可以检测丢帧和卡顿。

操作方法

  1. 播放视频后,通过 dumpsys SurfaceFlinger --list 查找目标 App 的 SurfaceView layer
  2. 对该 layer 执行 dumpsys SurfaceFlinger --latency,获取最近 ~128 帧的时间戳
  3. 提取每帧的 actualPresentTime(第 2 列,实际上屏时间),过滤掉无效帧(0x7FFFFFFFFFFFFFFF 表示未上屏)
  4. 计算相邻帧时间差 → 得到帧间隔序列
  5. 从帧间隔序列推导所有视频性能指标

输出格式说明

内容 说明
第 1 行 16666666 屏幕刷新周期(纳秒),16666666 = 60Hz
后续每行 3 列纳秒时间戳 第 1 列:desiredPresentTime(期望上屏时间);第 2 列:actualPresentTime(实际上屏时间);第 3 列:frameReadyTime(帧就绪时间)

一个关键限制------SurfaceView vs TextureView

渲染方式 SurfaceFlinger 能分离视频帧吗 使用场景
SurfaceView (独立 layer) 大部分全屏视频播放
TextureView 不能(和 UI 共享 Surface) 部分小窗播放、弹幕叠加

判断方法 :播放视频后,查看 dumpsys SurfaceFlinger --list 是否出现 SurfaceView[包名/...] 的 layer。有 → SurfaceView,没有 → TextureView。

3.2 dumpsys media.codec(辅助方案)

原理 :大部分 App 使用 MediaCodec API 硬件解码,该命令提供解码器级统计。

能提供什么

信息 说明
解码器名称 判断硬解(OMX.qcom. / c2.qti.)还是软解(OMX.google. / c2.android.
丢弃帧数 output buffers dropped(部分设备可用)
平均/最大解码耗时 判断解码性能是否足够(部分设备可用)

局限:纯 FFmpeg 软解码不走 MediaCodec,此时无数据。字段名和格式随 Android 版本差异大。

3.3 dumpsys media.player(有限场景)

适用范围极窄 ------只有使用 android.media.MediaPlayer 原生 API 的 App 才有数据。

播放器 是否有效
系统原生 MediaPlayer 有效
自研 App(确认用原生 API) 有效
抖音 / 快手 / 爱奇艺 / B站 无效
IJKPlayer / ExoPlayer 无效

3.4 三种方案总览

能力 SurfaceFlinger media.codec media.player
主流 App 通用性 全覆盖 大部分 极少数
帧间隔序列
丢帧数/丢帧率 (从帧间隔推导)
帧间隔 CV
连续丢帧检测
视频实际帧率 间接 间接
解码耗时
解码方式(硬/软)
TextureView 场景 不可用 可用 看实现

推荐策略:SurfaceFlinger 为主 + media.codec 为辅。SurfaceFlinger 提供帧级时间戳分析,media.codec 提供解码性能数据,两者互补。


四、SurfaceFlinger 帧间隔分析方法

SurfaceFlinger 输出的原始数据是纳秒时间戳序列,核心分析方法是从时间戳 → 帧间隔 → 指标

4.1 从时间戳到帧间隔

scss 复制代码
SurfaceFlinger 输出的 actualPresentTime 序列(纳秒):
  T1, T2, T3, T4, T5, ...

帧间隔序列(毫秒):
  (T2−T1)/1000000, (T3−T2)/1000000, (T4−T3)/1000000, ...

以 30fps 视频为例(理想帧间隔 = 1000 / 30 = 33.3ms):

markdown 复制代码
实际帧间隔序列(ms):
  33.2, 33.4, 33.1, 33.5, 33.2, 66.8, 33.3, 33.4, 33.1, 33.5, ...
                                   ↑
                         66.8ms ≈ 2× 理想间隔 → 丢了 1 帧

4.2 丢帧判定规则

帧间隔 > 1.5× 理想间隔 → 判为丢帧

为什么是 1.5 倍而不是 1.0 倍?因为即使正常播放,帧间隔也有轻微波动。1.5 倍留出合理容差:

视频帧率 理想间隔 丢帧阈值(1.5×) 含义
24fps 41.7ms 62.5ms 间隔 > 62.5ms 视为丢帧
30fps 33.3ms 50.0ms 间隔 > 50.0ms 视为丢帧
60fps 16.7ms 25.0ms 间隔 > 25.0ms 视为丢帧

4.3 从帧间隔推导丢帧数量

scss 复制代码
帧间隔 66.8ms,理想间隔 33.3ms

丢帧数 = round(66.8 / 33.3) − 1 = round(2.0) − 1 = 1 帧

帧间隔 133.6ms,理想间隔 33.3ms

丢帧数 = round(133.6 / 33.3) − 1 = round(4.0) − 1 = 3 帧

4.4 连续丢帧检测

丢帧率相同,但分布不同,体验天差地别:

css 复制代码
场景 A:1000 帧中,10 个不同位置各丢 1 帧
  丢帧率 = 1%,卡顿 10 次,每次 33ms
  用户感受:轻微、分散,可能不注意

场景 B:1000 帧中,1 个位置连续丢 10 帧
  丢帧率 = 1%,卡顿 1 次,持续 333ms
  用户感受:明显冻帧,一定会投诉

方法 :遍历帧间隔序列,记录连续超阈值的最大长度。最大连续丢帧数直接决定用户感受到的最严重卡顿。

4.5 注意事项

  1. 过滤无效时间戳0x7FFFFFFFFFFFFFFF(INT64_MAX)表示帧尚未上屏,必须过滤掉
  2. 过滤异常大间隔:帧间隔 > 5000ms 通常是暂停/切后台,不算卡顿
  3. 视频帧率自动检测:无需手动指定视频帧率。先采集一段数据,取帧间隔的中位数,然后匹配最近的标准帧率(24/25/30/48/50/60fps)作为 expected_fps。这样同一个工具可以自动适配不同帧率的视频源
  4. buffer 上限与去重 :SurfaceFlinger 最多保留 ~128 帧,且 --latency 不会被 reset 清空 ------每次调用返回的是最近 128 帧的完整缓冲区。因此必须记录上一轮最后时间戳,过滤已处理的旧帧,否则同一帧会被重复计数。采集间隔建议:30fps 视频 ≤ 4 秒,60fps 视频 ≤ 2 秒
  5. 多 Layer 遍历:视频播放时可能存在多个 SurfaceView(如视频 + 弹幕),应遍历所有匹配包名的 layer,取帧数最多的作为视频指标

五、完整指标体系

本节定义 10 个视频质量指标。5.1 / 5.2 讲解各指标的定义和计算方式,所有判定阈值统一汇总在 5.3 的检查清单中(含行业标准对照)。

5.1 核心指标(SurfaceFlinger 可直接获取)

指标 1:视频丢帧率

erlang 复制代码
丢帧率 = 帧间隔超阈值的帧数 / 总帧数 × 100%

指标 2:视频帧率达成率

yaml 复制代码
实际帧率 = 1000 / 帧间隔均值(ms)
帧率达成率 = 实际帧率 / 源帧率 × 100%

指标 3:帧间隔 CV(变异系数)

ini 复制代码
CV = 帧间隔标准差 / 帧间隔均值

和 UI 帧的 CV(#12 第五节)概念一致,但参考基准不同:

  • UI 帧的理想间隔 = VSYNC 周期(屏幕刷新率决定)
  • 视频帧的理想间隔 = 视频源帧间隔(编码帧率决定)

指标 4:最大连续丢帧数 & 最大卡顿时长

指标 计算方式 含义
最大连续丢帧数 连续超阈值帧间隔的最大长度 最严重一次冻帧持续几帧
最大卡顿时长 最大帧间隔值(ms) 最长一次画面停顿多久
卡顿次数 超阈值帧间隔的总次数 发生了几次画面不连续

判定标准(完整四级阈值见 5.3 检查清单):

指标 优秀 良好 警告 严重
最大连续丢帧 ≤ 1 帧 ≤ 3 帧 4 ~ 6 帧 > 6 帧
最大卡顿时长 < 50ms < 100ms 100 ~ 200ms > 200ms
卡顿次数 / 分钟 ≤ 1 ≤ 3 4 ~ 6 > 6

5.2 辅助指标

指标 5:首帧时间(First Frame Latency)

用户点击播放到第一帧画面渲染到屏幕的延迟。

采集方法:记录操作时间 T0,播放后轮询 SurfaceFlinger,第一个有效帧时间戳 T1 出现时,首帧时间 = T1 − T0。

指标 6:解码耗时(需 media.codec)

指标 阈值建议 说明
平均解码耗时 < 视频帧间隔 × 50% 30fps → 平均 < 16.7ms
P90 解码耗时 < 视频帧间隔 × 80% 30fps → P90 < 26.7ms
最大解码耗时 < 视频帧间隔 30fps → 最大 < 33.3ms

从解码器名称判断解码方式

前缀 解码方式 性能
OMX.qcom. / OMX.mtk. / c2.qti. 硬件解码 快,功耗低
OMX.google. / c2.android. 软件解码 慢,依赖 CPU

指标 7:音画同步偏移(A/V Sync)

国际标准 ITU-R BT.1359 定义了音视频同步的可感知和可接受阈值。人耳对"声音先于画面"的容忍度远低于 "声音滞后于画面",因此标准阈值是不对称的

偏移方向 可感知阈值 可接受阈值 说明
音频提前(声先于画) +45ms +90ms 人眼更敏感,容忍度低
音频滞后(画先于声) −125ms −185ms 容忍度相对高

简化参考(测试实用):偏移 ±20ms 以内无感知;±40ms 敏感用户可察觉;±80ms 普通用户注意到唇形对不上;> ±120ms 明显不同步。蓝牙耳机场景最容易出问题(见场景 5)。

指标 8:Buffer 健康度(网络视频)

指标 含义 数据来源
Buffering 次数 buffer 耗尽导致播放暂停的次数 logcat 关键词:buffering / underrun / empty
Buffering 总时长 累计等待数据的时间 logcat / 播放器回调

指标 9:Seek 延迟

Seek 延迟 用户感知
< 100ms 即时响应
100~300ms 轻微延迟
> 300ms 明显等待

5.3 统一判定标准 & 检查清单

所有指标的判定阈值汇总如下。指标 1~5 是必检项,来自 SurfaceFlinger,通用性高;指标 6~10 按场景选检。

核心指标(必检)

# 指标 数据源 优秀 良好 警告 严重(红线)
1 视频丢帧率 SurfaceFlinger < 0.1% 0.1% ~ 1% 1% ~ 3% > 3%
2 帧率达成率 SurfaceFlinger ≥ 95% 80% ~ 95% 60% ~ 80% < 60%
3 帧间隔 CV SurfaceFlinger < 0.1 0.1 ~ 0.3 0.3 ~ 0.6 > 0.6
4 最大连续丢帧 SurfaceFlinger ≤ 1 帧 ≤ 3 帧 4 ~ 6 帧 > 6 帧
5 最大卡顿时长 SurfaceFlinger < 50ms 50 ~ 100ms 100 ~ 200ms > 200ms

辅助指标(按场景选检)

# 指标 数据源 优秀 良好 警告 严重(红线)
6 首帧时间 SurfaceFlinger < 200ms 200 ~ 500ms 500ms ~ 1s > 1s
7 解码耗时 media.codec < 帧间隔 × 50% < 帧间隔 × 80% < 帧间隔 > 帧间隔
8 A/V 同步偏移 logcat / 播放器 ±20ms ±40ms ±80ms > ±120ms
9 Buffer 健康度 logcat / 播放器 0 次暂停 ≤ 1 次 2 ~ 3 次 > 3 次
10 Seek 延迟 SurfaceFlinger < 100ms 100 ~ 200ms 200 ~ 300ms > 300ms

5.4 行业标准对照

我们的阈值不是拍脑袋定的,参考了以下行业标准和工具:

标准 / 工具 领域 核心内容 和我们的关系
PerfDog(腾讯) 移动端性能 视频播放推荐 Jank = 0;Jank 判定采用"前 3 帧均值 × 2 + 固定阈值"双条件 丢帧率 < 0.1%(优秀)对应 PerfDog 的"接近零 Jank"
W3C VideoPlaybackQuality Web 视频 droppedVideoFrames / totalVideoFrames > 10% 触发质量降级 我们的红线(3%)严于 W3C 的 10%,面向高品质产品
ITU-R BT.1359 音视频同步 A/V 可感知:音频提前 +45ms / 滞后 −125ms;可接受:+90ms / −185ms 指标 8 直接对齐该标准
ITU-T P.1203 流媒体 QoE 基于 MOS(1-5 分)的自适应流质量评估,综合卡顿、启动、质量波动 我们的指标覆盖了 P.1203 关注的核心维度
Akamai QoE 流媒体 每次 rebuffering 降低 14% 满意度;启动超 2s 用户开始流失 首帧 < 200ms + Buffer 0 次暂停与其一致
ExoPlayer Analytics Android 播放器 提供 maxConsecutiveDroppedFrames,可配置通知阈值,无固定标准 我们给出了具体的连续丢帧四级标准

一句话总结 :我们的阈值整体严于 W3C(10%)和 ExoPlayer(无固定标准),对齐 PerfDog 和 ITU-R 标准,面向高品质产品。帧间隔 CV 是我们的特色指标,PerfDog / Perfetto 均未提供。


六、数据源可用性验证流程

拿到任何 App,先做一轮数据源验证:

vbnet 复制代码
Step 1:启动 App 并播放视频

Step 2:检查 SurfaceFlinger 是否可用
  → 执行 dumpsys SurfaceFlinger --list,搜索 SurfaceView
  → 有 SurfaceView layer → SurfaceFlinger 方案可用(最佳)
  → 无 SurfaceView layer → App 用 TextureView 渲染,降级到 Step 3

Step 3:检查 media.codec 是否可用
  → 执行 dumpsys media.codec,搜索 codec / drop / decode
  → 有解码器数据 → media.codec 可用
  → 无数据 → 纯软解码,回到 SurfaceFlinger(大部分场景仍可用)

Step 4:检查 media.player(大概率无效,但值得一试)
  → 执行 dumpsys media.player,搜索 numFrames
  → 有数据 → 额外数据源可用
  → 无数据 → 符合预期,主流 App 不走这条通道

实测兼容性(全屏 SurfaceView 播放)

App SurfaceFlinger media.codec media.player
抖音 可用 可用 不可用
快手 可用 可用 不可用
爱奇艺 可用 可用 不可用
腾讯视频 可用 可用 不可用
B站 可用 可用(硬解时) 不可用
微信视频号 可用 可用 不可用
自研 App(MediaPlayer) 可用 可用 可用
自研 App(ExoPlayer) 可用 可用 不确定

七、常见视频卡顿场景 & 诊断方法

场景 1:硬解码器繁忙

现象:多路视频同时播放(如信息流),部分视频卡顿。

原因:手机硬件解码器数量有限(通常 4~8 路),超出后降级为软解码,CPU 负担加重。

复制代码
硬解码:4.2ms/帧 → 远低于 33.3ms → 流畅
软解码:25.8ms/帧 → 接近 33.3ms → 容易掉帧
CPU 降频后的软解码:42ms/帧 → 超过 33.3ms → 必然掉帧

诊断 :通过 media.codec 查看解码器名称,OMX.google. / c2.android. 开头 = 软解。

场景 2:分辨率切换冻帧

现象:网络视频切换清晰度(360p → 1080p)时短暂冻帧。

原因:分辨率切换需要重建解码器,200~500ms 间隙。

SurfaceFlinger 表现:帧间隔序列中出现一个 200~500ms 的异常间隔,前后帧间隔正常。

场景 3:网络 buffering

现象:网络视频播放,帧率忽高忽低。

原因:网络带宽不足,解码器输入 buffer 空了。

视频规格 带宽需求参考
30fps 1080p H.264 ≈ 5~8 Mbps
30fps 4K H.265 ≈ 15~25 Mbps
60fps 1080p H.264 ≈ 10~15 Mbps

SurfaceFlinger 表现:帧间隔序列中出现间歇性的大间隔(数百毫秒),夹杂正常间隔。CV 飙高。

场景 4:CPU 降频导致软解码变慢

现象:长时间播放后越来越卡。

原因:设备发热后 CPU 降频,软解码器算力不足(参考 CPU 系列 #7)。

诊断:交叉分析 CPU 频率比(趋势下降)和 SurfaceFlinger 帧间隔 CV(趋势上升)。

场景 5:A/V 同步异常(蓝牙耳机)

现象:连接蓝牙耳机后,视频声音和画面对不上。

蓝牙编码 固有延迟 说明
SBC 170~270ms 默认编码,延迟最高
AAC 120~200ms iOS 常用,Android 上延迟偏高
aptX 100~250ms 标准 aptX,中等延迟
aptX Low Latency < 40ms 游戏/视频专用,需耳机支持
LDAC 200~250ms 追求音质,延迟最高之一
LC3(LE Audio) 20~40ms 新一代蓝牙低延迟标准

场景 6:帧率与刷新率不匹配(Judder)

现象 :24fps 电影在 60Hz 屏幕上有轻微"抖动感",但不丢帧

原因:24 不能整除 60,每帧显示时长不均匀(3:2 pulldown)。

复制代码
24fps 在 60Hz :每帧交替显示 3 或 2 个 VSYNC → 帧间隔交替 50ms/33ms → judder
24fps 在 120Hz:每帧固定显示 5 个 VSYNC → 帧间隔恒定 41.7ms → 无 judder
30fps 在 120Hz:每帧固定显示 4 个 VSYNC → 帧间隔恒定 33.3ms → 无 judder

SurfaceFlinger 表现:帧间隔交替出现两种值,丢帧率 = 0%,但 CV 偏高(> 0.2)。

识别方法:丢帧率正常 + CV 偏高 + 帧间隔呈规律性交替 → 大概率是 Judder,不是 bug。


八、与 UI 帧率的联动分析

视频播放和 UI 交互往往同时发生(边看视频边滑评论),需要同时采集两路数据。

联合诊断决策表

症状 UI 帧率 视频帧间隔 CPU 频率比 可能原因 排查方向
UI 卡,视频不卡 CV 正常 正常 UI 线程阻塞 帧耗时阶段拆解(#12)
UI 不卡,视频卡 正常 CV 高 / 丢帧多 正常 解码器瓶颈 / buffer 不足 media.codec 解码耗时
都卡 CV 高 CPU 降频,整机算力不足 CPU 频率比趋势(#7)
都卡 CV 高 正常 CPU 被占满 top / CPU 核心利用率(#8)
都不卡,但音画不同步 正常 CV 正常 正常 蓝牙延迟 / 同步逻辑 bug 蓝牙编码类型、播放器日志
都不卡,但画面抖 正常 CV 偏高 正常 帧率/刷新率不整除 确认 Judder(场景 6)

采集频率建议

数据 采集方式 建议间隔
UI 帧率 + 卡顿 dumpsys gfxinfo 1~2 秒
视频帧间隔 SurfaceFlinger --latency 2~4 秒
解码统计 dumpsys media.codec 5~10 秒
CPU 频率/负载 /proc/stat + cpufreq 5~10 秒

九、不同场景的指标优先级

不同视频场景关注的指标不同:

场景 必检指标 辅助指标 可忽略
本地视频播放 丢帧率、CV、最大连续丢帧 解码耗时 Buffer、Seek
短视频(抖音/快手) 首帧时间、Seek 延迟、丢帧率 Buffer A/V 同步
长视频(爱奇艺/腾讯) 丢帧率、A/V 同步、CV Buffer Seek
直播 Buffer 健康度、丢帧率、首帧时间 CV Seek
多路视频(信息流) 丢帧率、解码方式(硬/软) CPU 负载 A/V 同步、Seek

短视频 最核心的指标是首帧时间------用户刷视频时,每个视频都有一次首帧加载。首帧慢 = 每刷一个视频都卡一下。


小结

知识点 一句话
核心问题 gfxinfo 只采 UI 帧,采不到视频帧------两条独立管线
通用方案 SurfaceFlinger --latency 是唯一真正通用的视频卡顿检测方案
原理 不管什么播放器,视频帧最终都提交到 Surface → SurfaceFlinger 上屏
SurfaceFlinger 限制 TextureView 渲染场景无法分离视频帧,需降级 media.codec
media.player 对抖音/快手/爱奇艺等主流 App 无效
分析方法 时间戳 → 帧间隔序列 → 丢帧/CV/连续丢帧/实际帧率
必检指标 丢帧率、帧率达成率、CV、最大连续丢帧、最大卡顿时长
判定标准 四级分档(优秀/良好/警告/严重),对齐 PerfDog、ITU-R BT.1359 等行业标准
和 UI 的关系 视频帧 + UI 帧 + CPU 数据三路联合诊断

下一篇我们把 FPS 系列所有指标整合到一起,给出完整的采集落地方案------从脚本架构到自动化报告。


系列目录

  • 第 1~4 篇:内存泄漏检测 & 内存采集避坑
  • 第 5~9 篇:CPU 采集系列(入门 → 避坑 → 降频 → 单核 → 落地)
  • 第 10 篇:FPS 帧率采集入门
  • 第 11 篇:FPS 采集的 8 个坑
  • 第 12 篇:UI 卡顿量化------用数据回答"到底有多卡"
  • 第 13 篇(本篇):视频播放卡顿检测
  • 第 14 篇(下一篇):FPS 采集落地方案

我是测试工坊,专注 Android 系统级性能工程。 如果你也在做帧率相关的性能测试,欢迎评论区交流 👇 关注我,后续更新不迷路。

相关推荐
Kapaseker6 小时前
一杯美式深入理解 data class
android·kotlin
鹏多多6 小时前
Flutter使用screenshot进行截屏和截长图以及分享保存的全流程指南
android·前端·flutter
Carson带你学Android6 小时前
OpenClaw移动端要来了?Android官宣AI原生支持App Functions
android
黄林晴6 小时前
Android 删了 XML 预览,现在你必须学 Compose 了
android
三少爷的鞋6 小时前
Android 面试系列 | 内存泄露:从"手动配对"到"架构自愈"
android
恋猫de小郭6 小时前
什么 AI 写 Android 最好用?官方做了一个基准测试排名
android·前端·flutter
louisgeek16 小时前
Android MediatorLiveData
android
锋风1 天前
远程服务器运行Android Studio开发aosp源码
android
测试工坊1 天前
Android UI 卡顿量化——用数据回答"到底有多卡"
android