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

禁用解码器后avformat_find_stream_info无法获取视频宽高的问询

解决FFmpeg禁用解码器后无法获取视频宽高的问题

问题原因

你编译FFmpeg时禁用了所有解码器,而avformat_find_stream_info()在无法解码视频帧的情况下,没法从首帧中提取宽高信息——部分容器的视频宽高不会直接存在文件头的元数据里,必须解码首帧才能获取。

可行解决方案

1. 启用对应视频编码的解码器

根据你实际处理的视频编码,在编译FFmpeg时添加对应解码器的启用参数,比如:

  • 处理H.264视频:添加--enable-decoder=h264
  • 处理H.265视频:添加--enable-decoder=hevc
  • 处理MPEG-4视频:添加--enable-decoder=mpeg4

启用解码器后,avformat_find_stream_info()就能正常解码首帧并填充宽高到codecpar->width和codecpar->height中。

2. 解析容器元数据或码流扩展数据(无需解码器)

如果不想启用解码器,可以通过解析容器的元数据结构或视频码流的扩展数据(extradata)来提取宽高:

方法A:使用av_codec_get_dimensions()函数

FFmpeg提供的av_codec_get_dimensions()可以尝试从AVCodecParameters的extradata中解析宽高,这个过程不需要解码器,只要FFmpeg支持该编码格式的基础解析能力(需启用对应编码的parser)。

示例代码:

int width = 0, height = 0;
AVCodecParameters *codecpar = format_context->streams[0]->codecpar;

// 尝试从extradata解析宽高
int ret = av_codec_get_dimensions(codecpar, &width, &height);
if (ret == 0 && width > 0 && height > 0) {
    // 成功获取到宽高
}

编译时需确保启用对应编码的parser,比如处理H.264时添加--enable-parser=h264。

方法B:手动解析码流扩展数据

以H.264为例,可以直接解析SPS(序列参数集)中的宽高信息,这部分只需要解析NAL单元结构,不需要解码器:

示例代码:

AVCodecParameters *codecpar = format_context->streams[0]->codecpar;
if (codecpar->codec_id == AV_CODEC_ID_H264 && codecpar->extradata_size > 4) {
    // 跳过AVCC格式的extradata头部(前4字节)
    uint8_t *sps_buf = codecpar->extradata + 4;
    int sps_len = codecpar->extradata_size - 4;

    // 初始化H.264 parser
    AVCodecParserContext *parser = av_parser_init(AV_CODEC_ID_H264);
    if (!parser) {
        // 初始化失败处理
        return;
    }

    AVCodecContext *tmp_ctx = avcodec_alloc_context3(avcodec_find_decoder(AV_CODEC_ID_H264));
    if (tmp_ctx) {
        // 解析SPS数据
        int parsed_len = av_parser_parse2(parser, tmp_ctx, &sps_buf, &sps_len, sps_buf, sps_len, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
        if (parsed_len > 0) {
            int width = tmp_ctx->width;
            int height = tmp_ctx->height;
            // 这里拿到宽高
        }
        avcodec_free_context(&tmp_ctx);
    }
    av_parser_close(parser);
}

方法C:解析容器原生结构

不同容器的元数据存储位置不同,比如:

  • MOV/MP4:可以遍历AVFormatContext的metadata字典,用av_dict_get()查找width、height相关字段;或者直接解析moov原子中的tkhd(轨道头部)结构。
  • Matroska:直接读取AVStream的codecpar中存储的轨道信息,部分Matroska文件会直接在轨道元数据中写入宽高。

3. 调整avformat_find_stream_info()的参数

可以给avformat_find_stream_info()传入一个包含少量解码参数的AVDictionary,比如设置更大的probesize,让FFmpeg读取更多文件数据来尝试从元数据中提取宽高,不过这个方法的兼容性取决于容器是否在文件头存储了宽高信息:

示例代码:

AVDictionary *opts = nullptr;
av_dict_set(&opts, "probesize", "1000000", 0); // 设置更大的探测大小
int ret = avformat_find_stream_info(format_context, &opts);
av_dict_free(&opts);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 17:55:22