Android智能猫砂盆视频加载慢卡顿问题分析

Android智能猫砂盆视频加载慢卡顿问题分析

1.参考文档:

help.aliyun.com/zh/document...

2.SDK自身卡顿原因:

2.1 为什么首帧时间大

如果设备正常响应强制I帧指令(以办公室的WiFi为例),设备响应强制I帧耗时300ms以内的话,一般首帧的延迟应在1.5秒以内。

首帧耗时= 请求播放地址耗时(300ms)+连接播放地址耗时(150ms)+等待设备I帧耗时(300ms)+播放器内部缓冲延迟(200ms)+解码渲染耗时(10ms)

导致首帧延迟时间大的原因主要有以下两种情况。

  • 设备未正常响应强制I帧指令时,会增加一个GOP长度的延迟,此时您需要使设备正常响应强制I帧指令。
  • 设备端连接推流地址耗时大,此时请通过控制台右上角的工单联系我们。

2.2 为什么直播播放卡顿

产生播放卡顿、画面跳帧的原因主要有以下几种情况。

  • 设备SDK缓冲区设置过小

    Link Visual设备端SDK提供码流比特率设置接口,SDK内部会通过传入的比特率换算并设置缓冲区大小,若码流比特率设置过小,会导致设备端SDK缓冲区频繁触发丢包,从而影响画面质量。此时建议您重新设置合适的SDK缓冲区。

    说明

    Link Visual目前不支持帧大小超过512KB的码流传输。

  • 设备网络不佳

    若设备所处网络上行带宽不足以支持设定的码流传输,会引起设备端SDK缓冲区频繁丢包,从而影响画面质量。建议您调整设备位置或者检查设备网络状态。

  • 播放端网络不佳

    播放端所处下行网络带宽至少需要大于当前码流,播放器提供获取码流的接口可以用来展示当前实际码流信息。请检查播放端网络带宽是否符合要求,并建议您展示当前码流(建议码流展示样式为:24fps 80KB/s),便于以后定位问题。

  • 码流问题

    Link Visual不支持B帧,H264建议使用BaseLine/Main Profile。

    最大码流与清晰度对照表如下。

    编码格式 分辨率 最大码流
    H264 1080P <2Mbps
    720P <1Mbps
    D1 <0.5Mbps
    H265 1080P <1.5Mbps
    720P <0.75Mbps
    D1 <0.5Mbps
  • 解码耗时大

    当编码复杂或帧超大引起解码耗时大,进而引起播放器主动丢帧,导致画面卡顿,此时建议您降低设备编码复杂度和码流大小。

  • 设备时间戳异常

    前后两帧之间PTS/DTS差值应与实际编码器生成帧时时间戳差值保持一致。

    • 若Link Visual的时间戳两帧之间差值比实际大,会引起播放端解码器延迟解码,可能会触发播放器缓冲区溢出丢帧,引起画面慢放和画面卡顿。
    • 若Link Visual的时间戳两帧之间差值比实际小,会引起播放端解码器提前解码,引起画面快放。

说明

推荐您使用设备端SDK提供的码流自检功能做时间戳检查。

直播播放断开

产生播放过程中画面静止一段时间后报错的原因主要如下。

  • 设备推流异常

    设备因网络断开或者程序bug引起推流突然中断,若非网络引起,需要结合设备端日志进行分析,排除bug。

  • 播放端网络不佳

播放器若持续一段时间都未能拉到流或者检测到网络断开会往上层抛出错误,属于正常现象。

说明

对于播放端拉流错误(1100),建议App在实现时主动做1-2次的重试逻辑,若仍失败则呈现给用户重试。

设备端的设置需要设备进行排查

3.App卡顿和加载慢原因分析:

3.1 没有设置播放器固定缓存帧数

arduino 复制代码
/**
 *设置播放器固定缓存帧数
 *@param frameCount 播放器固定缓存帧数,取值范围:0帧~50帧,数值越大播放器延迟越   大,流畅性越好,默认5帧
 */
void setBufferedFrameCount(int frameCount);

3.2 没有设置播放器抗抖动最大缓冲区时长

arduino 复制代码
 /**
   * 设置播放器抗抖动最大缓冲区时长,默认1000ms,范围200-3000ms
   * @param jitterBufferSizeInMs
   */
  void setMaxJitterBufferSizeInMs(int jitterBufferSizeInMs);

3.3 没有设置播放停止时画面

如果不设置此模式默认播放停止时下次进来始终是显示黑色

java 复制代码
/**
 * 设置播放停止时画面绘制策略
 * @param playerStoppedDrawingMode
 * ALWAYS_KEEP_LAST_FRAME          播放停止时始终保留最后一帧画面
 * KEEP_LAST_FRAME_WITHOUT_ERROR   播放停止时只有未出现错误时才保留最后一帧画面(默认是此模式) 
 * ALWAYS_BLACK                    播放停止时始终显示黑色
 */
void setPlayerStoppedDrawingMode(PlayerStoppedDrawingMode playerStoppedDrawingMode)

3.4 播放失败重试机制错误:

  • Android播放失败是延迟5s后重新初始化,如果网络不好会一直初始化
  • 一直重复初始化比较消耗资源,需要及时关闭回收播放器
  • sdk文档给出建议是添加2次重连,而不是一直初始化

3.5 初始化和关闭界面资源回收策略:

  • 初始化时设置播放器固定缓存帧数
  • 设置播放器抗抖动最大缓冲区时长
  • 在创建播放器前回收之前的资源
  • 关闭界面回收资源
  • 添加是否初始化变量防止重复初始化

3.6 修改设置播放器数据源时机:

  • 在前面的准备工作做完之后再设置数据源
  • 不要在最开始设置数据源

