通過調用外部程序(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下載,歡迎各位下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章