MediaProjection搭配MediaRecorder录屏出现视频损坏问题咨询
为什么MediaRecorder会出现这个颜色异常/视频损坏的问题?
这个问题核心是Android 6.0(API 23)及更早版本中MediaRecorder与VirtualDisplay的兼容性bug,具体可以拆解为这几点原因:
硬编码分辨率的宽高比不匹配:你设置的视频尺寸是480x270(16:9横屏比例),但出问题的Android 6设备屏幕是540x960(9:16竖屏比例)。Android 6的MediaRecorder处理Surface来源的视频时,对跨宽高比的分辨率缩放支持不佳,容易触发颜色空间转换错误(比如YUV格式采样或映射出错),最终导致画面变色、模糊。而Android 7.0(API 24)修复了这部分缩放与颜色处理逻辑,所以表现正常。
Density参数与视频尺寸适配偏差:你传递给
createVirtualDisplay的density是设备原生的densityDpi,但硬编码的视频尺寸远小于设备实际分辨率。在Android 6中,当VirtualDisplay的密度与视频尺寸不匹配时,会引发画面渲染的像素映射异常,进而被MediaRecorder录制成损坏的画面。API封装层级的差异:MediaCodec方案是你手动控制视频流编码,对格式转换的掌控更精细;而MediaRecorder是封装好的高层API,Android 6版本的底层实现对非原生分辨率的Surface输入兼容性较差,尤其是结合MediaProjection的VirtualDisplay使用时,容易出现帧数据捕获错误。
MediaRecorder搭配MediaProjection是否稳定?
整体来看,Android 7.0及以上版本中,MediaRecorder + MediaProjection的组合是比较稳定的,官方也推荐用这种方案快速实现录屏(尤其是需要同时录制音频时,比MediaCodec+MediaMuxer的实现成本低很多)。
但在Android 6.0及以下版本,确实存在不少已知的兼容性问题:
- 非原生分辨率/宽高比的视频录制容易出现画面异常
- 部分设备可能出现音视频不同步
- 少数厂商定制系统会限制MediaRecorder对VirtualDisplay的访问权限
修复建议
针对你的问题,可以尝试这些调整方案:
- 保持视频尺寸与设备屏幕宽高比一致:不要硬编码480x270,而是根据设备屏幕宽高比计算合适的视频尺寸,同时确保尺寸为偶数(H.264编码要求):
DisplayMetrics metrics = getResources().getDisplayMetrics(); int screenWidth = metrics.widthPixels; int screenHeight = metrics.heightPixels; // 按比例缩小到最大不超过480的宽度 int videoWidth = 480; int videoHeight = (int) ((float) videoWidth * screenHeight / screenWidth); // 修正为偶数 videoHeight = videoHeight % 2 == 0 ? videoHeight : videoHeight + 1; - 匹配VirtualDisplay的density参数:按视频尺寸与屏幕尺寸的比例,缩放原生density后传入:
int videoDensity = (int) ((float) videoWidth / screenWidth * metrics.densityDpi); media_projection.createVirtualDisplay("name", videoWidth, videoHeight, videoDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediarecorder.getSurface(), null, null); - 调整编码器或帧率设置:在Android 6设备上,尝试切换到
MediaRecorder.VideoEncoder.H263,或者将帧率降低到24fps,部分设备的MediaRecorder对这些参数的兼容性更好。
内容的提问来源于stack exchange,提问作者user9609225

