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

使用libavformat编码FLV时,如何提前写入尺寸信息以支持边编码边剪辑

解决FLV边编码边剪辑时的尺寸识别问题

你遇到的问题根源很明确:在边编码边写入FLV文件时,默认的libavformat FLV muxer不会在文件头部的MetaData Tag中提前写入视频宽高信息,导致ffmpeg读取未完成的文件时,无法从头部获取关键的尺寸参数。而编码完成后,muxer会自动补全这些元数据,所以此时剪辑操作就能正常执行。

下面是针对你的代码的具体修改方案,确保宽高信息被提前写入FLV头部,完美支持边编码边剪辑:

1. 切换到推荐的codecpar字段(替代废弃的codec字段)

旧版代码中使用的video_stream->codec已经被官方标记为废弃,改用codecpar来设置编码参数,能确保元数据被正确传递给muxer,避免兼容性问题:

// 替换原有的video_stream->codec相关设置
video_stream->codecpar->codec_id = AV_CODEC_ID_H264;
video_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
video_stream->codecpar->bit_rate = bitrate;
video_stream->codecpar->width = 640;
video_stream->codecpar->height = 480;
video_stream->codecpar->format = AV_PIX_FMT_YUV420P;

// 设置时间基和帧率,让元数据更完整
video_stream->time_base = (AVRational){1, 25};
video_stream->avg_frame_rate = (AVRational){25, 1};

2. 强制写入FLV头部的MetaData Tag

在调用avformat_write_header之前,手动添加包含宽高的元数据,让FLV muxer把这些信息提前写入文件头部:

// 创建元数据字典并设置核心参数
AVDictionary *metadata = NULL;
av_dict_set(&metadata, "width", "640", 0);
av_dict_set(&metadata, "height", "480", 0);
// 可选:额外添加帧率信息,让元数据更完整
av_dict_set(&metadata, "framerate", "25", 0);

// 将元数据关联到输出上下文
avformat_set_metadata(container_format_context, metadata);

// 释放字典避免内存泄漏
av_dict_free(&metadata);

3. 确保编码器全局头与extradata同步

打开编码器后,把编码器上下文的extradata(包含H264的SPS/PPS关键信息)同步到stream的codecpar中,这能让FLV muxer在头部写入正确的编码配置:

// 打开编码器之后添加这行代码
avcodec_parameters_from_context(video_stream->codecpar, avcodec_context);

4. 修改后的完整关键代码片段

整合以上修改后的核心代码如下,你可以直接替换原有的对应部分:

AVOutputFormat *container_format;
AVFormatContext *container_format_context;
AVStream *video_stream;
char *path = "/home/user/temp.flv";

// 分配输出媒体上下文
avformat_alloc_output_context2(&container_format_context, NULL, NULL, path);
container_format = container_format_context->oformat;

// 查找libx264编码器
AVCodec* codec = avcodec_find_encoder_by_name("libx264");

// 创建视频流
video_stream = avformat_new_stream(container_format_context, codec);
video_stream->id = container_format_context->nb_streams - 1;

// 使用codecpar设置视频参数(替代废弃的codec字段)
video_stream->codecpar->codec_id = AV_CODEC_ID_H264;
video_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
video_stream->codecpar->bit_rate = bitrate;
video_stream->codecpar->width = 640;
video_stream->codecpar->height = 480;
video_stream->codecpar->format = AV_PIX_FMT_YUV420P;
video_stream->time_base = (AVRational){1, 25};
video_stream->avg_frame_rate = (AVRational){25, 1};

// 初始化编码器上下文
AVCodecContext *avcodec_context = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(avcodec_context, video_stream->codecpar);

// 设置全局头标志(FLV容器必须)
if (container_format_context->oformat->flags & AVFMT_GLOBALHEADER) {
    avcodec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

// 补充编码器的其他配置
avcodec_context->gop_size = 10;
avcodec_context->qmax = 31;
avcodec_context->qmin = 2;
avcodec_context->pix_fmt = AV_PIX_FMT_YUV420P;
avcodec_context->time_base = (AVRational){1, 25};

// 打开编码器
int ret = avcodec_open2(avcodec_context, codec, NULL);
if (ret < 0) {
    // 这里添加你的错误处理逻辑
}

// 同步编码器上下文到stream的codecpar
avcodec_parameters_from_context(video_stream->codecpar, avcodec_context);

// 添加FLV头部元数据
AVDictionary *metadata = NULL;
av_dict_set(&metadata, "width", "640", 0);
av_dict_set(&metadata, "height", "480", 0);
av_dict_set(&metadata, "framerate", "25", 0);
avformat_set_metadata(container_format_context, metadata);
av_dict_free(&metadata);

// 打开输出文件
if (!(container_format->flags & AVFMT_NOFILE)) {
    ret = avio_open(&container_format_context->pb, path, AVIO_FLAG_WRITE);
    if (ret < 0) {
        // 这里添加你的错误处理逻辑
    }
}

// 写入文件头
ret = avformat_write_header(container_format_context, NULL);
if (ret < 0) {
    // 这里添加你的错误处理逻辑
}

// 后续的帧编码和写入逻辑...

为什么这样修改有效?

  • 使用codecpar确保参数被muxer正确识别,避免废弃字段带来的兼容性问题
  • 手动添加的元数据会被FLV muxer写入到文件开头的MetaData Tag中,ffmpeg读取未完成的文件时能直接从这里获取宽高
  • 同步编码器的extradata确保H264的SPS/PPS被写入FLV头部,让解码器能正确解析视频流

现在你可以边编码边执行ffmpeg剪辑命令,ffmpeg就能从FLV头部获取到尺寸参数,不会再出现报错了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:18:51