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

C++ FFmpeg编码MP4流时帧率与码率异常问题求助

问题根源与修复方案

你的问题核心是时间戳处理错误和流参数配置不完整,导致播放器无法正确解析视频的时长与帧率。以下是具体修复步骤:

1. 修复Packet时间戳转换

FFmpeg中,编码器输出的Packet的PTS/DTS基于codec_context->time_base,但写入容器时需要转换为对应AVStream的time_base。你的代码直接写入Packet未做转换,导致时间戳异常,播放器计算出错误的帧率和时长。

修改编码循环中的Packet处理逻辑:

ret = avcodec_receive_packet(codec_context, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
    break;
}
pkt->stream_index = video_stream->index;
// 新增:将PTS/DTS转换为流的时间基准
av_packet_rescale_ts(pkt, codec_context->time_base, video_stream->time_base);
av_interleaved_write_frame(output_format_context, pkt);
av_packet_unref(pkt);

2. 完整配置流的帧率参数

你注释掉了流的r_frame_rate和avg_frame_rate设置,导致容器无法正确识别视频帧率。恢复这两个参数配置:

AVStream* ffmpeg_example::create_stream(AVFormatContext*& fctx, AVCodecContext*& codec_ctx) {
    AVStream* stream = avformat_new_stream(fctx, nullptr);
    avcodec_parameters_from_context(stream->codecpar, codec_ctx);
    stream->time_base = codec_ctx->time_base;
    // 恢复帧率参数配置
    stream->r_frame_rate = codec_ctx->framerate;
    stream->avg_frame_rate = stream->r_frame_rate;
    return stream;
}

3. 设置合理码率

你当前将bitrate设为0,编码器会使用默认超高码率,导致文件过大且播放异常。在set_codec_params中设置合理码率(例如5Mbps):

void ffmpeg_example::set_codec_params(AVFormatContext*& fctx, AVCodecContext*& codec_ctx, double width, double height, int fps, int bitrate) {
    std::cout << "encoding video for width:" << width << ", height:" << height << ", fps:" << fps << ", bitrate:" << bitrate << std::endl;
    codec_ctx->codec_id = fctx->oformat->video_codec;
    codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
    codec_ctx->width = width;
    codec_ctx->height = height;
    codec_ctx->gop_size = 12;
    codec_ctx->pix_fmt = COMMON_AV_FRAME_FORMAT;
    codec_ctx->framerate = AVRational{ fps, 1 };
    codec_ctx->time_base = AVRational{ 1, fps };
    // 设置默认码率为5Mbps,若传入有效值则使用传入值
    codec_ctx->bit_rate = bitrate > 0 ? bitrate : 5000000;
    if (fctx->oformat->flags & AVFMT_GLOBALHEADER) {
        codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    }
}

4. 同步编码器打开后的流参数

部分编码器(如MPEG4)在打开后会修改codec_context的time_base,因此需要将创建流的逻辑移到编码器打开之后,确保参数同步:
修改initFfmpegcontext函数的代码顺序:

// Open the codec
ret = avcodec_open2(codec_context, encoder, nullptr);
if (ret < 0) {
    std::cout << "Could not open encoder with context." << std::endl;
    return -1;
}

// 移到编码器打开后创建流,保证参数同步
// Create a new video stream
video_stream = create_stream(output_format_context, codec_context);
if (!video_stream) {
    std::cout << "Could not create stream." << std::endl;
    return -1;
}

验证修复结果

修改后重新生成视频,使用ffmpeg -i output.mp4查看信息,应显示:

  • 时长接近00:00:04.00
  • 帧率为30fps
  • 码率接近设置的数值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 14:42:01