Flutter Video Player播放32MB 2K视频时崩溃问题求助
Flutter播放32MB 2K视频崩溃问题排查与解决
我开发的博客App通过Django REST API上传视频,Flutter端用video_player播放。9MB以内的视频能正常上传播放,但播放32MB的2K分辨率视频时App直接崩溃。后来改用cached_video_player的CachedVideoPlayerController,问题依旧。
原错误日志(video_player)
D/BufferPoolAccessor2.0(12981): bufferpool2 0x70b2b0f534b8 : 0(0 size) total buffers - 0(0 size) used buffers - 17/25 (recycle/alloc) - 6/22 (fetch/transfer) D/BufferPoolAccessor2.0(12981): evictor expired: 1, evicted: 1 D/BufferPoolAccessor2.0(12981): bufferpool2 0x70b2b0f4ef58 : 0(0 size) total buffers - 0(0 size) used buffers - 15/25 (recycle/alloc) - 9/22 (fetch/transfer) D/BufferPoolAccessor2.0(12981): bufferpool2 0x70b2b0eedfa8 : 0(0 size) total buffers - 0(0 size) used buffers - 19/30 (recycle/alloc) - 9/25 (fetch/transfer) D/BufferPoolAccessor2.0(12981): evictor expired: 2, evicted: 2 D/BufferPoolAccessor2.0(12981): bufferpool2 0x70b2b0f3a6f8 : 5(40960 size) total buffers - 4(32768 size) used buffers - 22/27 (recycle/alloc) - 8/24 (fetch/transfer) D/BufferPoolAccessor2.0(12981): bufferpool2 0x70b2b0f887b8 : 5(31457280 size) total buffers - 0(0 size) used buffers - 14/20 (recycle/alloc) - 10/20 (fetch/transfer) D/BufferPoolAccessor2.0(12981): bufferpool2 0x70b2b0f5f6f8 : 5(31457280 size) total buffers - 0(0 size) used buffers - 15/20 (recycle/alloc) - 8/20 (fetch/transfer) D/BufferPoolAccessor2.0(12981): evictor expired: 2, evicted: 2 D/BufferPoolAccessor2.0(12981): evictor expired: 1, evicted: 1 Lost connection to device.
更换cached_video_player后的错误日志
D/BufferPoolAccessor2.0( 9534): evictor expired: 1, evicted: 1 D/BufferPoolAccessor2.0( 9534): bufferpool2 0x7d90ca5b8d48 : 5(31457280 size) total buffers - 3(18874368 size) used buffers - 636/643 (recycle/alloc) - 10/639 (fetch/transfer) D/BufferPoolAccessor2.0( 9534): evictor expired: 1, evicted: 1 Lost connection to device.
相关代码片段
final url = Uri.parse('path to video file'); VideoPlayerController videocontroller = VideoPlayerController.networkUrl(url); videocontroller.addListener(() { setState(() { _hasVideo = true; }); }); videocontroller.setLooping(true); videocontroller.initialize(); setState(() { _hasVideo = true;
注:_hasVideo是区分图片帖和视频帖的布尔字段。
问题分析
从日志里的BufferPoolAccessor2.0相关信息来看,核心问题是内存过载。2K视频单帧数据量远大于普通视频,直接加载网络视频时,播放器会预加载大量帧到内存,导致设备内存耗尽触发崩溃。更换缓存包无效,是因为缓存包主要解决重复加载问题,没从根本上控制内存占用。
解决方案
规范控制器生命周期管理
- 页面销毁时必须释放控制器资源,避免内存泄漏:
@override void dispose() { videocontroller?.dispose(); super.dispose(); } - 监听初始化完成的Future,避免过早触发UI更新:
videocontroller.initialize().then((_) { setState(() { _hasVideo = true; }); });
- 页面销毁时必须释放控制器资源,避免内存泄漏:
限制视频缓冲与分辨率
- 初始化控制器时配置
videoPlayerOptions,关闭后台播放并优化缓冲策略:VideoPlayerController.networkUrl( url, videoPlayerOptions: VideoPlayerOptions( allowBackgroundPlayback: false, mixWithOthers: false, ), ); - 后端转码适配:在Django后端对上传的2K视频自动生成1080P/720P转码版本,Flutter端根据设备性能选择合适分辨率播放。
- 初始化控制器时配置
列表场景内存优化
如果是列表展示视频,滚动时销毁不可见的视频控制器,仅保留当前可见项的控制器,避免同时加载多个大视频占用内存。尝试更优播放器封装
可以用chewie(基于video_player的封装,自带内存优化逻辑),或者flutter_ffmpeg(底层视频处理,可自定义缓冲策略)替代原生播放器。
内容的提问来源于stack exchange,提问作者Ananth
相关产品推荐
相关产品推荐

