通过调用外部程序(ffmpeg.exe)的方式获取本地媒体文件的信息

  在博主之前的博文《FFmpeg解封装(解复用)并获取本地媒体文件的信息》中,介绍了使用FFmpeg的API获取媒体文件信息的方法。但FFmpeg的API是比较复杂的,如果不是专门从事音视频开发的工程师,可能无法很好地使用里面的API。本文以获取媒体文件的信息为例子,介绍另外一种使用FFmpeg的方法---------通过调用外部程序(ffmpeg.exe)的方式使用FFmpeg。使用该方法程序员不需要了解FFmpeg的api,只需要懂得一些FFmpeg的命令即可对媒体文件进行处理。下面介绍这种方法:

一、原理:

  在下图所示文件夹中,存在ffmpeg.exe和video1.mp4。

通过命令提示符进入上图所示目录中,执行命令:

ffmpeg -hide_banner -i video1.mp4

可以得到如下图所示的媒体文件video1.mp4的信息

所以程序员在程序中只要通过调用外部程序的方式执行命令“ffmpeg -hide_banner -i video1.mp4”(比如在Qt中可以通过QProcess的start函数执行命令),将在命令提示符中输出的信息保存到程序的变量中,即可在程序中得到媒体文件的信息

二、代码

开发环境为windows7 64位,Qt5.9.0 + vs2015

部分代码如下:

QtGuiApplication2.h

#pragma once

#include <QtWidgets/QMainWindow>
#include <QProcess>
#include "ui_QtGuiApplication2.h"

class QtGuiApplication2 : public QMainWindow
{
	Q_OBJECT

public:
	QtGuiApplication2(QWidget *parent = Q_NULLPTR);
public slots:
	void ReadMediaFileInformation();
	void ProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
private:
	Ui::QtGuiApplication2Class ui;
	QProcess *m_proc;
	std::string m_FFmpegBuf;   //保存FFmpeg的输出信息
	QString m_MediaFileName;   //要获取信息的媒体文件的名称
};

QtGuiApplication2.cpp

#include "QtGuiApplication2.h"

using namespace std;

QtGuiApplication2::QtGuiApplication2(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	m_proc = new QProcess(this);
	m_proc->setProcessChannelMode(QProcess::MergedChannels);
	connect(m_proc, SIGNAL(readyReadStandardOutput()), this, SLOT(ReadMediaFileInformation()));
	connect(m_proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(ProcessFinished(int, QProcess::ExitStatus)));
	m_MediaFileName = "video1.mp4";
	QString cmd = "ffmpeg -hide_banner -i " + m_MediaFileName;
        if (m_proc->state() != m_proc->NotRunning)
	{
		m_proc->waitForFinished(20000);
	}
	m_proc->start(cmd); //启动外部进程(执行命令ffmpeg -hide_banner -i video1.mp4)
}

//当外部进程产生的新的数据时该函数会被调用
void QtGuiApplication2::ReadMediaFileInformation()
{
	QString buf(QString::fromLocal8Bit(m_proc->read(10000)));
	string s = buf.toStdString();
	if (0 == s.length())
	{
		return;
	}
	m_FFmpegBuf += s;
}

//当外部进程结束时,该函数会被调用
void QtGuiApplication2::ProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
	qDebug("m_FFmpegBuf:%s", m_FFmpegBuf.c_str());
	int pos1,pos2;
	string bitrate;
	string duration;
	pos1 = m_FFmpegBuf.find("bitrate: ");
	pos2 = m_FFmpegBuf.find(" kb/s");
	if (pos1>=0 && pos2>=0)
	{
		bitrate = m_FFmpegBuf.substr(pos1+strlen("bitrate: "), (pos2+strlen(" kb/s")) - (pos1+strlen("bitrate: ")));  //该媒体文件的平均码率
	}

	pos1 = m_FFmpegBuf.find("Duration: ");
	pos2 = m_FFmpegBuf.find(", start:");
	if (pos1 >= 0 && pos2 >= 0)
	{
		duration = m_FFmpegBuf.substr(pos1 + strlen("Duration: "), pos2 - (pos1 + strlen("Duration: "))); //该媒体文件总时长
	}

	ui.LabelMediaFileName->setText(m_MediaFileName);
	ui.Labelbitrate->setText(QString::fromStdString(bitrate));
	ui.LabelDuration->setText(QString::fromStdString(duration));
}

执行上述程序的效果如下:

可以看到可以得到媒体文件video1.mp4的信息(码率,时长)

三、两种使用FFmpeg方式的比较:

1、通过外部进程调用ffmpeg.exe的方式:

优点:操作简单,只需要了解FFmpeg的命令即可对媒体文件进行处理。主要使用在对音视频处理执行时间要求不高的场合,比如市面上的一些视频编辑器的转换封装格式,合并视频音频,音视频分离等操作就是通过这种方式实现的。

缺点:执行效率低,时间开销大。有些音视频操作是只能用FFmpeg的API完成而无法通过调用ffmpeg.exe代替的,比如实现一个播放器。

2、通过调用FFmpeg的API的方式:

优点:灵活,速度快,效率高。能通过外部进程调用ffmpeg.exe的方式实现的操作就必然可以通过调用FFmpeg的API的方式实现。

缺点:使用比较复杂,对程序员的要求较高。

四、资源文件下载

上面演示的所有源码,完整的工程可以在https://download.csdn.net/download/u014552102/11859971下载,欢迎各位下载

发布了54 篇原创文章 · 获赞 55 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/u014552102/article/details/102535491
今日推荐