在博主之前的博文《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下載,歡迎各位下載