4.修改动画加载:

  • 只有在加载buffer时才显示loading动画
  • 其他状态隐藏动画
  • 不要因为播放器状态问题一直加载loading
typescript 复制代码
            @Override
            public void onPlayerStateChange(LVPlayerState state) {
                switch (state) {
                    case STATE_BUFFERING:
                        binding.loading.setVisibility(View.VISIBLE);
                        break;
                    case STATE_READY:
                    case STATE_IDLE:
                    case STATE_ENDED:
                        binding.loading.setVisibility(View.GONE);
                        break;
                }
            }

5.优化后的时间统计和效果:

目前测试了20次,视频加载时间均值在1.2s

直播暂停时一直有画面不会黑屏:

6.总结

6.1、设备硬件 & 推流端根源

  1. 首帧延迟偏高

    • 设备没有及时响应强制 I 帧指令,多出一个 GOP 等待耗时;

    • 设备连接推流地址耗时过长。

    计算公式:首帧耗时 = 获取播放地址耗时 + 连接地址耗时 + 等待 I 帧 + 播放器缓冲 + 解码渲染耗时

  2. 缓冲区配置不合理SDK 缓冲区由设定码率换算而来,码率参数过小,缓冲区容量不足,上行码流溢出频繁丢包、花屏卡顿;同时单帧码流不可超过 512KB。

  3. 设备上行网络带宽不足上行带宽承载不住当前编码码流,持续发生丢包。

  4. 编码参数不符合 SDK 约束

    • H264 不能携带 B 帧,选用 Baseline / Main Profile;
    • 不同分辨率、编码格式存在上限码流,超出上限极易解码卡顿;
    • H265、高分辨率码流负载高,解码压力大引发播放器主动丢帧。
  5. 视频时间戳 PTS/DTS 异常

    • 帧间隔时间戳偏大 → 解码器堆积、缓冲区溢出、画面卡顿慢放
    • 帧间隔时间戳偏小 → 画面倍速快放可调用 SDK 码流自检功能校验时间戳。
  6. 设备端推流中断设备网络抖动断开、硬件程序异常,直接终止视频推流,App 播放画面静止后抛出错误。

6.2、播放端(App‑SDK 参数配置缺陷)

  1. 未手动限定播放器缓存帧数setBufferedFrameCount,缓冲帧数不合理,流畅度和延迟无法平衡;默认 5 帧,区间 0‑50 帧。
  2. 抗抖动缓冲区时长setMaxJitterBufferSizeInMs使用默认 1000ms,没有根据网络环境调整(可调范围 200‑3000ms),网络波动下容易卡顿。
  3. 停止播放画面策略未配置,默认出错之后黑屏;需要设置ALWAYS_KEEP_LAST_FRAME留存最后一帧画面,规避黑屏问题。

6.3、播放器生命周期、资源与初始化问题

  1. 播放器资源没有做好复用与回收,上一个播放实例未释放就新建实例,造成资源冲突、内存占用过高;
  2. 缺少初始化标记变量,播放器被多次重复初始化;
  3. 设置播放数据源时机错误:过早设置 DataSource,播放器准备流程错乱,拖慢首帧加载速度;正确顺序:配置缓冲参数 → 初始化播放器 → 最后设置播放地址。

6.4、异常重连重试逻辑缺陷

  1. 旧方案播放失败之后固定延迟 5 秒循环初始化播放器;
  2. 无限重试反复创建销毁播放器,CPU 资源消耗严重;
  3. 优化方案:仅限制 1‑2 次重连尝试,重试失败交由用户手动触发。

6.5、UI Loading 状态逻辑错误

loading 动画一直常驻显示,没有绑定播放器状态;优化:仅在STATE_BUFFERING缓冲加载阶段展示加载动画,就绪、空闲、播放结束状态隐藏 Loading。

6.6、最终优化成果

  1. 规范播放器初始化顺序、缓冲参数、抖动缓冲区、停播留帧配置;
  2. 管控播放器实例生命周期、防止重复初始化、做好资源回收;
  3. 限制播放失败重试次数,杜绝无限初始化;
  4. 绑定播放器状态控制 Loading 动画;
  5. 设备侧规范 I 帧推送、码流上限、H264 编码配置、PTS 时间戳;
  6. 实测 20 次首帧加载平均耗时下降至 1.2s,暂停播放可保留最后一帧,不再黑屏。
  7. 如果网络非常差或者没网的异常情况下不可避免,要么加缓存,但是这种直播推流实时性比较高的场景缓存也就失去意义.
相关推荐
只会cv的小前端2 小时前
七巧低代码服务端脚本使用方法
android·低代码·rxjava
3 小时前
Android 自定义 View 实战:从零打造工业级全向摇杆控件(OmniJoystickView)
android·kotlin·自定义view·摇杆控件
雨白3 小时前
深入理解 Kotlin 协程 (十一):以逸待劳,探秘 select 多路复用与并发安全策略
android·kotlin
hunterandroid5 小时前
[Android 从零到一] Android 深度链接与 App Links:从 URI Scheme 到可验证的应用跳转
android
我命由我123457 小时前
Jetpack Compose - Material Design 断点范围、WindowSizeClass、针对不同屏幕尺寸创建预览、四类导航栏
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
执明wa8 小时前
Android 开发中的设计模式入门:六大设计原则
android·设计模式
松仔log21 小时前
Java中级——组合和继承
android·java·开发语言
我命由我123451 天前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
lilian2331 天前
Harmony os 技术实战|拼豆制图06:收藏 ID、生成记录与重启恢复怎么不打架
android·java·数据库·harmonyos