• Qt ffmpeg音视频转换工具


    Qt ffmpeg音视频转换工具,QProcess方式调用ffmpeg,对音视频文件进行格式转换,支持常见的音视频格式,主要在于QProcess的输出处理以及转换的文件名和后缀的处理,可以进一步加上音视频剪切合并和音视频文件属性查询修改的功能。

    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3. #include
    4. #include
    5. #include
    6. #include
    7. MainWindow::MainWindow(QWidget *parent) :
    8. QMainWindow(parent),
    9. ui(new Ui::MainWindow)
    10. {
    11. ui->setupUi(this);
    12. QFont font;
    13. font.setPixelSize(16);
    14. setFont(font);
    15. setWindowTitle(QStringLiteral("ffmpeg工具"));
    16. ui->listWidget->setMaximumWidth(200);
    17. connect(ui->listWidget, SIGNAL(clicked(QModelIndex)), this, SLOT(convert()));
    18. ui->checkBox->setChecked(true);
    19. mProcess = new QProcess;
    20. connect(mProcess, SIGNAL(readyReadStandardError()), this, SLOT(readError()));
    21. connect(mProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
    22. connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(finished(int,QProcess::ExitStatus)));
    23. mTimer = new QTimer(this);
    24. connect(mTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
    25. mTimer->start(1000);
    26. initListWidget();
    27. }
    28. MainWindow::~MainWindow()
    29. {
    30. delete ui;
    31. }
    32. void MainWindow::readError()
    33. {
    34. QString str = mProcess->readAllStandardError().data();
    35. if (str == "\r")
    36. {
    37. ui->textBrowser->append(mTmpStr);
    38. mTmpStr.clear();
    39. }
    40. else
    41. {
    42. mTmpStr += str;
    43. if (str.contains("\r\n"))
    44. {
    45. ui->textBrowser->append(mTmpStr);
    46. mTmpStr.clear();
    47. }
    48. }
    49. }
    50. void MainWindow::readOutput()
    51. {
    52. QByteArray qba = mProcess->readAllStandardOutput();
    53. QTextCodec* tc = QTextCodec::codecForName("System");
    54. QString str = tc->toUnicode(qba);
    55. if (str == "\r")
    56. {
    57. ui->textBrowser->append(mTmpStr);
    58. mTmpStr.clear();
    59. }
    60. else
    61. {
    62. mTmpStr += str;
    63. if (str.contains("\r\n"))
    64. {
    65. ui->textBrowser->append(mTmpStr);
    66. mTmpStr.clear();
    67. }
    68. }
    69. }
    70. void MainWindow::finished(int exitCode, QProcess::ExitStatus exitStatus)
    71. {
    72. ui->textBrowser->append(QStringLiteral("finished : %1 %2").arg(exitCode).arg(exitStatus));
    73. mProcess->close();
    74. if (exitCode == 0 && exitStatus == 0)
    75. {
    76. informationMessageBox(QStringLiteral("提示"), QStringLiteral("%1\n转换\n%2\n完成").arg(mSourceFile).arg(mTargetFile));
    77. }
    78. else
    79. {
    80. informationMessageBox(QStringLiteral("提示"), QStringLiteral("%1\n转换\n%2\n失败").arg(mSourceFile).arg(mTargetFile));
    81. }
    82. }
    83. void MainWindow::updateTimer()
    84. {
    85. if (!mTmpStr.isEmpty())
    86. {
    87. ui->textBrowser->append(mTmpStr);
    88. mTmpStr.clear();
    89. }
    90. }
    91. void MainWindow::initListWidget()
    92. {
    93. QStringList nameLst;
    94. nameLst.append(QStringLiteral("FLAC转MP3")); // ffmpeg -i input.flac -ab 320k -map_metadata 0 -id3v2_version 3 output.mp3
    95. nameLst.append(QStringLiteral("M4A转MP3")); // ffmpeg -i 1.m4a -acodec libmp3lame -aq 0 123.mp3
    96. nameLst.append(QStringLiteral("WAV转MP3")); // ffmpeg -i input.wav -f mp3 -acodec libmp3lame -aq 0 output.mp3
    97. nameLst.append(QStringLiteral("APE转MP3")); // ffmpeg -i 1.ape -acodec libmp3lame -aq 0 123.mp3
    98. nameLst.append("");
    99. nameLst.append(QStringLiteral("MP4转M4A")); // ffmpeg -i test.mp4 -acodec copy -vn 123.m4a
    100. nameLst.append(QStringLiteral("MP4转AAC")); // ffmpeg -i test.mp4 -acodec copy -vn 123.aac
    101. nameLst.append(QStringLiteral("MP4转MP3")); // ffmpeg -i test.mp4 -acodec libmp3lame -aq 0 123.mp3
    102. nameLst.append("");
    103. nameLst.append(QStringLiteral("MP3转OGG")); // ffmpeg -i bb.mp3 -acodec libvorbis -ab 128k bb.ogg
    104. nameLst.append(QStringLiteral("MP3转WAV")); // ffmpeg -i input.mp3 -f wav output.wav
    105. QMap cmdMap;
    106. cmdMap.insert(QStringLiteral("FLAC转MP3"), QStringLiteral("ffmpeg -i \"%1\" -ab 320k -map_metadata 0 -id3v2_version 3 -aq 0 \"%2\""));
    107. cmdMap.insert(QStringLiteral("M4A转MP3"), QStringLiteral("ffmpeg -i \"%1\" -acodec libmp3lame -aq 0 \"%2\""));
    108. cmdMap.insert(QStringLiteral("WAV转MP3"), QStringLiteral("ffmpeg -i \"%1\" -f mp3 -acodec libmp3lame -aq 0 \"%2\""));
    109. cmdMap.insert(QStringLiteral("APE转MP3"), QStringLiteral("ffmpeg -i \"%1\" -acodec libmp3lame -aq 0 \"%2\""));
    110. cmdMap.insert(QStringLiteral("MP4转M4A"), QStringLiteral("ffmpeg -i \"%1\" -acodec copy -vn \"%2\""));
    111. cmdMap.insert(QStringLiteral("MP4转AAC"), QStringLiteral("ffmpeg -i \"%1\" -acodec copy -vn \"%2\""));
    112. cmdMap.insert(QStringLiteral("MP4转MP3"), QStringLiteral("ffmpeg -i \"%1\" -acodec libmp3lame -aq 0 \"%2\""));
    113. cmdMap.insert(QStringLiteral("MP3转OGG"), QStringLiteral("ffmpeg -i \"%1\" -acodec libvorbis -ab 128k \"%2\""));
    114. cmdMap.insert(QStringLiteral("MP3转WAV"), QStringLiteral("ffmpeg -i \"%1\" -f wav \"%2\""));
    115. foreach (QString name, nameLst)
    116. {
    117. QListWidgetItem *item = new QListWidgetItem;
    118. if (!name.isEmpty())
    119. {
    120. item->setText(name);
    121. item->setData(Qt::UserRole, cmdMap.value(name));
    122. }
    123. else
    124. {
    125. item->setText("");
    126. item->setData(Qt::UserRole, "");
    127. }
    128. ui->listWidget->addItem(item);
    129. }
    130. }
    131. QString MainWindow::getFileSuffix(QString file)
    132. {
    133. QString ret;
    134. if (file == "FLAC")
    135. {
    136. ret = QStringLiteral("flac");
    137. }
    138. else if (file == "MP3")
    139. {
    140. ret = QStringLiteral("mp3");
    141. }
    142. else if (file == "M4A")
    143. {
    144. ret = QStringLiteral("m4a");
    145. }
    146. else if (file == "WAV")
    147. {
    148. ret = QStringLiteral("wav");
    149. }
    150. else if (file == "APE")
    151. {
    152. ret = QStringLiteral("ape");
    153. }
    154. else if (file == "AAC")
    155. {
    156. ret = QStringLiteral("aac");
    157. }
    158. else if (file == "MP4")
    159. {
    160. ret = QStringLiteral("mp4");
    161. }
    162. else if (file == "OGG")
    163. {
    164. ret = QStringLiteral("ogg");
    165. }
    166. return ret;
    167. }
    168. void MainWindow::convert()
    169. {
    170. QListWidgetItem *item = ui->listWidget->currentItem();
    171. QString tmp = item->data(Qt::UserRole).toString();
    172. if (mProcess->isOpen())
    173. {
    174. mProcess->close();
    175. }
    176. mSourceFile.clear();
    177. mTargetFile.clear();
    178. mSource.clear();
    179. mTarget.clear();
    180. mSourceSuffix.clear();
    181. mTargetSuffix.clear();
    182. if (!tmp.isEmpty())
    183. {
    184. mTitle = item->text();
    185. mCmd = tmp;
    186. setWindowTitle(QStringLiteral("ffmpeg工具 - %1").arg(mTitle));
    187. }
    188. else
    189. {
    190. mTitle.clear();
    191. mCmd.clear();
    192. setWindowTitle(QStringLiteral("ffmpeg工具"));
    193. }
    194. }
    195. bool MainWindow::informationMessageBox(const QString &title, const QString &text, bool isOnlyOk)
    196. {
    197. QMessageBox msgBox(this);
    198. msgBox.setFont(this->font());
    199. msgBox.setIcon(QMessageBox::Information);
    200. msgBox.setWindowTitle(title);
    201. msgBox.setText(text);
    202. if (isOnlyOk)
    203. {
    204. msgBox.setStandardButtons(QMessageBox::Ok);
    205. msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
    206. }
    207. else
    208. {
    209. msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
    210. msgBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
    211. msgBox.setButtonText(QMessageBox::Cancel, QStringLiteral("取消"));
    212. }
    213. return (msgBox.exec() == QMessageBox::Ok);
    214. }
    215. void MainWindow::closeEvent(QCloseEvent *event)
    216. {
    217. if (informationMessageBox(QStringLiteral("提示"), QStringLiteral("确定关闭"), false))
    218. {
    219. event->accept();
    220. }
    221. else
    222. {
    223. event->ignore();
    224. }
    225. }
    226. void MainWindow::on_pushButton_import_clicked()
    227. {
    228. if (mTitle.isEmpty() || mCmd.isEmpty())
    229. {
    230. return;
    231. }
    232. mSource = mTitle.split(QStringLiteral("转"))[0];
    233. mTarget = mTitle.split(QStringLiteral("转"))[1];
    234. mSourceSuffix = getFileSuffix(mSource);
    235. mTargetSuffix = getFileSuffix(mTarget);
    236. if (mSourceSuffix.isEmpty() || mTargetSuffix.isEmpty())
    237. {
    238. informationMessageBox(QStringLiteral("提示"), QStringLiteral("不支持的文件格式"));
    239. return;
    240. }
    241. QString file = QFileDialog::getOpenFileName(this, QStringLiteral("打开%1文件").arg(mSource), QStringLiteral("."), QStringLiteral("%1文件(*.%2)").arg(mSource).arg(mSourceSuffix));
    242. if (!file.isEmpty())
    243. {
    244. mSourceFile = file;
    245. if (ui->checkBox->isChecked())
    246. {
    247. QString tmp = mSourceFile;
    248. mTargetFile = tmp.replace(QStringLiteral(".%1").arg(mSourceSuffix), QStringLiteral(".%1").arg(mTargetSuffix));
    249. }
    250. }
    251. }
    252. void MainWindow::on_pushButton_save_clicked()
    253. {
    254. if (mSourceFile.isEmpty())
    255. {
    256. return;
    257. }
    258. QString file = QFileDialog::getSaveFileName(this, QStringLiteral("保存%1文件").arg(mTarget), mTargetFile, QStringLiteral("%1文件(*.%2)").arg(mTarget).arg(mTargetSuffix));
    259. if (!file.isEmpty())
    260. {
    261. mTargetFile = file;
    262. }
    263. }
    264. void MainWindow::on_pushButton_convert_clicked()
    265. {
    266. if (mSourceFile.isEmpty() || mTargetFile.isEmpty())
    267. {
    268. return;
    269. }
    270. QString cmd = mCmd.arg(mSourceFile).arg(mTargetFile);
    271. ui->textBrowser->append("\n" + cmd + "\n");
    272. if (mProcess->isOpen())
    273. {
    274. mProcess->close();
    275. }
    276. mTmpStr.clear();
    277. mProcess->start(cmd);
    278. }
  • 相关阅读:
    Ubuntu20.04 安装QT5.9.7 环境
    c++_learning-并发与多线程
    Java Maven POM配置参考
    10分钟搞定 Spring 批处理组件 —— spring-batch
    Imaris 卡退,是不是缓存盘没有设置好?
    GaussDB数据库SQL系列-LOCK TABLE
    Linux进程(三)--进程切换&命令行参数
    我的创作纪念日的温柔与七夕的浪漫交织了在一起
    地图双屏鼠标跟随效果
    【YOLOv5/v7改进系列】引入RT-DETR的RepC3
  • 原文地址:https://blog.csdn.net/mabing993/article/details/132940995