基于时间限制切换MediaRecorder输出文件的Android开发求助
Android MediaRecorder 定时切换输出文件的实现思路
核心问题分析
原生MediaRecorder的OnInfoListener触发MEDIA_RECORDER_INFO_MAX_DURATION_REACHED时,会自动停止录制,必须重启才能继续,无法满足不停止录制切换文件的需求,因此需要从底层或替代方案入手。
方案一:基于MediaCodec+MediaMuxer的底层实现(推荐)
放弃封装后的MediaRecorder,直接使用Android底层编码组件,完全掌控录制流程:
- 核心逻辑:用
MediaCodec负责音视频编码,MediaMuxer负责将编码后的数据包写入文件;通过定时器监控录制时长,到达阈值时切换MediaMuxer的输出文件,编码流程不中断。 - 具体步骤:
- 初始化
MediaCodec(配置视频尺寸、码率、编码格式,音频采样率、声道数等),启动编码线程。 - 初始化第一个
MediaMuxer,绑定初始输出文件,添加音视频轨道后调用start()。 - 用
ScheduledExecutorService或Handler设置定时任务,例如每5分钟触发一次分片逻辑。 - 触发分片时:
- 调用当前
MediaMuxer的stop()和release(),确保文件结构完整。 - 创建新的输出文件,初始化新的
MediaMuxer,重复添加音视频轨道并start()。 - 后续编码后的数据包直接写入新的
MediaMuxer。
- 调用当前
- 初始化
- 关键注意点:
- 处理音视频同步:记录每个数据包的时间戳,切换
MediaMuxer时保持时间戳连续。 - 异常处理:捕获
MediaMuxer的启动/停止异常,避免录制中断。
- 处理音视频同步:记录每个数据包的时间戳,切换
伪代码示例:
// 定时任务触发分片 scheduledExecutor.scheduleAtFixedRate(() -> { // 停止当前Muxer currentMuxer.stop(); currentMuxer.release(); // 创建新文件和Muxer File newFile = createNewOutputFile(); MediaMuxer newMuxer = new MediaMuxer(newFile.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); // 添加音视频轨道(需复用之前的轨道参数) int videoTrackIndex = newMuxer.addTrack(videoFormat); int audioTrackIndex = newMuxer.addTrack(audioFormat); newMuxer.start(); currentMuxer = newMuxer; }, 5, 5, TimeUnit.MINUTES);
方案二:魔改MediaRecorder原生源码(仅适用于AOSP/定制ROM开发)
如果能修改Android系统源码,可以直接扩展MediaRecorder的分片逻辑:
- 核心逻辑:在
MediaRecorder的native层添加定时分片触发机制,复用原有按文件大小分片的逻辑,实现定时切换输出文件。 - 具体步骤:
- 定位到
MediaRecorder的native代码(路径:frameworks/av/media/libmedia/MediaRecorder.cpp)。 - 找到处理文件大小限制的逻辑(如
checkFileSize()方法),添加时间检查分支:- 记录录制开始时间,每次编码后检查当前时长是否达到设定阈值。
- 达到阈值时,调用原有分片逻辑:关闭当前文件、创建新文件、重新打开输出流,编码流程不中断。
- 在Java层的
MediaRecorder类添加新API,例如setOutputDurationLimit(long duration),将阈值传递到native层。 - 编译系统源码,替换原有
MediaRecorder组件。
- 定位到
方案三:伪无缝切换(无源码权限时的妥协方案)
如果无法修改底层,可通过提前预加载MediaRecorder减少切换中断:
- 核心逻辑:在接近时间阈值时,提前初始化好第二个
MediaRecorder,到点时快速切换,尽量缩短录制中断时间。 - 具体步骤:
- 启动第一个
MediaRecorder开始录制,用Handler监控录制时长。 - 在到达目标时长前100ms,初始化第二个
MediaRecorder,配置与第一个完全相同的参数(分辨率、码率、格式等)。 - 到达阈值时,立即调用第一个
MediaRecorder的stop()和release(),同时启动第二个MediaRecorder的start()。 - 重复上述逻辑,实现多文件分片。
- 启动第一个
- 局限性:会存在极短的录制中断(通常几十毫秒),适合对无缝要求不高的场景。
内容的提问来源于stack exchange,提问作者Alhusseen Alfalahy
相关产品推荐
相关产品推荐

