前言
本文记录用 FFmpeg 获取视频流+音频流的信息(编码格式、分辨率、帧率、播放时长…),所用的工程基于上个博客编译成功的工程:使用FFmpeg4.3.1的SDK官方开发包编译ffmpeg.c
一、需求
我们经常需要知道一个媒体文件所包含的媒体流的信息,比如文件格式、播放时长、码率、视音频编码格式,视频分辨率,帧率,音频属性等信息。
如何使用 FFmpeg API 获取这些信息呢?
- 媒体容器封装格式
- 文件播放时长
- 文件平均码率(视频+音频)
- 视频属性(编码器名称、视频分辨率、帧率、编码码率)
- 音频属性(编码器名称、采样率、声道数、编码码率)
二、源码
ffmepg.h 文件中添加我们自定义的结构体,我们后面会利用 ffmepg 的 API 函数将音视频流信息填充到各个字段:
typedef struct __AVGeneralMediaInfo { char filepath[1024]; // 文件路径 int64_t duration; // 时长,单位:微秒 time_base:1,000,000 int64_t totalBitrate; // 总码率 int videoStreamIndex; // 视频流索引 int audioStreamIndex; // 音频流索引 char videoCodecName[256]; int width; // 视频宽 int height; // 视频高 double frameRate; // 视频帧率 char audioCodecName[256]; int sampleRate; // 采样率 int channels; // 声道数 } AVGeneralMediaInfo; void get_avgeneral_mediainfo(AVGeneralMediaInfo* avmi, const char* filepath);
ffmepg.c 文件中添加获取音视频流的基本信息的接口
// 封装:查找解码器 // type:[0:video, 1:audio] void get_decoder_name(AVGeneralMediaInfo *avmi, AVFormatContext *avFmtctx, int type) { int nindex = -1; if (type == 0) { // video nindex = avmi->videoStreamIndex; } else if (type == 1) { // aduio nindex = avmi->audioStreamIndex; } if (nindex >= 0) { AVCodecContext* avcodecCtx = NULL; AVCodec *avcodec = NULL; avcodecCtx = avFmtctx->streams[nindex]->codec; avcodec = avcodec_find_decoder(avcodecCtx->codec_id); if (type == 0) { // video strcpy(avmi->videoCodecName, avcodec->name); printf("videoCodecName = %s\n", avmi->videoCodecName); } else if (type == 1) { strcpy(avmi->audioCodecName, avcodec->long_name); printf("audioCodecName = %s\n", avmi->audioCodecName); } } } // 获取音视频流的基本信息 void get_avgeneral_mediainfo(AVGeneralMediaInfo *avmi, const char *filepath) { int ret = -1; int i = 0; AVFormatContext* avFmtCtx = NULL; // 大管家 if (avmi == NULL || filepath == NULL) { return; } // 1.打开音视频文件或网络流 ret = avformat_open_input(&avFmtCtx, filepath, NULL, NULL); if (ret < 0) { printf("error avformat_open_input:%s\n", filepath); return; } // 2.打印音视频流信息 av_dump_format(avFmtCtx, 0, filepath, 0); // 3.继续深入,读取更多的字段 avmi->duration = avFmtCtx->duration; // 时长 avmi->totalBitrate = avFmtCtx->bit_rate; // 总码率 printf("duration = %lld, totalBitrate = %lld\n", avmi->duration, avmi->totalBitrate); // 分别读取音视频流,更多的参数 for (i = 0; i < avFmtCtx->nb_streams; i++) { AVStream* avstmp = avFmtCtx->streams[i]; // 拿到具体的一路流 if (avstmp->codec->codec_type == AVMEDIA_TYPE_VIDEO) { avmi->videoStreamIndex = i; avmi->width = avstmp->codec->width; avmi->height = avstmp->codec->height; // 视频帧率:avg_frame_rate // fps:frames per second if (avstmp->avg_frame_rate.num != 0 && avstmp->avg_frame_rate.den != 0) { avmi->frameRate = (double)avstmp->avg_frame_rate.num / (double)avstmp->avg_frame_rate.den; } printf("width = %d, height = %d, frameRate = %.3lf\n", avmi->width, avmi->height, avmi->frameRate); } else if (avstmp->codec->codec_type == AVMEDIA_TYPE_AUDIO) { avmi->audioStreamIndex = i; avmi->channels = avstmp->codec->channels; avmi->sampleRate = avstmp->codec->sample_rate; printf("channel = %d, sampleRate = %d\n", avmi->channels, avmi->sampleRate); } } // 读取具体的解码器 // avcodec_find_decoder() // 视频解码器 get_decoder_name(avmi, avFmtCtx, 0); // 音频解码器 get_decoder_name(avmi, avFmtCtx, 1); // release avformat_close_input(&avFmtCtx); }
ffmpeg431_test.cpp 文件内容如下:
#include <iostream> extern "C" { #include "ffmpeg.h" } int main(int argc, char** argv) { AVGeneralMediaInfo* avmi = new AVGeneralMediaInfo(); if (avmi) { get_avgeneral_mediainfo(avmi, "SampleVideo_1280x720_20mb.mp4"); delete avmi; avmi = NULL; } }
三、运行结果
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'SampleVideo_1280x720_20mb.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 creation_time : 1970-01-01T00:00:00.000000Z encoder : Lavf53.24.2 Duration: 00:01:57.31, bitrate: N/A Stream #0:0(und): Video: h264 (avc1 / 0x31637661), none, 1280x720, 1048 kb/s, 25 fps, 25 tbr, 12800 tbn (default) Metadata: creation_time : 1970-01-01T00:00:00.000000Z handler_name : VideoHandler Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 48000 Hz, 6 channels, 383 kb/s (default) Metadata: creation_time : 1970-01-01T00:00:00.000000Z handler_name : SoundHandler duration = 117312000, totalBitrate = 0 width = 1280, height = 720, frameRate = 25.000 channel = 6, sampleRate = 48000 videoCodecName = h264 audioCodecName = AAC (Advanced Audio Coding)
使用 MediaInfo 打开 SampleVideo_1280x720_20mb.mp4 可以看到与上面打印对应的参数