Qt-视频播放器
一、概述
本项目使用 QMediaPlayer 和 QAudioOutput 分离的音频架构采用 QVideoWidget 作为视频输出组件,为Qt6风格语法。项目结构简单,适合初学者或想熟悉Qt6新风格的程序员。
仓库:https://github.com/orpheanlive/Qt-video.git
二、内容
.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QMediaPlayer>
#include <QAudioOutput>
#include <QVideoWidget>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;QMediaPlayer *player;QAudioOutput *audioOutput;QString drtTime;QString posTime;private slots:void onPlaybackStateChanged(QMediaPlayer::PlaybackState state);void onDurationChanged(qint64 duration);void onPositionChanged(qint64 position);void onMediaStatusChanged(QMediaPlayer::MediaStatus status);void onErrorOccurred(QMediaPlayer::Error error, const QString &errorString);void on_file_clicked();void on_play_clicked();void on_pause_clicked();void on_stop_clicked();void on_sound_clicked();void onVolumeSliderChanged(int value);void onProgressSliderReleased();
};
#endif // MAINWINDOW_H
.cpp
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QFileDialog>
#include <QDir>
#include <QFileInfo>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 初始化媒体播放器player = new QMediaPlayer(this);audioOutput = new QAudioOutput(this);player->setAudioOutput(audioOutput);// 设置视频输出到UI中的videoWidgetplayer->setVideoOutput(ui->videoWidget);// 连接信号槽connect(player, &QMediaPlayer::playbackStateChanged, this, &MainWindow::onPlaybackStateChanged);connect(player, &QMediaPlayer::durationChanged, this, &MainWindow::onDurationChanged);connect(player, &QMediaPlayer::positionChanged, this, &MainWindow::onPositionChanged);connect(player, &QMediaPlayer::mediaStatusChanged, this, &MainWindow::onMediaStatusChanged);connect(player, &QMediaPlayer::errorOccurred, this, &MainWindow::onErrorOccurred);// 设置初始音量audioOutput->setVolume(0.7);// 初始化按钮状态ui->play->setEnabled(true);ui->pause->setEnabled(false);ui->stop->setEnabled(false);qDebug() << "Media player initialized successfully";
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::onPlaybackStateChanged(QMediaPlayer::PlaybackState state)
{qDebug() << "Playback state:" << state;switch (state) {case QMediaPlayer::StoppedState:ui->play->setEnabled(true);ui->pause->setEnabled(false);ui->stop->setEnabled(false);break;case QMediaPlayer::PlayingState:ui->play->setEnabled(false);ui->pause->setEnabled(true);ui->stop->setEnabled(true);break;case QMediaPlayer::PausedState:ui->play->setEnabled(true);ui->pause->setEnabled(false);ui->stop->setEnabled(true);break;default:break;}
}void MainWindow::onDurationChanged(qint64 duration)
{qDebug() << "Duration changed:" << duration;ui->progressSlider->setRange(0, duration);int sec = duration / 1000;int min = sec / 60;sec = sec % 60;int hour = min / 60;min = min % 60;if (hour > 0) {drtTime = QString::asprintf("%02d:%02d:%02d", hour, min, sec);} else {drtTime = QString::asprintf("%02d:%02d", min, sec);}ui->timeLabel->setText(posTime + " / " + drtTime);
}void MainWindow::onPositionChanged(qint64 position)
{if (!ui->progressSlider->isSliderDown()) {ui->progressSlider->setValue(position);}int sec = position / 1000;int min = sec / 60;sec = sec % 60;int hour = min / 60;min = min % 60;if (hour > 0) {posTime = QString::asprintf("%02d:%02d:%02d", hour, min, sec);} else {posTime = QString::asprintf("%02d:%02d", min, sec);}ui->timeLabel->setText(posTime + " / " + drtTime);
}void MainWindow::onMediaStatusChanged(QMediaPlayer::MediaStatus status)
{qDebug() << "Media status:" << status;
}void MainWindow::onErrorOccurred(QMediaPlayer::Error error, const QString &errorString)
{qDebug() << "Media player error:" << error << errorString;ui->fileNameLabel->setText("错误: " + errorString);
}void MainWindow::on_file_clicked()
{QString currentpath = QDir::currentPath();QString dlgtitle = "请选择视频文件";QString filter = "视频文件 (*.mp4 *.avi *.mkv *.mov *.wmv *.flv);;""所有文件 (*.*)";QString strfile = QFileDialog::getOpenFileName(this, dlgtitle, currentpath, filter);if (strfile.isEmpty()) {qDebug() << "No file selected";return;}QFileInfo fileinfo(strfile);QString fileName = fileinfo.fileName();ui->fileNameLabel->setText("文件: " + fileName);qDebug() << "Selected file:" << strfile;// 停止当前播放player->stop();// 设置媒体源QUrl fileUrl = QUrl::fromLocalFile(strfile);player->setSource(fileUrl);qDebug() << "Setting source to:" << fileUrl;}void MainWindow::on_play_clicked()
{player->play();}void MainWindow::on_pause_clicked()
{player->pause();
}void MainWindow::on_stop_clicked()
{player->stop();ui->progressSlider->setValue(0);posTime = "00:00";ui->timeLabel->setText(posTime + " / " + drtTime);
}void MainWindow::on_sound_clicked()
{bool muted = audioOutput->isMuted();audioOutput->setMuted(!muted);// 更新按钮文本if (audioOutput->isMuted()) {ui->sound->setText("静音");} else {ui->sound->setText("声音");}
}void MainWindow::onVolumeSliderChanged(int value)
{float volume = value / 100.0f;audioOutput->setVolume(volume);// 自动静音/取消静音if (value == 0 && !audioOutput->isMuted()) {audioOutput->setMuted(true);ui->sound->setText("静音");} else if (value > 0 && audioOutput->isMuted()) {audioOutput->setMuted(false);ui->sound->setText("声音");}
}void MainWindow::onProgressSliderReleased()
{qint64 position = ui->progressSlider->value();player->setPosition(position);
}
