Flutter中如何处理录制中的视频?实现无丢帧边录边推流
问题背景
在不稳定4G环境下需要实现边录边推流,流程要求:
- 开始录制
- 推流至服务器
- 停止录制
- 发送剩余文件块
- 等待请求完成
核心约束是必须处理音视频帧做分析,且不能丢失任何帧,因此无法使用“发送即忘”的传统流方案。
当前技术障碍
Flutter Camera插件版本迭代后,丢失了录制中访问文件的能力:
- 2020年版本支持通过
cameraController.startVideoRecording(pathToSave)指定或获取录制路径,两步即可实现边录边推:final pathToSave = cameraController.startVideoRecording();startStreamingTheFile(pathToSave);
- 当前版本仅能通过
final filePath = stopVideoRecording();获取文件路径,无法在录制过程中访问文件。
尝试过的不可行方案
- 分段录制:每2分钟录制一段,切换录制并发送已完成片段,但Flutter Camera不允许同一
CameraDescription存在两个CameraController,且启停录制的间隙会导致丢帧,此方案不可行。 - 帧级采集合成:通过
startImageStream()监听每帧画面,同时监听麦克风流;将帧保存为图片;每2分钟用ffmpeg将图片与音频合成为视频片段;发送片段并循环。该方案无丢帧,但开发工作量极大。
核心疑问
- 是否存在在录制过程中访问录制文件的方法?
- 录制文件是否仅在
stopRecording()调用后才生成?
解答
关于录制文件生成时机
Flutter Camera插件当前版本中,录制的视频文件是逐步写入磁盘的,但官方API并未暴露录制中的文件路径或句柄,只有调用stopVideoRecording()后才会返回完整文件路径。也就是说,文件在录制过程中已经存在,但官方没有提供访问途径。
可行解决方案
方案1:自定义Camera插件扩展(推荐)
基于官方Flutter Camera插件源码修改,恢复2020年版本的路径返回逻辑,同时确保文件写入时可安全读取:
- 在原生层(Android/iOS)的录制启动逻辑中,将生成的临时文件路径返回给Flutter层
- 修改Flutter层
CameraController的startVideoRecording()方法,返回实时录制文件路径 - 处理跨平台文件读写同步问题:比如Android允许
FileOutputStream并发读取,iOS避免文件独占锁
方案2:系统文件监听(临时 workaround)
提前指定固定临时文件路径(部分版本Camera插件支持通过参数指定保存路径),通过系统文件监听API监听文件变化:
- Android使用
FileObserver、iOS使用NSFileHandle监控文件大小增长 - 读取新增文件块进行推流,注意处理文件写入的原子性,避免读取不完整帧数据
- 该方案依赖系统特性,需做跨平台兼容性测试
方案3:帧级处理优化
如果必须使用startImageStream()方案,可通过以下方式降低工作量:
- 用Flutter
isolate处理帧保存与FFmpeg合成,避免阻塞UI线程 - 封装FFmpeg调用逻辑,使用预定义命令模板(如
ffmpeg -framerate 30 -i frame_%d.jpg -i audio.wav -c:v libx264 -c:a aac output.mp4) - 用缓存池管理帧数据,减少内存占用
内容的提问来源于stack exchange,提问作者Victor Gorban
相关产品推荐
相关产品推荐

