You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MediaRecorder采用GLSurfaceView的SurfaceTexture作预览时帧率骤降问题

我之前做类似的视频录制功能时也踩过这个坑,咱们来一步步拆解问题的成因和解决办法:

问题成因分析
  • 旧Camera API的预览目标限制:如果你用的是android.hardware.Camera这个旧版API,它只能设置一个预览输出目标——要么把帧发给GLSurfaceView的SurfaceTexture,要么发给MediaRecorder的Surface。你现在的做法相当于让两个组件同时抢Camera的帧资源,结果就是MediaRecorder启动后优先占用了大部分帧,GLSurfaceView的渲染线程拿不到足够的帧更新,自然帧率暴跌甚至静止。
  • SurfaceTexture的单消费者特性:SurfaceTexture的帧数据默认只能被一个消费者有效处理。当你把它创建的Surface传给MediaRecorder后,MediaRecorder会成为主要的帧消费者,GLSurfaceView那边就只能断断续续拿到残留的帧,预览就卡成了静止画面。
  • 编码与渲染的资源抢占:MediaRecorder启动后会占用大量CPU、GPU资源做视频编码,如果你的GLSurfaceView还有复杂的渲染逻辑,两个高负载任务抢资源,也会进一步拖慢预览帧率。
针对性解决办法

根据你使用的Camera API版本,分两种场景处理:

场景1:继续使用旧版android.hardware.Camera API

方案A:帧转发(推荐,预览连续性好)

让Camera只把帧输出给GLSurfaceView的SurfaceTexture,然后在GL渲染线程里,把渲染好的帧再转发给MediaRecorder的Surface:

  1. 给MediaRecorder创建独立的Surface(可以用MediaRecorder.getSurface(),API 21+支持)。
  2. 在GLSurfaceView的Renderer的onDrawFrame方法中,先完成预览帧的渲染,再通过离屏渲染(FBO)或者切换渲染目标的方式,把当前帧绘制到MediaRecorder的Surface对应的纹理上。
  3. 注意要处理好GL上下文的切换,避免线程冲突。

方案B:临时切换预览目标(实现简单,有短暂卡顿)

录制开始时把Camera的预览目标切给MediaRecorder,结束后切回GLSurfaceView:

// 录制启动逻辑
mCamera.stopPreview();
Surface mediaRecorderSurface = new Surface(glSurfaceViewInstance.getSurfaceTexture());
mMediaRecorder.setPreviewDisplay(mediaRecorderSurface);
mCamera.setPreviewDisplay(mediaRecorderSurface); // 确保和MediaRecorder用同一个Surface
mCamera.startPreview();
mMediaRecorder.start();

// 录制停止逻辑
mMediaRecorder.stop();
mCamera.stopPreview();
mCamera.setPreviewTexture(glSurfaceViewInstance.getSurfaceTexture());
mCamera.startPreview();

这种方法的缺点是切换瞬间会有预览中断,适合对预览连续性要求不高的场景。

场景2:迁移到android.hardware.camera2 API(长期最优解)

Camera2 API原生支持同时把Camera的帧输出到多个Surface,完美解决资源冲突问题:

  1. 创建CameraCaptureSession时,把GLSurfaceView的Surface和MediaRecorder的Surface都加入输出列表。
  2. 配置CaptureRequest,让Camera同时向这两个Surface输出帧。这样GLSurfaceView的预览和MediaRecorder的录制可以并行进行,互不干扰。
通用优化小技巧
  • 匹配编码与预览参数:让MediaRecorder的视频分辨率、帧率和GLSurfaceView的渲染尺寸一致,比如mMediaRecorder.setVideoSize(previewWidth, previewHeight),避免编码时额外的缩放转换消耗资源。
  • 简化GL渲染逻辑:去掉onDrawFrame里不必要的计算和绘制操作,减少GPU占用,给视频编码留出足够资源。
  • 后台线程处理MediaRecorder操作:把MediaRecorder的初始化、启动、停止等操作放到后台线程执行,别阻塞UI线程或GL渲染线程。

内容的提问来源于stack exchange,提问作者Gensoukyou1337

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:34:57