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

使用libavformat/libavcodec编码视频时长远短于预期的原因及解决办法

问题原因与修复方案

核心问题

你的代码编码出的视频时长远短于预期,主要由两个关键问题导致:

1. 未触发编码器Flush

VP8这类帧间编码的编码器会缓存部分帧用于预测优化,当你循环发送完360帧后,编码器内部仍有未输出的缓存帧。如果不主动触发Flush逻辑,这些帧不会被写入文件,导致实际有效帧数远少于预期,最终视频时长被大幅压缩。

2. 码率参数配置冲突

你设置的最小码率rc_min_rate = 2.5e6大于最大码率rc_max_rate = 2e6,这是无效的参数组合,会导致编码器行为异常,可能直接丢弃部分帧或无法正常完成编码流程。

另外还有两个细节问题需要修正:发送帧后未释放帧引用、写入Packet后未释放Packet引用,虽然不是时长问题的直接原因,但会引发内存泄漏。


修复步骤

1. 添加编码器Flush逻辑

在编码循环结束后,发送NULL帧触发编码器输出所有缓存的帧:

// 原编码循环结束后添加以下代码
avcodec_send_frame(vcodec_ctx, NULL);
while ((res = avcodec_receive_packet(vcodec_ctx, vpacket)) == 0) {
    printf("Flushed DTS: %ld, PTS: %ld\n", vpacket->dts, vpacket->pts);
    if ((res = av_interleaved_write_frame(fmt_ctx, vpacket)) < 0)
        throw av::av_error(res);
    av_packet_unref(vpacket);
}
if (res != AVERROR_EOF && res != AVERROR(EAGAIN))
    throw av::av_error(res);

2. 修正码率参数

确保最小码率不超过最大码率,比如调整为:

vcodec_ctx->rc_max_rate = 2.5e6;
vcodec_ctx->rc_min_rate = 2e6;

如果不需要严格的码率控制,也可以直接删除rc_buffer_size、rc_max_rate、rc_min_rate这几个参数,让编码器自动适配。

3. 完善帧与Packet的引用管理

  • 发送帧到编码器后,释放帧的引用:
// send to encoder
avcodec_send_frame(vcodec_ctx, vframe);
av_frame_unref(vframe); // 释放帧引用,避免内存泄漏
  • 写入Packet到文件后,释放Packet的引用:
if ((res = av_interleaved_write_frame(fmt_ctx, vpacket)) < 0)
    throw av::av_error(res);
av_packet_unref(vpacket); // 释放Packet引用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:00:06