使用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
相关产品推荐
相关产品推荐

