如何在Android CameraX中对录制的视频进行压缩?
Android CameraX录制视频后的压缩实现方案
在Android上,针对CameraX录制完成的视频进行压缩,主要有三种实用方案,从原生无依赖到第三方灵活处理,覆盖不同需求场景:
方案1:使用原生MediaCodec硬编码(无额外依赖,性能最优)
利用Android系统自带的MediaCodec进行硬件加速编码,是最轻量化的方案,适合仅需基础压缩(降分辨率、比特率)的场景。
核心步骤:
- 获取原视频参数:用
MediaMetadataRetriever读取原视频的分辨率、比特率、帧率等信息,作为压缩参数的参考。 - 配置编码参数:通过
MediaFormat设置目标分辨率(如原1080P降为720P)、比特率(原比特率的50%-70%)、帧率等。 - 提取与编码帧:用
MediaExtractor读取原视频的音视频帧,通过MediaCodec编码后,再用MediaMuxer合成压缩后的视频文件。
关键代码片段:
// 获取原视频参数 val retriever = MediaMetadataRetriever() retriever.setDataSource(inputVideoPath) val originalWidth = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 1920 val originalHeight = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 1080 retriever.release() // 配置目标编码格式 val targetWidth = 1280 val targetHeight = 720 val targetBitrate = (originalWidth * originalHeight * 30 * 0.1).toInt() // 按经验公式计算比特率 val videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, targetWidth, targetHeight).apply { setInteger(MediaFormat.KEY_BIT_RATE, targetBitrate) setInteger(MediaFormat.KEY_FRAME_RATE, 30) setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2) setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface) } // 后续需实现MediaExtractor读取帧、MediaCodec编码、MediaMuxer写入文件的逻辑,注意异步回调与异常处理
方案2:使用FFmpeg(灵活支持复杂处理)
如果需要同时进行视频裁剪、滤镜、转码等复杂操作,FFmpeg是首选。可通过预编译的aar包快速集成。
核心操作:
- 集成FFmpeg:在build.gradle中添加依赖(如
com.arthenica:mobile-ffmpeg-full:4.4.LTS)。 - 执行压缩命令:通过FFmpeg命令行参数设置压缩规则,例如降低分辨率、比特率:
示例代码:
// FFmpeg压缩命令:将原视频转为720P,视频比特率1.5Mbps,音频比特率128kbps val command = arrayOf( "-i", inputVideoPath, "-s", "1280x720", "-b:v", "1500k", "-c:v", "libx264", "-preset", "medium", "-c:a", "aac", "-b:a", "128k", outputVideoPath ) // 执行命令 val rc = FFmpeg.execute(command) if (rc == RETURN_CODE_SUCCESS) { // 压缩成功 } else { // 压缩失败,处理错误日志 }
方案3:使用AndroidX Media3库(官方推荐,兼容性好)
Media3是Google推出的新一代媒体库,整合了ExoPlayer、MediaCodec等功能,提供更简洁的API处理媒体编码。
核心步骤:
- 添加Media3依赖:在build.gradle中引入
androidx.media3:media3-transformer等相关模块。 - 使用Transformer进行压缩:通过
Transformer配置MediaItem和TransformationRequest,设置目标分辨率、比特率等参数,执行压缩。
示例代码:
val transformer = Transformer.Builder(context) .setTransformationRequest( TransformationRequest.Builder() .setResolution(Size(1280, 720)) .setVideoMimeType(MediaFormat.MIMETYPE_VIDEO_AVC) .build() ) .build() val mediaItem = MediaItem.fromUri(Uri.fromFile(File(inputVideoPath))) transformer.start( mediaItem, Uri.fromFile(File(outputVideoPath)), object : Transformer.Listener { override fun onCompleted(p0: MediaItem) { // 压缩完成 } override fun onError(p0: MediaItem, p1: TransformationException) { // 处理压缩错误 } } )
注意事项
- 权限处理:Android 12及以下需申请
WRITE_EXTERNAL_STORAGE,Android 13+需申请READ_MEDIA_VIDEO和WRITE_MEDIA_VIDEO权限。 - 参数调整:压缩参数需平衡文件大小与画质,例如低比特率会导致画质下降,过高则压缩效果不明显。
- 后台处理:压缩属于耗时操作,建议放在
WorkManager或后台线程中执行,避免阻塞主线程。
内容的提问来源于stack exchange,提问作者Saeed Noshadi
相关产品推荐
相关产品推荐

