如何通过FFmpeg实现移动端相机视频录制同步压缩,适配Android、iOS
移动端相机录制同步FFmpeg压缩双端适配方案
该方案确实存在,核心逻辑是跳过未压缩原始视频的本地暂存步骤,将相机实时采集的音视频原始帧直接送入FFmpeg编码管道,同步输出压缩后的视频文件,磁盘占用仅与最终压缩后的视频体积挂钩,完全适配磁盘空间不足的录制场景,同时支持Android、iOS双端。
通用实现流程
双端底层编码逻辑完全复用,仅系统采集层存在差异:
- 调用系统相机/音频采集API,获取原始YUV视频帧、PCM音频帧
- 按采集时间戳对齐音视频帧,送入FFmpeg编码上下文
- FFmpeg实时执行编码+封装操作,直接写入最终输出文件
- 全程无中间大文件生成,仅占用压缩后视频对应的磁盘空间
Android端实现要点
- 采集层采用Camera2或CameraX API,配置ImageReader输出YUV_420_888格式的原始视频帧,音频采用AudioRecord采集PCM数据
- 初始化FFmpeg编码上下文,设置压缩参数,核心配置示例如下:
// 视频编码器初始化伪代码 AVCodec *video_codec = avcodec_find_encoder(AV_CODEC_ID_H264); AVCodecContext *video_ctx = avcodec_alloc_context3(video_codec); video_ctx->width = 1280; // 输出宽度 video_ctx->height = 720; // 输出高度 video_ctx->pix_fmt = AV_PIX_FMT_YUV420P; video_ctx->bit_rate = 1500 * 1000; // 1.5Mbps码率,可按需调整 video_ctx->time_base = (AVRational){1, 30}; video_ctx->framerate = (AVRational){30, 1}; video_ctx->gop_size = 60; // 关键帧间隔 avcodec_open2(video_ctx, video_codec, NULL);
- 单独启动编码子线程,循环读取采集到的音视频帧,格式转换后调用
avcodec_send_frame送入编码器,编码完成的packet直接写入输出封装上下文 - 追求性能可开启FFmpeg硬编码支持,适配高通、联发科等平台的硬件编码能力,降低CPU占用
iOS端实现要点
- 采集层采用AVCaptureSession,配置视频输出格式为kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,音频采用AVCaptureAudioDataOutput采集PCM数据
- 编码逻辑完全复用Android端的FFmpeg代码,仅需将CMSampleBuffer中存储的YUV/PCM数据拷贝到AVFrame对应结构中即可送入编码队列
- 可调用VideoToolbox相关能力配合FFmpeg实现硬编码,进一步提升编码效率
关键注意事项
- 音视频帧的pts必须以系统采集的原始时间戳为准赋值,避免最终输出文件出现音画不同步问题
- 低性能设备可适当降低输出分辨率、帧率,或切换为H.265编码降低码率,避免采集+编码负载过高导致丢帧
- 编码操作必须放在独立子线程执行,禁止阻塞相机采集线程和UI主线程
内容的提问来源于stack exchange,提问作者fff
相关产品推荐
相关产品推荐

