You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

FFmpeg C/C++实现H264双Pass编码遇阻:stats_out为空及API困惑

我之前也碰到过一模一样的问题,折腾了好几天才摸清楚FFmpeg双Pass编码的正确打开方式,给你梳理下关键的坑和解决流程:

核心问题:你漏掉了统计文件的路径配置!

不管是用AV_CODEC_FLAG_PASS1还是av_opt_set(CodecCtx, "pass", "1", 0),单独设置Pass标记是没用的——FFmpeg需要知道把统计数据写到哪个文件里,没有指定路径的话,它根本无处存储数据,自然stats_out会是(null)

正确的双Pass编码步骤

第一Pass:生成统计文件

  1. 初始化编码器上下文,先设置好基础编码参数:码率、分辨率、帧率、GOP大小等(这些参数在第二Pass必须完全一致)。
  2. 必须先指定统计文件的保存路径:
    av_opt_set(CodecCtx, "stats_file", "./h264_2pass_stats.log", 0);
    
  3. 再设置第一Pass模式(推荐用av_opt_set,标志位方式在新版FFmpeg中已不推荐):
    av_opt_set(CodecCtx, "pass", "1", 0);
    // 旧版方式:CodecCtx->flags |= AV_CODEC_FLAG_PASS1; 不建议再用
    
  4. 打开编码器,遍历所有帧执行编码,但不需要保存输出的码流(第一Pass的输出是无效的,仅用于生成统计数据)。
  5. 编码完成后关闭编码器,此时指定路径下的统计文件已经生成。

第二Pass:使用统计文件优化编码

  1. 重新初始化编码器上下文,必须和第一Pass设置完全相同的基础参数(码率、帧率、分辨率等不能变)。
  2. 指定同一个统计文件路径,设置第二Pass模式:
    av_opt_set(CodecCtx, "stats_file", "./h264_2pass_stats.log", 0);
    av_opt_set(CodecCtx, "pass", "2", 0);
    // 旧版方式:CodecCtx->flags |= AV_CODEC_FLAG_PASS2;
    
  3. 打开编码器,再次遍历所有帧执行编码,这次保存输出的码流就是经过双Pass优化后的结果。
  4. 编码完成后关闭编码器,可按需删除统计文件。

关于废弃的FF_API_STATS_BIT字段

这些字段确实已经被FFmpeg标记为废弃,新版的双Pass编码完全依赖外部的统计文件传递数据,你不需要再手动读写这些字段——只要保证第一Pass正确生成统计文件,第二Pass能读取到它就行,这些内部统计字段已经不再参与双Pass逻辑了。

额外注意事项

  • 第一Pass的输出码流可以直接丢弃,不需要写入文件,它的唯一作用是让编码器收集帧的复杂度数据。
  • 第二Pass的编码器参数必须和第一Pass严格一致,否则统计数据无效,会导致编码结果不符合预期。
  • 如果你使用的是FFmpeg 4.x及以上版本,优先用av_opt_set配置passstats_file,避免直接操作flags,因为标志位的配置方式正在被逐步淘汰。

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

火山引擎 最新活动