用FFmpeg获取视频流+音频流的信息(编码格式、分辨率、帧率、播放时长...)
简介
我们经常需要知道一个媒体文件所包含的媒体流的信息,比如文件格式、播放时长、码率、视音频编码格式,视频分辨率,帧率,音频属性等信息。
如何使用FFmpeg API获取这些信息呢?
媒体容器封装格式
文件播放时长
文件平均码率(视频+音频)
视频属性(编码器名称、视频分辨率、帧率、编码码率)
音频属性(编码器名称、采样率、声道数、编码码率)
avformat_open_input
avformat_find_stream_info
伪代码:
/// 数据结构:大管家婆
AVFormatContext* m_inputAVFormatCxt = NULL;
/// 打开文件
res = avformat_open_input(&m_inputAVFormatCxt, filepath, 0, NULL);
/// 查找流信息
if (avformat_find_stream_info(m_inputAVFormatCxt, 0) < 0)
av_dump_format(m_inputAVFormatCxt, 0, filepath, 0);
///avformat_close_input(&m_inputAVFormatCxt);
/// 遍历流信息:音频、视频
for (int i = 0; i < m_inputAVFormatCxt->nb_streams; i++)
{
AVStream *in_stream = m_inputAVFormatCxt->streams[i];
if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
}
}
///查找解码器
if (avmi->videoStreamIndex != -1)
{
AVCodecContext *avctx;
AVCodec *codec;
do
{
avctx = m_inputAVFormatCxt->streams[avmi->videoStreamIndex]->codec;
// 寻找视频解码器
codec = avcodec_find_decoder(avctx->codec_id);
}
}
获取音视频流基本信息
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. 进一步读取音视频流信息
avformat_find_stream_info(avFmtCtx, NULL);
/// 3. 打印音视频流信息
av_dump_format(avFmtCtx, 0, filepath, 0);
读取总时长和总码率
/// 继续深入,读取更多的字段
avmi->duration = avFmtCtx->duration; //时长
avmi->totalBitrate = avFmtCtx->bit_rate; //总码率
printf("duration=%lld, totalBitrate=%lld\n",
avmi->duration,
avmi->totalBitrate);
读取视频宽高帧率和音频的声道数采样率
/// 分别读取音视频流,更多的参数
//avFmtCtx->nb_streams
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("channels=%d, sampleRate=%d\n",
avmi->channels,
avmi->sampleRate);
}
}
读取音视频解码器的名称
///查找解码器
if (avmi->videoStreamIndex != -1)
{
AVCodecContext *avctx;
AVCodec *codec;
do
{
avctx = m_inputAVFormatCxt->streams[avmi->videoStreamIndex]->codec;
// 寻找视频解码器
codec = avcodec_find_decoder(avctx->codec_id);
}
}