上海古都建筑设计集团,上海办公室装修设计公司,上海装修公司高质量的内容分享社区,上海装修公司我们不是内容生产者,我们只是上海办公室装修设计公司内容的搬运工平台

FFmpeg获取音视频流信息

guduadmin02小时前

文章目录

  • 前言
  • 一、需求
  • 二、源码
  • 三、运行结果

    前言

    本文记录用 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 
      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 可以看到与上面打印对应的参数

      FFmpeg获取音视频流信息,在这里插入图片描述,第1张


      我的qq:2442391036,欢迎交流!


网友评论

搜索
最新文章
热门文章
热门标签