如何通过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
相关产品推荐
相关产品推荐

