Qt-视频播放器

一、概述

本项目使用 QMediaPlayerQAudioOutput 分离的音频架构采用 QVideoWidget 作为视频输出组件,为Qt6风格语法。项目结构简单,适合初学者或想熟悉Qt6新风格的程序员。

仓库:https://github.com/orpheanlive/Qt-video.git

二、内容

.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMediaPlayer>
#include <QAudioOutput>
#include <QVideoWidget>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    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

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中的videoWidget
    player->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);
}
相关推荐
Larry_Yanan4 小时前
Qt多进程(三)QLocalSocket
开发语言·c++·qt·ui
醒过来摸鱼4 小时前
Java classloader
java·开发语言·python
superman超哥4 小时前
仓颉语言中元组的使用:深度剖析与工程实践
c语言·开发语言·c++·python·仓颉
小鸡吃米…5 小时前
Python - 继承
开发语言·python
JIngJaneIL5 小时前
基于java+ vue农产投入线上管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
祁思妙想5 小时前
Python中的FastAPI框架的设计特点和性能优势
开发语言·python·fastapi
唐装鼠5 小时前
rust自动调用Deref(deepseek)
开发语言·算法·rust
Lucas555555555 小时前
现代C++四十不惑:AI时代系统软件的基石与新征程
开发语言·c++·人工智能
源代码•宸5 小时前
goframe框架签到系统项目(BITFIELD 命令详解、Redis Key 设计、goframe 框架教程、安装MySQL)
开发语言·数据库·经验分享·redis·后端·mysql·golang
吃喝不愁霸王餐APP开发者6 小时前
Java后端系统对接第三方外卖API时的幂等性设计与重试策略实践
java·开发语言