Flutter中video_player播放HLS .m3u8直播无法实时更新求助
解决Flutter video_player播放HLS直播仅加载20秒的问题
核心原因
你的代码没有处理HLS直播流的续播逻辑。video_player默认加载初始的m3u8切片列表后,不会主动请求更新后的流信息,当播放完已加载的切片(约20秒)后就会停止,无法获取后续的直播内容。
解决方案
你需要监听播放器的播放状态,当检测到播放接近当前加载的末尾时,重新加载直播流,具体实现如下:
- 添加播放状态监听
在初始化播放器后,添加监听器来检测播放位置是否接近当前总时长,触发重新加载:
// 初始化控制器后添加监听 await videoPlayerController.initialize(); videoPlayerController.addListener(_onPlayerUpdate); videoPlayerController.play(); home.notifyListeners(); // 监听函数 void _onPlayerUpdate() { final position = videoPlayerController.value.position; final duration = videoPlayerController.value.duration; // 当播放位置距离当前总时长不足1秒时,重新加载流 if (duration != null && position >= duration - const Duration(seconds: 1)) { _reloadLiveStream(); } }
- 实现流重载逻辑
编写函数销毁旧控制器、重新初始化并播放:
Future<void> _reloadLiveStream() async { // 先销毁旧控制器 await videoPlayerController.dispose(); // 重新创建控制器 videoPlayerController = VideoPlayerController.network('https://example.com/abcdef.m3u8'); // 初始化并继续播放 await videoPlayerController.initialize(); videoPlayerController.addListener(_onPlayerUpdate); videoPlayerController.play(); home.notifyListeners(); }
- 额外注意事项
- 更新插件版本:确保使用最新版的
video_player,旧版本可能存在HLS直播兼容性问题。 - 权限配置:确认Android的
AndroidManifest.xml已添加<uses-permission android:name="android.permission.INTERNET"/>,iOS的Info.plist已开启网络访问权限(HTTPS无需额外配置ATS)。 - 避免重复触发:添加加载状态标志,防止在重新加载过程中重复执行逻辑。
优化后的完整代码片段
// 定义控制器和加载状态 late VideoPlayerController videoPlayerController; bool _isReloading = false; // 播放按钮部分 SizedBox( width: screenHeight * 0.2, child: FloatingActionButton( heroTag: 'Start', onPressed: () async { if (!_isReloading) { _isReloading = true; videoPlayerController = VideoPlayerController.network('https://example.com/abcdef.m3u8'); await videoPlayerController.initialize(); videoPlayerController.addListener(_onPlayerUpdate); videoPlayerController.play(); home.notifyListeners(); _isReloading = false; } }, child: const Text('Start'), ), ) // 状态监听与重载函数 void _onPlayerUpdate() { if (_isReloading) return; final position = videoPlayerController.value.position; final duration = videoPlayerController.value.duration; if (duration != null && position >= duration - const Duration(seconds: 1)) { _reloadLiveStream(); } } Future<void> _reloadLiveStream() async { _isReloading = true; await videoPlayerController.dispose(); videoPlayerController = VideoPlayerController.network('https://example.com/abcdef.m3u8'); await videoPlayerController.initialize(); videoPlayerController.addListener(_onPlayerUpdate); videoPlayerController.play(); home.notifyListeners(); _isReloading = false; }
内容的提问来源于stack exchange,提问作者Jiehfeng
相关产品推荐
相关产品推荐

