使用 MediaRecorder 录制视频时,如何设置分辨率、帧率和码率?

解读

面试官问“如何设置”并不是想听一句“调 setVideoSize / setVideoFrameRate / setVideoEncodingBitRate 就行”,而是考察候选人是否:

  1. 知道 MediaRecorder 的“先解锁摄像头 → 配置 CamcorderProfile → 再绑定到 MediaRecorder”这一套国内 ROM 也通行的生命周期;
  2. 能区分“Profile 硬编码能力”与“业务层动态降级”两套策略,避免在低端机上直接写死 1080p 导致 prepare() 抛 CamcorderProfile 为 null 的 Crash;
  3. 理解帧率、码率与最终文件大小、发热、编解码器负载之间的权衡,能给出“国内短视频 720p@30 fps 1.5 Mbps”这样可直接落地的经验值;
  4. 熟悉国产定制 ROM(华为、小米、OPPO)对 MediaRecorder 的隐藏限制,例如部分机型强制要求 setOutputFormat 必须在 setVideoSource 之后立即调用,否则报 -38 错误。

知识点

  1. MediaRecorder 状态机:Initial→Initialized→DataSourceConfigured→Prepared→Recording→Released,任何参数设置必须在对应状态之前完成,否则抛 IllegalStateException。
  2. CamcorderProfile 与动态参数两套 API:
    • 官方推荐 CamcorderProfile.hasProfile(cameraId, quality) 先判存在,再用 profile.videoFrameWidth/Height、profile.videoFrameRate、profile.videoBitRate 一次性 apply 到 MediaRecorder;
    • 若要做“非标准分辨率”或可变帧率,需手动 setVideoSize(w,h)、setVideoFrameRate(fps)、setVideoEncodingBitRate(bps),但必须先通过 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP 查询 MediaCodecInfo.CodecCapabilities 是否支持该组合,否则 prepare() 直接崩溃。
  3. 国内兼容性细节:
    • 华为 EMUI 11 之后若 targetSdk≥31,需在 AndroidManifest 声明 android:hardwareAccelerated="true" 且动态申请 CAMERA+RECORD_AUDIO,否则 MediaRecorder.start() 报 “start failed -22”;
    • 小米 MIUI 14 对后台录制限制极严,若应用退到后台 5 s 内未调用 startForegroundService,系统会强制 reset MediaRecorder,表现为主播端“点击开始录制后秒退”。
  4. 性能与体验权衡:
    • 帧率:短视频业务 30 fps 足够,直播带货场景可降到 24 fps 降低发热;
    • 码率:720p 使用 1.5–2 Mbps、1080p 使用 3.5–4 Mbps,在 H.264 baseline 下可兼顾清晰度与上传流量;
    • 分辨率:国内低端 4G 存量机(Android 8–9)最高仅支持 1280×720@30 fps,需在代码层做 capability 降级,不能依赖后台配置。

答案

分三步落地,兼顾兼容性与性能:

第一步:获取相机能力

CameraManager cm = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
String backId = cm.getCameraIdList()[0];
CameraCharacteristics chars = cm.getCameraCharacteristics(backId);
StreamConfigurationMap map = chars.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] videoSizes = map.getOutputSizes(MediaRecorder.class);
// 取最大 720p 尺寸作为上限
Size targetSize = chooseMax720p(videoSizes);

第二步:构造 Profile 或手动参数

MediaRecorder recorder = new MediaRecorder();
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {
    CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P);
    profile.videoBitRate = 1_500_000;   // 国内 720p 1.5 Mbps
    profile.videoFrameRate = 30;
    recorder.setProfile(profile);
} else {
    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    recorder.setVideoSize(targetSize.getWidth(), targetSize.getHeight());
    recorder.setVideoFrameRate(30);
    recorder.setVideoEncodingBitRate(1_500_000);
}

第三步:对齐与启动

recorder.setPreviewDisplay(surface);
recorder.setOutputFile(outputPath);
try {
    recorder.prepare();
    recorder.start();   // 进入 Recording 状态
} catch (IOException e) {
    // 国产 ROM 常见 -38、-22 错误在此捕获,提示用户“权限或参数不支持”
}

录制完成后按顺序 stop()→reset()→release(),防止小米 ROM 报 “media server died” 异常。

拓展思考

  1. 如果产品需求是“60 fps 高帧率 + 慢动作回放”,MediaRecorder 已无法满足,需要转向 MediaCodec + Camera2 自定义流水线,同时把帧率提升到 120 fps,码率同步翻倍到 6–8 Mbps,并手动写 MP4 封装(MediaMuxer),此时要处理国产芯片平台(麒麟、天玑)对 H.264 High Profile 的兼容差异。
  2. Android 14 引入 Ultra HDR 录制,需使用 Camera2 的 DynamicRangeProfiles.HLG10 并搭配 MediaRecorder.setVideoHDR(true),但目前小米 14 系列仅开放给系统相机,第三方应用调用会抛 UnsupportedOperationException,面试时可作为“国内 ROM 策略限制”案例,展示对最新趋势的跟踪。
  3. 对于隐私合规,国内监管要求“录制前必须弹窗告知用户并征得同意”,可在 MediaRecorder.start() 前插入自定义蒙层,同时把录制文件路径存入 MediaStore.VOLUME_EXTERNAL_PRIMARY,确保卸载后用户仍可在系统相册回看,避免“强行写私有目录”被应用市场审核驳回。