FLV_PLAYBACK_ANALYSIS.md 4.5 KB

FLV播放问题分析和解决方案

问题描述

项目中播放FLV流 https://devflytopull.codroner.com/live/flytodev-stream-7CTDL9K00A0121.flv 时出现播放慢或无法播放的问题。

问题分析

1. FLV流本身正常

通过测试脚本验证,FLV流可以正常访问:

  • 响应时间:320ms
  • 平均速度:233KB/s
  • 内容类型:video/x-flv
  • FLV文件头正确

2. Android项目中的问题

2.1 播放器配置过于激进

原问题

  • 缓冲区设置过小(256KB)
  • 探测大小过小(16字节)
  • 分析时间过短(50ms)
  • 超时时间过短(1秒)
  • 禁用了所有缓冲机制

解决方案

// 使用更合理的缓冲设置
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "max-buffer-size", "1024000"); // 1MB
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", "50000"); // 50KB
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzeduration", "100000"); // 100ms
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", "5000000"); // 5秒
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "stimeout", "5000000"); // 5秒

// 启用缓冲机制
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 1);
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "sync-av-start", 1);
ijkPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 1);

2.2 Surface创建时机问题

原问题

  • 在Surface创建前就调用了prepareAsync()
  • 可能导致播放器准备失败

解决方案

// 在Surface创建后再开始准备
@Override
public void surfaceCreated(@NonNull SurfaceHolder holder) {
    ijkPlayer.setDisplay(holder);
    if (!playerObj.isPlayerPlaying()) {
        ijkPlayer.prepareAsync();
    }
}

2.3 缺少错误处理和重试机制

原问题

  • 播放错误时没有重试机制
  • 错误信息不够详细

解决方案

// 添加重试机制
private void retryConnection(ChannelPlayerObj playerObj) {
    new Thread(() -> {
        try {
            Thread.sleep(2000); // 等待2秒后重试
            if (getActivity() != null) {
                getActivity().runOnUiThread(() -> {
                    try {
                        IjkMediaPlayer ijkPlayer = playerObj.getIjkPlayer();
                        if (ijkPlayer != null) {
                            ijkPlayer.reset();
                            ijkPlayer.setDataSource(playerObj.getCurrentPlayingUrl());
                            ijkPlayer.prepareAsync();
                        }
                    } catch (Exception e) {
                        LogUtil.e("重试连接失败: " + e.getMessage());
                    }
                });
            }
        } catch (InterruptedException e) {
            LogUtil.e("重试连接被中断: " + e.getMessage());
        }
    }).start();
}

修复内容

1. 优化播放器配置

  • 增加缓冲区大小到1MB
  • 增加探测大小到50KB
  • 增加分析时间到100ms
  • 增加超时时间到5秒
  • 启用包缓冲和音视频同步
  • 禁用低延迟模式以提高稳定性

2. 修复Surface创建时机

  • 确保在Surface创建后再设置播放器显示
  • 在Surface创建后再调用prepareAsync()

3. 添加重试机制

  • 播放错误时自动重试
  • 2秒延迟后重新连接
  • 详细的错误日志记录

4. 改进日志记录

  • 添加详细的时间戳记录
  • 记录每个步骤的耗时
  • 便于问题定位和性能分析

测试工具

1. Python测试脚本

创建了 test_flv_stream.py 用于测试FLV流的可访问性:

  • HEAD请求测试
  • GET请求测试
  • FLV文件头验证
  • 流式读取测试

2. Android测试Activity

创建了两个测试Activity:

  • FlvTestActivity:完整的FLV测试界面
  • SimpleFlvTestActivity:简化的测试界面

建议

1. 网络优化

  • 确保设备网络连接稳定
  • 考虑使用CDN加速
  • 监控网络带宽使用

2. 播放器优化

  • 根据设备性能调整缓冲设置
  • 考虑使用ExoPlayer作为备选方案
  • 添加播放质量自适应

3. 错误处理

  • 添加网络状态监听
  • 实现播放质量监控
  • 提供用户友好的错误提示

预期效果

修复后应该能够:

  1. 正常播放FLV流
  2. 减少播放延迟
  3. 提高播放稳定性
  4. 自动处理网络异常
  5. 提供详细的调试信息

验证方法

  1. 运行测试脚本验证FLV流可访问性
  2. 使用测试Activity验证播放功能
  3. 查看日志确认播放器状态
  4. 测试网络异常情况下的重试机制