使用just_audio和audio_service的HLS流音频播放器暂停超1分钟后无响应
解决方案
根因说明
故障由HLS流的原生特性触发:HLS服务端返回的分片通常带有有效期限制,暂停时间超过已缓冲时长后,已缓存的分片以及播放列表地址会过期失效,just_audio默认不会自动重新拉取最新的播放资源,直接进入idle状态,同时上层audio_service未处理该异常场景,导致锁屏控件无响应。
修复步骤
- 调整播放器缓冲配置,增加过期分片容错时长
修改AudioPlayer初始化参数,适配你的HLS分片有效时长:
final audioPlayer = AudioPlayer( bufferConfiguration: BufferConfiguration( // 按实际业务的HLS分片有效期调整,建议设置为分片有效期的1.5倍 maxStale: const Duration(seconds: 300), ), );
- 监听播放器状态,异常进入idle时自动恢复
增加processingState监听,区分用户主动停止和异常失效场景,自动重新加载音频源:
// 自行维护标记位,用户主动调用stop/ dispose时设为true bool isUserInitiatedStop = false; audioPlayer.processingStateStream.listen((state) async { if (state == ProcessingState.idle && audioPlayer.audioSource != null && !isUserInitiatedStop) { // 保存当前播放进度 final lastPosition = audioPlayer.position; // 重新加载最新的音频源,注意此处要拉取最新的未过期HLS地址,不要复用缓存的旧URL await audioPlayer.setAudioSource( HlsAudioSource(Uri.parse(yourLatestHlsUrl)), initialPosition: lastPosition, ); // 若当前处于待播放状态,自动触发播放 if (audioPlayer.playing) { await audioPlayer.play(); } } });
- 适配audio_service的播放回调逻辑
在自定义AudioHandler的play方法中增加idle状态兼容,避免锁屏点击无响应:
class MyAudioHandler extends BaseAudioHandler { @override Future<void> play() async { if (audioPlayer.processingState == ProcessingState.idle) { // 复用上述的音频源重新加载逻辑 final lastPosition = audioPlayer.position; await audioPlayer.setAudioSource( HlsAudioSource(Uri.parse(yourLatestHlsUrl)), initialPosition: lastPosition, ); } await audioPlayer.play(); super.play(); } }
日志排查补充
上层just_audio未捕获日志是因为报错由底层播放器抛出,可直接查看底层日志定位其他潜在问题:
- 安卓端执行
adb logcat | grep ExoPlayer查看ExoPlayer报错信息 - iOS端通过Xcode控制台查看AVPlayer相关报错信息
内容的提问来源于stack exchange,提问作者swiftymf
相关产品推荐
相关产品推荐

