Flutter播放最多9路RTSP流时出现mmap failed:1错误求解决方案
Flutter多路RTSP播放触发mmap权限错误的解决方案
问题背景
开发最多9路RTSP流播放功能,运行一段时间后出现Dart VM虚拟内存分配失败错误:
flutter/third_party/dart/runtime/vm/virtual_memory_posix.cc: 69: error: mmap failed: 1 (Operation not permitted)' eax 00000000 ebx 000052b5 ecx 000052d0 edx 00000006 esi a007f978 edi a007f920 xcs 00000073 xds 0000007b xes 0000007b xfs 0000003b xss 0000007b eip abe6a424 ebp a007db08 esp a007daac flags 00000292
依赖包配置:
dependencies: flutter: sdk: flutter flutter_vlc_player: ^7.4.2 # To play RTSP streams media_kit: ^1.1.11 # Primary package media_kit_video: ^1.2.5 # For video rendering. media_kit_libs_video: ^1.0.5 # Native video dependencies
错误本质
该错误并非Dart本身的问题,而是多路视频流播放导致系统资源耗尽,Dart VM尝试分配虚拟内存时被系统权限拦截。每路RTSP流的解码、渲染都会占用大量内存、GPU资源和文件句柄,9路并发极易触发设备的资源上限。
解决方案
1. 降低单路视频的资源消耗
- 调整渲染质量:将
FilterQuality.medium改为FilterQuality.low,减少GPU计算负载 - 请求低码率/分辨率流:如果RTSP服务支持,直接拉取720p甚至更低分辨率的流,大幅降低内存占用
- 优化布局尺寸:确保
videoWidth和videoHeight匹配实际播放流的分辨率,避免不必要的缩放计算
2. 优化资源分配与释放逻辑
- 拉长初始化间隔:将原代码中
Future.delayed(Duration(seconds: index))的间隔从1秒改为2-3秒,给系统足够时间完成前一路流的资源分配与初始化 - 严格释放控制器:在页面销毁时必须遍历所有控制器调用
dispose,避免内存泄漏@override void dispose() { for (final controller in controllers) { controller.dispose(); } super.dispose(); } - 生命周期联动:监听App前后台状态,后台时暂停所有播放,前台恢复,减少后台资源占用
@override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); for (final controller in controllers) { if (state == AppLifecycleState.paused) { controller.pause(); } else if (state == AppLifecycleState.resumed) { controller.play(); } } }
3. 系统层面资源扩容(Android)
- 在
AndroidManifest.xml中开启大内存模式:<application android:name=".MainApplication" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true"> - 测试高配置设备:如果低配置设备复现问题,高配置设备正常,说明是硬件资源限制,需考虑动态限流(比如只同时播放4路,其余路显示缩略图)
4. 替换初始化逻辑为顺序可控加载
放弃Wrap+FutureBuilder的批量延迟初始化,改为顺序初始化,确保每路流初始化完成后再启动下一路:
Future<void> initVideoControllers() async { for (final rtspUrl in rtspUrlsList) { final controller = VideoController.network(rtspUrl); // 根据实际包调整初始化方式 await controller.initialize(); setState(() => controllers.add(controller)); await Future.delayed(const Duration(seconds: 2)); } }
内容的提问来源于stack exchange,提问作者EuSousa
相关产品推荐
相关产品推荐

