Qt ffmpeg音视频转换工具,QProcess方式调用ffmpeg,对音视频文件进行格式转换,支持常见的音视频格式,主要在于QProcess的输出处理以及转换的文件名和后缀的处理,可以进一步加上音视频剪切合并和音视频文件属性查询修改的功能。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QTextCodec>
#include <QFileDialog>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFont font;
font.setPixelSize(16);
setFont(font);
setWindowTitle(QStringLiteral("ffmpeg工具"));
ui->listWidget->setMaximumWidth(200);
connect(ui->listWidget, SIGNAL(clicked(QModelIndex)), this, SLOT(convert()));
ui->checkBox->setChecked(true);
mProcess = new QProcess;
connect(mProcess, SIGNAL(readyReadStandardError()), this, SLOT(readError()));
connect(mProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(finished(int,QProcess::ExitStatus)));
mTimer = new QTimer(this);
connect(mTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
mTimer->start(1000);
initListWidget();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::readError()
{
QString str = mProcess->readAllStandardError().data();
if (str == "\r")
{
ui->textBrowser->append(mTmpStr);
mTmpStr.clear();
}
else
{
mTmpStr += str;
if (str.contains("\r\n"))
{
ui->textBrowser->append(mTmpStr);
mTmpStr.clear();
}
}
}
void MainWindow::readOutput()
{
QByteArray qba = mProcess->readAllStandardOutput();
QTextCodec* tc = QTextCodec::codecForName("System");
QString str = tc->toUnicode(qba);
if (str == "\r")
{
ui->textBrowser->append(mTmpStr);
mTmpStr.clear();
}
else
{
mTmpStr += str;
if (str.contains("\r\n"))
{
ui->textBrowser->append(mTmpStr);
mTmpStr.clear();
}
}
}
void MainWindow::finished(int exitCode, QProcess::ExitStatus exitStatus)
{
ui->textBrowser->append(QStringLiteral("finished : %1 %2").arg(exitCode).arg(exitStatus));
mProcess->close();
if (exitCode == 0 && exitStatus == 0)
{
informationMessageBox(QStringLiteral("提示"), QStringLiteral("%1\n转换\n%2\n完成").arg(mSourceFile).arg(mTargetFile));
}
else
{
informationMessageBox(QStringLiteral("提示"), QStringLiteral("%1\n转换\n%2\n失败").arg(mSourceFile).arg(mTargetFile));
}
}
void MainWindow::updateTimer()
{
if (!mTmpStr.isEmpty())
{
ui->textBrowser->append(mTmpStr);
mTmpStr.clear();
}
}
void MainWindow::initListWidget()
{
QStringList nameLst;
nameLst.append(QStringLiteral("FLAC转MP3")); // ffmpeg -i input.flac -ab 320k -map_metadata 0 -id3v2_version 3 output.mp3
nameLst.append(QStringLiteral("M4A转MP3")); // ffmpeg -i 1.m4a -acodec libmp3lame -aq 0 123.mp3
nameLst.append(QStringLiteral("WAV转MP3")); // ffmpeg -i input.wav -f mp3 -acodec libmp3lame -aq 0 output.mp3
nameLst.append(QStringLiteral("APE转MP3")); // ffmpeg -i 1.ape -acodec libmp3lame -aq 0 123.mp3
nameLst.append("");
nameLst.append(QStringLiteral("MP4转M4A")); // ffmpeg -i test.mp4 -acodec copy -vn 123.m4a
nameLst.append(QStringLiteral("MP4转AAC")); // ffmpeg -i test.mp4 -acodec copy -vn 123.aac
nameLst.append(QStringLiteral("MP4转MP3")); // ffmpeg -i test.mp4 -acodec libmp3lame -aq 0 123.mp3
nameLst.append("");
nameLst.append(QStringLiteral("MP3转OGG")); // ffmpeg -i bb.mp3 -acodec libvorbis -ab 128k bb.ogg
nameLst.append(QStringLiteral("MP3转WAV")); // ffmpeg -i input.mp3 -f wav output.wav
QMap<QString, QString> cmdMap;
cmdMap.insert(QStringLiteral("FLAC转MP3"), QStringLiteral("ffmpeg -i \"%1\" -ab 320k -map_metadata 0 -id3v2_version 3 -aq 0 \"%2\""));
cmdMap.insert(QStringLiteral("M4A转MP3"), QStringLiteral("ffmpeg -i \"%1\" -acodec libmp3lame -aq 0 \"%2\""));
cmdMap.insert(QStringLiteral("WAV转MP3"), QStringLiteral("ffmpeg -i \"%1\" -f mp3 -acodec libmp3lame -aq 0 \"%2\""));
cmdMap.insert(QStringLiteral("APE转MP3"), QStringLiteral("ffmpeg -i \"%1\" -acodec libmp3lame -aq 0 \"%2\""));
cmdMap.insert(QStringLiteral("MP4转M4A"), QStringLiteral("ffmpeg -i \"%1\" -acodec copy -vn \"%2\""));
cmdMap.insert(QStringLiteral("MP4转AAC"), QStringLiteral("ffmpeg -i \"%1\" -acodec copy -vn \"%2\""));
cmdMap.insert(QStringLiteral("MP4转MP3"), QStringLiteral("ffmpeg -i \"%1\" -acodec libmp3lame -aq 0 \"%2\""));
cmdMap.insert(QStringLiteral("MP3转OGG"), QStringLiteral("ffmpeg -i \"%1\" -acodec libvorbis -ab 128k \"%2\""));
cmdMap.insert(QStringLiteral("MP3转WAV"), QStringLiteral("ffmpeg -i \"%1\" -f wav \"%2\""));
foreach (QString name, nameLst)
{
QListWidgetItem *item = new QListWidgetItem;
if (!name.isEmpty())
{
item->setText(name);
item->setData(Qt::UserRole, cmdMap.value(name));
}
else
{
item->setText("");
item->setData(Qt::UserRole, "");
}
ui->listWidget->addItem(item);
}
}
QString MainWindow::getFileSuffix(QString file)
{
QString ret;
if (file == "FLAC")
{
ret = QStringLiteral("flac");
}
else if (file == "MP3")
{
ret = QStringLiteral("mp3");
}
else if (file == "M4A")
{
ret = QStringLiteral("m4a");
}
else if (file == "WAV")
{
ret = QStringLiteral("wav");
}
else if (file == "APE")
{
ret = QStringLiteral("ape");
}
else if (file == "AAC")
{
ret = QStringLiteral("aac");
}
else if (file == "MP4")
{
ret = QStringLiteral("mp4");
}
else if (file == "OGG")
{
ret = QStringLiteral("ogg");
}
return ret;
}
void MainWindow::convert()
{
QListWidgetItem *item = ui->listWidget->currentItem();
QString tmp = item->data(Qt::UserRole).toString();
if (mProcess->isOpen())
{
mProcess->close();
}
mSourceFile.clear();
mTargetFile.clear();
mSource.clear();
mTarget.clear();
mSourceSuffix.clear();
mTargetSuffix.clear();
if (!tmp.isEmpty())
{
mTitle = item->text();
mCmd = tmp;
setWindowTitle(QStringLiteral("ffmpeg工具 - %1").arg(mTitle));
}
else
{
mTitle.clear();
mCmd.clear();
setWindowTitle(QStringLiteral("ffmpeg工具"));
}
}
bool MainWindow::informationMessageBox(const QString &title, const QString &text, bool isOnlyOk)
{
QMessageBox msgBox(this);
msgBox.setFont(this->font());
msgBox.setIcon(QMessageBox::Information);
msgBox.setWindowTitle(title);
msgBox.setText(text);
if (isOnlyOk)
{
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
}
else
{
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
msgBox.setButtonText(QMessageBox::Cancel, QStringLiteral("取消"));
}
return (msgBox.exec() == QMessageBox::Ok);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if (informationMessageBox(QStringLiteral("提示"), QStringLiteral("确定关闭"), false))
{
event->accept();
}
else
{
event->ignore();
}
}
void MainWindow::on_pushButton_import_clicked()
{
if (mTitle.isEmpty() || mCmd.isEmpty())
{
return;
}
mSource = mTitle.split(QStringLiteral("转"))[0];
mTarget = mTitle.split(QStringLiteral("转"))[1];
mSourceSuffix = getFileSuffix(mSource);
mTargetSuffix = getFileSuffix(mTarget);
if (mSourceSuffix.isEmpty() || mTargetSuffix.isEmpty())
{
informationMessageBox(QStringLiteral("提示"), QStringLiteral("不支持的文件格式"));
return;
}
QString file = QFileDialog::getOpenFileName(this, QStringLiteral("打开%1文件").arg(mSource), QStringLiteral("."), QStringLiteral("%1文件(*.%2)").arg(mSource).arg(mSourceSuffix));
if (!file.isEmpty())
{
mSourceFile = file;
if (ui->checkBox->isChecked())
{
QString tmp = mSourceFile;
mTargetFile = tmp.replace(QStringLiteral(".%1").arg(mSourceSuffix), QStringLiteral(".%1").arg(mTargetSuffix));
}
}
}
void MainWindow::on_pushButton_save_clicked()
{
if (mSourceFile.isEmpty())
{
return;
}
QString file = QFileDialog::getSaveFileName(this, QStringLiteral("保存%1文件").arg(mTarget), mTargetFile, QStringLiteral("%1文件(*.%2)").arg(mTarget).arg(mTargetSuffix));
if (!file.isEmpty())
{
mTargetFile = file;
}
}
void MainWindow::on_pushButton_convert_clicked()
{
if (mSourceFile.isEmpty() || mTargetFile.isEmpty())
{
return;
}
QString cmd = mCmd.arg(mSourceFile).arg(mTargetFile);
ui->textBrowser->append("\n" + cmd + "\n");
if (mProcess->isOpen())
{
mProcess->close();
}
mTmpStr.clear();
mProcess->start(cmd);
}