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

如何通过libav API区分音频、视频等不同类型的解复用器?

通过libav API区分解复用器类型

FFmpeg 6.1的AVInputFormat结构体确实没有提供直接的分类字段,但可以通过格式的MIME类型、格式名称、特性标记这几个维度间接区分音频类、动图类、视频类及音视频容器类解复用器。以下是具体的判断逻辑和实现示例:

分类判断逻辑

1. 音视频容器类(如mov、mp4)

容器格式的核心是能封装多轨音视频流,判断依据:

  • 格式名称为常见容器名(如mov、mp4、mkv、flv等)
  • MIME类型通常为video/mp4、application/x-matroska这类容器专属类型
  • 多数容器格式的AVInputFormat->flags不会包含AVFMT_NOFILE标记(因为需要读取文件/流数据)

2. 音频类解复用器(如alsa、s16le)

分为原始音频格式和音频设备/协议两类:

  • 原始音频:MIME类型以audio/开头(如audio/L16对应s16le),或格式名称为raw音频编码名
  • 音频设备:格式名称为设备专属标识(如alsa、pulse),AVInputFormat->flags通常包含AVFMT_NOFILE(直接从设备读取,无需文件)

3. 视频类解复用器(如hevc、mjpeg)

指单轨原始视频格式,判断依据:

  • MIME类型以video/开头(如video/hevc、video/mjpeg)
  • 排除动图类格式(如gif),格式名称为原始视频编码名
  • 对应的解码器类型为AVMEDIA_TYPE_VIDEO(可通过av_codec_find_decoder验证)

4. 动图类解复用器(如gif)

核心特征是多帧动画,判断依据:

  • 格式名称为gif,MIME类型为image/gif
  • 打开后可观察到视频流包含连续低帧率帧(通常用于循环动画)

代码实现示例

#include <libavformat/avformat.h>
#include <string.h>

int main() {
    void *opaque = NULL;
    const AVInputFormat *fmt;

    // 初始化格式库(FFmpeg 4.x+可省略,兼容旧版本建议保留)
    av_register_all();

    while ((fmt = av_demuxer_iterate(&opaque))) {
        int is_container = 0;
        int is_audio = 0;
        int is_video = 0;
        int is_gif = 0;

        // 判断容器类:匹配常见容器名称
        const char *container_list[] = {"mov", "mp4", "mkv", "flv", "avi", "wmv", "mpegts", NULL};
        for (int i = 0; container_list[i]; i++) {
            if (!strcmp(fmt->name, container_list[i])) {
                is_container = 1;
                break;
            }
        }

        // 判断音频类:匹配MIME类型或音频设备名称
        if ((fmt->mime_type && strstr(fmt->mime_type, "audio/")) 
            || !strcmp(fmt->name, "alsa") 
            || !strcmp(fmt->name, "pulse")) {
            is_audio = 1;
        }

        // 判断动图类:匹配gif格式
        if (!strcmp(fmt->name, "gif")) {
            is_gif = 1;
        }

        // 判断视频类:排除动图的视频格式
        if (!is_gif && fmt->mime_type && strstr(fmt->mime_type, "video/")) {
            is_video = 1;
        }

        // 输出分类结果
        printf("解复用器: %s\n", fmt->name);
        if (is_container) printf("  类型: 音视频容器\n");
        if (is_audio) printf("  类型: 音频类\n");
        if (is_video) printf("  类型: 视频类\n");
        if (is_gif) printf("  类型: 动图类\n");
        printf("\n");
    }

    return 0;
}

补充说明

  • 上述判断为经验性逻辑,FFmpeg没有统一的分类标准,少量边缘格式可能需要特殊处理
  • 对于原始格式,可通过av_codec_find_decoder获取对应解码器,再通过AVCodec->type(AVMEDIA_TYPE_AUDIO/AVMEDIA_TYPE_VIDEO)进一步验证类型
  • 设备类解复用器可通过AVInputFormat->flags中的AVFMT_NOFILE标记快速识别

内容的提问来源于stack exchange,提问作者Jean-Michaël Celerier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 17:42:04