В этой статье описывается процесс разработки использования Qt для реализации проекта транскодера аудио и видео FFmepg.
1. Сначала создайте проект Qt и выберите MSVC2017 32bit в качестве его компилятора.
2. Скопируйте библиотеки и исходные файлы, связанные с FFmpeg, в текущий каталог.
3. Закомментируйте функцию готовых_app_arguments (нам будет удобно указать соответствующие параметры транскодирования при дальнейшем запуске)
4. Скопируйте некоторые необходимые файлы динамической библиотеки dll в каталог отладки.
5. Скопируйте файлы аудио- и видеоматериалов в build-QtVideoConverterFFmpeg431-Desktop_Qt_5_14_2_MinGW_32_bit-Debug
в каталоге(НажмитебегатьАвтоматически созданный каталог)
Нарисуйте простой интерфейс пользовательского интерфейса, эффект будет следующим:
Он включает в себя рамку, кнопку, индикатор выполнения, метку, виджет таблицы, поле со списком, редактирование строки и другие связанные элементы управления.
1、существоватьНачать перекодированиекнопка clicked Добавьте следующий код в функцию слота:
void Widget::on_pushButton_Running_clicked()
{
qDebug() << "hello,ffmpeg";
QString currentPath = QDir::current().path();
qDebug() << "Current path:" << currentPath;
char* arrParams[10] = { 0 };
for (int k = 0; k < 10; k++) {
arrParams[k] = new char[64]();
}
strcpy(arrParams[0], "QtVideoConverter.exe");
strcpy(arrParams[1], "-i");
strcpy(arrParams[2], "SampleVideo_1280x720_20mb.mp4");
strcpy(arrParams[3], "-vcodec");
strcpy(arrParams[4], "libx264");
strcpy(arrParams[5], "-acodec");
strcpy(arrParams[6], "copy");
strcpy(arrParams[7], "-y");
strcpy(arrParams[8], "SampleVideo_1280x720_20mb.flv");
main_ffmpeg431(9, arrParams);
AVGeneralMediaInfo* avmi = new AVGeneralMediaInfo();
for (int k = 0; k < 10; k++) {
delete[] arrParams[k];
avmi = NULL;
}
}
2. Нажмите «Выполнить», и вы увидите следующий интерфейс.
В настоящее время функция индикатора выполнения не реализована. Нажмите на транскодирование, чтобы. build-QtVideoConverter-Desktop_Qt_5_14_2_MSVC2017_32bit-Debug
В каталоге вы увидите, что перекодирование прошло успешно. flv документ
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setStyleSheet("background-color:#F0F0F0;"); // Настройка внешнего вида окон компонентов
// qss, похоже на css
ui->lblLogoText->setStyleSheet("color:#009100;font-style:italic;font-weight:bold;font-size:30px;");
// frame цвет фона
ui->frameTop->setStyleSheet("background-color:#C4E1FF;");
// кнопкацвет фона
ui->pushButton_Running->setStyleSheet("background-color:#C4E1FF;font-weight:bold;font-size:30px;color:#009100;border:2px groove gray;border-radius:10px;padding:2px 4px;");
}
// Линии сетки скрыты, а ячейки нельзя редактировать.
ui->tableWidget_FileList->verticalHeader()->setHidden(true); // Установите скрытое имя строки (обратите внимание, что это имя строки, а не вся строка)
ui->tableWidget_FileList->setShowGrid(false); // Определяет, отображается ли сетка между элементами данных в представлении.
ui->tableWidget_FileList->setEditTriggers(QAbstractItemView::NoEditTriggers); // Сделайте эту форму доступной только для чтения пользователям
Эффект следующий:
Фильтр событий: (двойной щелчок, полноэкранный режим)
// Фильтр событий: (двойной щелчок, полноэкранный режим)
bool Widget::eventFilter(QObject *obj, QEvent *event)
{
// Укажите элемент управления
if (obj == ui->frameTop || obj == ui->lblLogoText || obj == ui->lblLogoImage) {
// QEvent::MouseButtonPress,QEvent::MouseButtonDblClick
if (event->type() == QEvent::MouseButtonDblClick) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton) {
// QMessageBox::information(this, "Нажмите", "Нажмите меня поймал", QMessageBox::Yes | QMessageBox::No | QMessageBox::Yes);
if (!this->isMaximized()) {
this->showMaximized();
} else {
this->showNormal();
}
return true;
} else {
return false;
}
} else {
return false;
}
} else {
// pass the event on to the parent class
return Widget::eventFilter(obj, event);
}
}
Эффект:
Клавиша ESC для выхода из полноэкранного режима
// Кнопка: (esc — выход из полноэкранного режима)
void Widget::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Escape:
if (this->isMaximized()) {
this->showNormal();
}
break;
default:
QWidget::keyPressEvent(event);
}
}
Нажмите мышь, не отпуская ее, затем переместите мышь, чтобы перетащить, и отпустите мышь, чтобы завершить перетаскивание.
// тащитьдействовать---begin
void Widget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_bDrag = true;
// Получить начальное положение мыши
mouseStartPoint = event->globalPos(); // Значение смещения мыши относительно верхнего левого угла (0,0) всего экрана при возникновении события.
// mouseStartPoint = event->pos(); // Мышь активна относительно текущего события, когда событие происходит. Значение смещения верхнего левого угла виджета (0,0)
// Получить начальное положение окна
windowTopLeftPoint = this->frameGeometry().topLeft(); // По-прежнему представляет верхний левый угол всего экрана.
qDebug() << "mouseStartPoint" << mouseStartPoint.x() << mouseStartPoint.y();
qDebug() << "windowTopLeftPoint" << windowTopLeftPoint.x() << windowTopLeftPoint.y();
}
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
if (m_bDrag) {
// Получить расстояние, пройденное мышью
QPoint distance = event->globalPos() - mouseStartPoint;
// QPoint distance = event->pos() - mouseStartPoint;
// Изменить положение окна
this->move(windowTopLeftPoint + distance);
qDebug() << "move" << windowTopLeftPoint + distance;
}
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_bDrag = false;
}
}
// тащитьдействовать--end
Эффект следующий:
Нажмите выбиратьдокумент
кнопка,Выберите документ для перекодирования,Вы можете проанализировать соответствующую информацию выбранного документа.
void Widget::on_pushButton_AddFile_clicked()
{
// Определите класс диалогового окна документа
QFileDialog *fileDialog = new QFileDialog(this);
// Определить заголовок диалогового окна документа
fileDialog->setWindowTitle(tr("Открытьдокумент")); // Функция tr(): Qt автоматически выберет соответствующий документ перевода на основе текущей языковой среды и переведет строку на соответствующий язык.
// Установить путь по умолчанию
fileDialog->setDirectory(".");
// Установить фильтр документов
fileDialog->setNameFilter(tr("video(*.mp4 *.flv *.mkv);;All files(*.*)"));
// В настройках можно выбрать несколько документов. По умолчанию можно выбрать только один документ. QFileDialog::ExistingFiles
fileDialog->setFileMode(QFileDialog::ExistingFile);
// Установить режим просмотра
fileDialog->setViewMode(QFileDialog::Detail);
if (fileDialog->exec()) {
QString strFileName = fileDialog->selectedFiles()[0];
qDebug() << strFileName;
QFileInfo fileinfo;
fileinfo = QFileInfo(strFileName);
// Вставить элемент данных
ui->tableWidget_FileList->setRowCount(1);
ui->tableWidget_FileList->setItem(0, 0, new QTableWidgetItem(fileinfo.fileName())); // документ名 ui->tableWidget_FileList->setItem(0, 1, new QTableWidgetItem(fileinfo.suffix())); // суффикс
AVGeneralMediaInfo avmi;
std::string str = strFileName.toStdString();
const char *chFilename = str.c_str();
get_avgeneral_mediainfo(&avmi, chFilename);
ui->tableWidget_FileList->setItem(0, 2, new QTableWidgetItem(QString(QLatin1String(avmi.videoCodecName))));
ui->tableWidget_FileList->setItem(0, 3, new QTableWidgetItem(QString(QLatin1String(avmi.audioCodecName))));
char chDuration[128] = {0};
sprintf(chDuration, "%lld", avmi.duration);
ui->tableWidget_FileList->setItem(0, 4, new QTableWidgetItem(QString(QLatin1String(chDuration))));
ui->tableWidget_FileList->setItem(0, 5, new QTableWidgetItem(strFileName));
}
}
Эффект следующий:
tcworkthread.h
#ifndef TCWORKTHREAD_H
#define TCWORKTHREAD_H
#include <QThread>
extern "C" {
#include "ffmpeg.h"
}
#define MAX_CMDLINE_ARGC_COUNT 100
// Параметры транскодирования
typedef struct __TCParams {
char inFilename[512];
char videoCodecName[256];
char audioCodecName[256];
char muxerName[256];
// Определена конструкция без параметров function__TCParams(), в которой вызывается закрытая функция-член с именем __init().
// Функция конструктора будет автоматически вызываться при создании экземпляра структуры, поэтому при создании объекта TCParams функция __init() будет автоматически выполнена.
__TCParams() {
__init();
}
void __init() {
memset(inFilename, 0, 512);
memset(videoCodecName, 0, 256);
memset(audioCodecName, 0, 256);
memset(muxerName, 0, 256);
}
} TCParams;
class TCWorkThread : public QThread
{
public:
TCWorkThread();
private:
virtual void run(); // поток обработки задач
TCParams *m_pTCParams;
public:
int workCount; // считать
void SetTCParams(TCParams *params);
signals:
public slots:
};
tcworkthread.c
#include "tcworkthread.h"
#include <QDebug>
TCWorkThread::TCWorkThread()
{
workCount = 0;
m_pTCParams = nullptr;
}
void TCWorkThread::SetTCParams(TCParams *params)
{
m_pTCParams = params;
}
// run() 重新выполнить
void TCWorkThread::run()
{
if (m_pTCParams == nullptr) {
return;
}
// by lp, все параметры жестко закодированы и предназначены только для справки.
char* arrParams[MAX_CMDLINE_ARGC_COUNT] = { 0 };
for (int k = 0; k < MAX_CMDLINE_ARGC_COUNT; k++) {
arrParams[k] = new char[1024]();
}
char strOutName[512] = {0};
strcpy(arrParams[0], "QtVideoConverter.exe");
strcpy(arrParams[1], "-i");
strcpy(arrParams[2], m_pTCParams->inFilename);
strcpy(arrParams[3], "-vcodec");
strcpy(arrParams[4], m_pTCParams->videoCodecName);
strcpy(arrParams[5], "-acodec");
strcpy(arrParams[6], m_pTCParams->audioCodecName);
strcpy(arrParams[7], "-y");
sprintf(strOutName, "SampleVideo_1280x720_20mb.%s", m_pTCParams->muxerName);
strcpy(arrParams[8], strOutName);
// Подготовьте параметры
main_ffmpeg431(9, arrParams);
for (int k = 0; k < MAX_CMDLINE_ARGC_COUNT; k++) {
delete[] arrParams[k]; // Не забудьте освободить выделенную память
arrParams[k] = NULL;
}
}
// Функция обработки событий таймера
// Получайте информацию о ходе транскодирования в реальном времени
// Текущий прогресс 1.00 Когда, killTimer
void Widget::timerEvent(QTimerEvent *event)
{
int nPrg = (int)(get_tc_progress() * 100);
qDebug() << "progress:" << nPrg;
ui->progressBar_tcprg->setValue(nPrg);
if (nPrg >= 100) {
killTimer(m_TimerID1);
}
}
будет местный mp3 документ Конвертировать в flv документ
Прикреплен веб-сайт с шестнадцатеричными цветовыми кодами.:Шестнадцатеричные таблицы цветового кода, диаграммы и палитры