Android使用MediaRecorder、Camera2录制时如何在存文件前对帧应用变换矩阵
Android 视频录制帧变换实现方案
你提到的两个链路都存在冗余或逻辑缺陷,优先推荐基于OpenGL ES的硬件加速处理方案,全程GPU渲染无额外CPU拷贝开销,支持逐帧自定义变换矩阵。
链路选型说明
- 「Camera→Surface→MediaCodec + 变换处理→Surface→MediaRecorder→File」:完全冗余,MediaRecorder内部已经封装了MediaCodec编码器和MediaMuxer封装模块,编码后再输入MediaRecorder会导致二次编码,既损失画质又浪费性能,不可取。
- 「Camera→Surface→MediaCodec + 变换处理→File」:逻辑不完整,MediaCodec编码输出的是裸H.264/H.265流,没有容器封装、音视频同步信息,直接存储的文件无法被普通播放器识别。
推荐最优链路
Camera2 → SurfaceTexture → OpenGL ES 离屏渲染(应用变换矩阵)→ 编码器输入Surface → MediaCodec编码 → MediaMuxer封装输出MP4文件
如果目标设备API ≥26,可使用简化链路,无需自行维护编码和封装逻辑:Camera2 → SurfaceTexture → OpenGL ES 离屏渲染(应用变换矩阵)→ MediaRecorder输入Surface → MediaRecorder内部编码封装输出文件
核心实现步骤
1. Camera2 输出配置
- 创建
SurfaceTexture实例,将其对应的Surface加入到Camera2的CaptureRequest输出目标列表,Camera输出的帧会直接写入该SurfaceTexture。
2. OpenGL 变换管线搭建
- 创建与编码器/ MediaRecorder 输入Surface共享上下文的离屏EGL环境
- 生成
GL_TEXTURE_EXTERNAL_OES类型的纹理,与Camera输出的SurfaceTexture绑定 - 顶点着色器接收自定义变换矩阵参数,逐帧更新矩阵即可实现指定帧翻转180度、旋转、裁剪等效果
- 每次
SurfaceTexture触发新帧回调时,调用updateTexImage()更新纹理,执行渲染将变换后的帧绘制到编码器/ MediaRecorder的输入Surface上
3. 编码&封装配置
自行维护编码逻辑(全版本兼容)
- 配置视频编码的
MediaFormat,指定编码格式、分辨率、帧率、比特率、I帧间隔等参数 - 创建
MediaCodec视频编码器实例,调用createInputSurface()获取编码器输入Surface,作为OpenGL渲染的目标 - 启动编码器后循环读取编码输出的缓冲区,将编码后的视频流(如有音频同步添加音频流)传入
MediaMuxer封装为MP4写入文件
简化方案(API ≥26)
- 常规配置
MediaRecorder的音频、视频参数,输出路径等 - 调用
MediaRecorder.setInputSurface()获取自定义输入Surface,作为OpenGL渲染的目标 - 调用
MediaRecorder.start()后直接在OpenGL层处理帧变换即可,编码、音视频同步、封装逻辑由MediaRecorder内部完成
内容的提问来源于stack exchange,提问作者Braden Bagby
相关产品推荐
相关产品推荐

