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);
}
相关推荐
LawrenceLan几秒前
Flutter 零基础入门(十):final、const 与不可变数据
开发语言·flutter·dart
源代码•宸26 分钟前
Leetcode—1266. 访问所有点的最小时间【简单】
开发语言·后端·算法·leetcode·职场和发展·golang
遇见~未来30 分钟前
JavaScript数组全解析:从本质到高级技巧
开发语言·前端·javascript
南屿欣风30 分钟前
Sentinel 熔断规则 - 异常比例(order & product 示例)笔记
java·开发语言
u01040583637 分钟前
使用Java实现高性能的异步编程:CompletableFuture与Reactive Streams
java·开发语言
朔北之忘 Clancy44 分钟前
2020 年 6 月青少年软编等考 C 语言二级真题解析
c语言·开发语言·c++·学习·青少年编程·题解·尺取法
消失的旧时光-19431 小时前
C++ 中的 auto 与 nullptr:不是语法糖,而是类型系统升级
开发语言·c++
专注VB编程开发20年1 小时前
c#Type数组转成字符串的名称
java·开发语言
编程饭碗1 小时前
【多线程编程】
java·开发语言
vyuvyucd1 小时前
Python虚拟环境终极指南:venv到uv进阶
开发语言·python·uv