哈喽,这一篇记录一个小小的关于FFmpeg的使用,借助FFmpeg的API接口获取flv格式视频的时长。
查阅资料后,AVFormatContext中的duration字段可以获取视频时常,于是写出了如下代码:
代码语言:javascript复制#include <stdio.h>
#include <iostream>
extern "C" {
#include <libavformat/avformat.h>
}
#pragma comment(lib, "avformat.lib")
int main(int argc, char *argv[]) {
if (argc < 2) {
std::cout << "Usage: [programe] [intput_video_path/url]" << std::endl;
return -1;
}
char *inputUrl = argv[1];
AVFormatContext *fmtCtx = NULL;
int ret;
ret = avformat_network_init();
if (ret < 0) {
std::cout << "avformat_network_init failed " << std::endl;
return -1;
}
fmtCtx = avformat_alloc_context();
if (NULL == fmtCtx) {
std::cout << "avformat_alloc_context failed " << std::endl;
return -2;
}
ret = avformat_open_input(&fmtCtx, inputUrl, NULL, NULL);
if (ret < 0) {
std::cout << "avformat_open_input failed " << std::endl;
return -3;
}
int videoIndex = -1;
int nbStreams = fmtCtx->nb_streams;
for (int i = 0; i < nbStreams; i ) {
// fmtCtx->streams[i]->codec 新版ffmpeg已弃用
if (fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoIndex = i;
}
}
std::cout << "----------输入流信息---------------" << std::endl;
av_dump_format(fmtCtx, 0, inputUrl, NULL);
long duration = fmtCtx->duration; //微秒数
std::cout << "duration: " << duration << std::endl;
std::cout << "视频时常为: " << duration / 1000.0 / 1000.0 << "s" << std::endl;
system("pause");
return 0;
}
结果如下:
发现获取的视频时长为0,按照排查问题的一般思路,试试别的格式的文件是否也会有问题。尝试将文件更换为MP4文件,发现可以正常获取时长,如下图:
甚是不理解啊,经查阅资料发现,对于flv文件需要首先调用avformat_find_stream_info, 才可正常的获取视频时长,这一过程中,同时还发现另外一种获取视频时常的方式:FFmpeg对于 AVFormatContext->stream->codec的弃用(改为codecpar),修改后的代码如下:
代码语言:javascript复制#include <stdio.h>#include <iostream>extern "C" {#include <libavformat/avformat.h>}#pragma comment(lib, "avformat.lib")int main(int argc, char *argv[]) { if (argc < 2) { std::cout << "Usage: [programe] [intput_video_path/url]" << std::endl; return -1; } char *inputUrl = argv[1]; AVFormatContext *fmtCtx = NULL; int ret; ret = avformat_network_init(); if (ret < 0) { std::cout << "avformat_network_init failed " << std::endl; return -1; } fmtCtx = avformat_alloc_context(); if (NULL == fmtCtx) { std::cout << "avformat_alloc_context failed " << std::endl; return -2; } ret = avformat_open_input(&fmtCtx, inputUrl, NULL, NULL); if (ret < 0) { std::cout << "avformat_open_input failed " << std::endl; return -3; } ret = avformat_find_stream_info(fmtCtx, NULL); if (ret < 0) { std::cout << "avformat_find_stream_info failed " << std::endl; return -4; } int videoIndex = -1; int nbStreams = fmtCtx->nb_streams; for (int i = 0; i < nbStreams; i ) { // fmtCtx->streams[i]->codec 新版ffmpeg已弃用 if (fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoIndex = i; } } std::cout << "----------输入流信息---------------" << std::endl; av_dump_format(fmtCtx, 0, inputUrl, NULL); long duration = fmtCtx->duration; //微秒数 std::cout << "duration: " << duration << std::endl; std::cout << "视频时常为: " << duration / 1000.0 / 1000.0 << "s" << std::endl; // for flv file int seconds = fmtCtx->streams[videoIndex]->duration * fmtCtx->streams[videoIndex]->time_base.num / fmtCtx->streams[videoIndex]->time_base.den; std::cout << "flv file duratio: " << seconds << std::endl; system("pause"); return 0;}
其中:另外一种获取视频时长的方式为:
代码语言:javascript复制int seconds = fmtCtx->streams[videoIndex]->duration * fmtCtx->streams[videoIndex]->time_base.num / fmtCtx->streams[videoIndex]->time_base.den;
std::cout << "flv file duratio: " << seconds << std::endl;
FFmpeg弃用codec的修改为:
代码语言:javascript复制for (int i = 0; i < nbStreams; i ) {
// fmtCtx->streams[i]->codec 新版ffmpeg已弃用
if (fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoIndex = i;
}
}
调用avformat_find_stream_info的部分为:
代码语言:javascript复制 ret = avformat_find_stream_info(fmtCtx, NULL);
if (ret < 0) {
std::cout << "avformat_find_stream_info failed " << std::endl;
return -4;
}
修改后调用结果为:
终于可以成功获取flv格式视频的时长。可以动手去试试了!