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

Android下如何降低MediaCodec编码帧率?兼容旧版本设备

解决MediaCodec编码帧率无法限制的问题(兼容旧Android版本)

MediaCodec的KEY_FRAME_RATE和KEY_MAX_FPS_TO_ENCODER多数情况下只是编码器的参考值,不会主动丢弃输入帧——尤其是Surface输入场景,编码器会处理所有送到Surface的帧。要稳定限制帧率并兼容旧版本,核心是主动控制输入到编码器的帧数量,配合参数优化实现目标。

一、主动控制帧输入频率(全版本兼容,最可靠)

直接从源头控制向编码器提交帧的频率,比如目标10fps就每100ms提交一帧,超过频率的帧直接丢弃。

实现逻辑:

  1. 计算目标帧率对应的时间间隔(比如10fps对应1_000_000_000 / 10 = 100_000_000纳秒)。
  2. 记录上一次提交帧的时间戳,每次获取到新帧时,判断当前时间与上一次的间隔是否达到阈值,达到才提交,否则跳过。

示例代码:

// 目标帧率,可根据需求设置5-10之间的值
val targetFps = 10
val frameIntervalNs = 1_000_000_000 / targetFps
var lastFrameSubmitTimeNs = 0L

// 初始化编码器格式
val format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_VP8, size.width, size.height).apply {
    setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
    setInteger(MediaFormat.KEY_BIT_RATE, 1000000) // 固定1Mbps带宽
    setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR_FD)
    setInteger(MediaFormat.KEY_FRAME_RATE, targetFps) // 给编码器提供参考
    setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10) // 每10帧生成一个I帧(对应1秒)
    setInteger(MediaFormat.KEY_MAX_FPS_TO_ENCODER, targetFps) // 部分设备支持的硬限制
}

encoderInput = mEncoder!!.createInputSurface()
// Surface帧率控制仅在API 24+生效,旧版本忽略
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    encoderInput.setFrameRate(targetFps.toFloat(),
        Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
        Surface.CHANGE_FRAME_RATE_ALWAYS)
}

// 帧回调中的处理逻辑(以SurfaceTexture为例)
fun onFrameAvailable(surfaceTexture: SurfaceTexture) {
    val currentTimeNs = System.nanoTime()
    surfaceTexture.updateTexImage() // 必须调用,避免后续帧阻塞

    if (currentTimeNs - lastFrameSubmitTimeNs >= frameIntervalNs) {
        lastFrameSubmitTimeNs = currentTimeNs
        // 将帧渲染到编码器的InputSurface(需自行实现渲染逻辑,比如用OpenGL ES)
        renderFrameToEncoderSurface(surfaceTexture, encoderInput)
    }
    // 跳过的帧无需渲染到编码器
}

二、辅助优化建议

  1. Camera预览场景:优先设置Camera的预览帧率为目标帧率(比如Camera.Parameters.setPreviewFpsRange(10000, 10000)对应10fps),减少Camera输出的帧数量,降低后续处理压力。若Camera不支持低帧率,再用主动丢弃的方法。
  2. 编码器参数配合:保持BITRATE_MODE_CBR_FD模式,在固定带宽下,编码器会更合理地分配每帧的比特率,低帧率下单帧画质会更优。
  3. 旧版本兼容:API 24以下的系统完全依赖主动帧控制,不要依赖Surface.setFrameRate()或编码器的帧率参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:50:31