QT:基于QMediaPlayer制作的视频播放器(最下方有整合包,可直接运行)

举报
笨笨小乌龟 发表于 2024/07/20 16:02:09 2024/07/20
【摘要】 ​@author: bbxwg@Qt_version:5.11.1@Time: 2024-07-05目录QT版本:5.11.1视频播放器成效:视频播放器功能:QMediaPlayer介绍:功能特性MainWindow.h:MainWindow.cpp:ui设计:缺点:整合资源包地址:QT版本:5.11.1视频播放器成效:​编辑视频播放器功能:        1. 支持外地导入文件,外地拖拽文...

@author: bbxwg

@Qt_version:5.11.1

@Time: 2024-07-05

目录

QT版本:5.11.1

视频播放器成效:

视频播放器功能:

QMediaPlayer介绍:

功能特性

MainWindow.h:

MainWindow.cpp:

ui设计:

缺点:

整合资源包地址:



QT版本:5.11.1

视频播放器成效:

编辑

视频播放器功能:

        1. 支持外地导入文件,外地拖拽文件到列表中

        2. 支持一键静音,一键返回上次音量

        3. 支持空格暂停播放,ESC关闭窗口

        4. 支持拖放进度条控制视频速度

        5. 支持倍速播放

        6. 支持一键清空列表

        7. 支持快进10S,快退10S

        8. 支持一键放大缩小

        9. 支持点击列表元素播放视频

因为QMediaPlayer需要解码器去解析视频,而QT并不自带,所以我们需要去下载一下。

百度网盘:

链接:https://pan.baidu.com/s/1EoGhiNDOGkwaiJzjuY1zNw?pwd=qwer 
提取码:qwer

GitHub:

Releases · Nevcairiel/LAVFilters (github.com)

编辑

安装在自己的QT目录下即可

编辑

QMediaPlayer介绍:

QMediaPlayer是Qt多媒体模块中的一个核心类,它提供了播放音频和视频内容的功能。这个类的设计旨在简化跨平台的媒体播放,使得开发者能够在多种操作系统(如Linux、Windows、macOS及移动平台)上轻松集成多媒体播放能力到他们的应用中,而无需关心底层实现细节。以下是关于QMediaPlayer的一些关键点:

功能特性

  • 媒体播放:支持播放各种音频和视频文件格式,支持的格式依赖于底层操作系统提供的解码器。例如,在Linux下通常使用GStreamer,Windows下使用DirectShow,Android和iOS则分别使用它们各自的多媒体框架。

  • 流媒体播放:除了本地文件,QMediaPlayer还能够播放网络流媒体资源,如HTTP直播流(HLS)、RTSP流等。

  • 状态管理:QMediaPlayer提供了多种状态枚举,如PlayingPausedStopped等,以及媒体状态(如LoadingMediaBufferingMediaStalledMedia),允许开发者监控播放器的当前状态。

  • 信号与槽:QMediaPlayer发出多种信号,如stateChanged()mediaStatusChanged(),开发者可以通过连接这些信号到自定义的槽函数,实现对播放事件的响应和控制。

  • 视频输出:为了显示视频内容,QMediaPlayer可以与QVideoWidget、QOpenGLWidget或自定义的QAbstractVideoSurface结合使用。

  • 音频输出:音频可以通过默认音频输出播放,也可以通过QAudioOutput类进行更细致的控制,比如调整音量、选择音频输出设备等。

  • 播放列表管理:虽然QMediaPlayer本身不直接管理播放列表,但它可以与QMimeData和QMediaPlaylist等类协作,实现播放列表功能。

  • 资源与缓冲:支持媒体资源的加载、缓冲管理以及错误处理,可以通过属性和信号监测缓冲进度和错误状态。

       我们还需要一个播放视频的组件,类似于被投屏的幕布,正是QVideoWidget,他可以接收QMediaPlayer解析的视频流。这里对于他仅仅只作用了接收的功能,在此就不细讲,大家有时间可以去了解一下。

MainWindow.h:
 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QtWidgets>
#include <QSlider>
#include <QMouseEvent>
#include <QFileDialog>
#include <QMediaPlayer>
#include <QVideoWidget>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    void MediaInit();
    void dragEnterEvent(QDragEnterEvent *event);
    void dragLeaveEvent(QDragLeaveEvent *event);
    void dragMoveEvent(QDragMoveEvent *event);
    void dropEvent(QDropEvent *event);
    ~MainWindow();

private slots:
    void on_actionimport_file_triggered();

    void on_Begin_clicked();

    void onItemDoubleClicked(QListWidgetItem * item);

    void showListWidgetMenuSlot(QPoint);

    void deleteAllData();

    void GetDuration(qint64);

    void upDateSlider(qint64);

    void slot_PlayError(QMediaPlayer::Error);

    void on_back_clicked();

    void on_advance_clicked();

    void ChangeVoice(int);

    void MoveVideo(int);

    void on_fullScreen_clicked();

    void on_volumeData_clicked();

    void on_action_h_Help_triggered();

    void keyPressEvent(QKeyEvent *event);

    void on_Speed_currentIndexChanged(const QString &arg1);

private:
    Ui::MainWindow *ui;
    QMediaPlayer *Player;
    QVideoWidget *videoWidget;
    QListWidget *DataList;
    QMenu *Menu;
    QAction *deleteAll;
    QString totalFormatTime;
    QString currentFormatTime;
    int back_volume = 0;
    int flag_back_volume = 0;
};

#endif // MAINWINDOW_H

MainWindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //初始化
    this->MediaInit();
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 初始化函数
void MainWindow::MediaInit() {

    this->setWindowTitle("乌龟牌播放器");
    this->setWindowIcon(QPixmap(":/Icon/Icon/tortoiseTitleIcon.png"));

    // 初始化变量
    Player = new QMediaPlayer(this);
    videoWidget = new QVideoWidget(this);
    DataList = new QListWidget(this);
    Menu = new QMenu(this);
    deleteAll = new QAction("删除全部", this);

    // 功能性设置
    DataList->setContextMenuPolicy(Qt::CustomContextMenu);
    Menu->addAction(deleteAll);
    ui->videoSlider->setSingleStep(0);
    ui->Begin->setDisabled(true);
    ui->back->setDisabled(true);
    ui->advance->setDisabled(true);
    this->setAcceptDrops(true);

    // ui布局
    this->DataList->setStyleSheet("QListView {	font: 25 9pt Microsoft YaHei;border: 15px solid white;border-radius: 10px;}"
                                  "QListView::item {height: 60px;}"
                                  "QListView::item:hover {background-color: transparent;padding: 10px;border-left: 3px solid rgb(130, 130, 130);}"
                                  "QListView::item:selected { background-color: transparent;color: black;padding: 10px;border-left: 3px solid black;}");

    ui->horizontalLayout->addWidget(videoWidget,10);
    ui->horizontalLayout->addWidget(DataList,0);
    ui->fullScreen->setIcon(QPixmap(":/Icon/Icon/magnify.png"));
    ui->fullScreen->setIconSize(QSize(20,20));
    ui->Begin->setIcon(QPixmap(":/Icon/Icon/begin.png"));
    ui->Begin->setIconSize(QSize(20,20));
    ui->back->setIcon(QPixmap(":/Icon/Icon/back.png"));
    ui->back->setIconSize(QSize(20,20));
    ui->advance->setIcon(QPixmap(":/Icon/Icon/advance.png"));
    ui->advance->setIconSize(QSize(20,20));
    ui->volumeData->setIcon(QPixmap(":/Icon/Icon/volumeHigh.png"));
    ui->volumeData->setIconSize(QSize(20,20));

    // 信号
    connect(DataList, &QListWidget::itemDoubleClicked, this, &MainWindow::onItemDoubleClicked);
    connect(DataList, SIGNAL(customContextMenuRequested(QPoint)),this, SLOT(showListWidgetMenuSlot(QPoint)));
    connect(deleteAll,SIGNAL(triggered()),this,SLOT(deleteAllData()));
    connect(Player, SIGNAL(durationChanged(qint64)), this, SLOT(GetDuration(qint64)));
    connect(Player, SIGNAL(positionChanged(qint64)), this, SLOT(upDateSlider(qint64)));
    connect(Player, SIGNAL(error(QMediaPlayer::Error)),this,SLOT(slot_PlayError(QMediaPlayer::Error)));
    connect(ui->volumeSlider, SIGNAL(valueChanged(int)), this, SLOT(ChangeVoice(int)));
    connect(ui->videoSlider, SIGNAL(sliderMoved(int)), this, SLOT(MoveVideo(int)));
}

void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    event->accept();
}
void MainWindow::dragLeaveEvent(QDragLeaveEvent *event)
{
    event->accept();
}
void MainWindow::dragMoveEvent(QDragMoveEvent *event)
{
    event->accept();
}
void MainWindow::dropEvent(QDropEvent *event)
{
    QString name;
    QList<QUrl> urls;
    QList<QUrl>::Iterator i;
    urls = event->mimeData()->urls();
    for(i = urls.begin(); i != urls.end(); ++i) {
        name = i->path();
        this->DataList->addItem(name);
    }

    Player->setMedia(QUrl::fromLocalFile(name));
    Player->setVideoOutput(videoWidget);
    Player->play();
}

// 错误提示
void MainWindow::slot_PlayError(QMediaPlayer::Error error) {
    QString text;
    if(QMediaPlayer::NoError==error)
    {
        text="正常解码!";
    }
    else if(QMediaPlayer::ResourceError==error)
    {
        text="媒体资源无法解析。";
    }
    else if(QMediaPlayer::FormatError==error)
    {
        text="不支持该媒体资源的格式,没有解码器!";
    }
    else if(QMediaPlayer::NetworkError==error)
    {
        text="发生网络错误。";
    }
    else if(QMediaPlayer::AccessDeniedError==error)
    {
        text="没有适当的权限来播放媒体资源。";
    }
    else if(QMediaPlayer::ServiceMissingError==error)
    {
        text="没有找到有效的播放服务,播放无法继续。";
    }

    QMessageBox::critical(this,"播放器提示",text,QMessageBox::Ok,QMessageBox::Ok);
}

// 更新进度条
void MainWindow::upDateSlider(qint64 position) {

    ui->Begin->setDisabled(false);
    ui->back->setDisabled(false);
    ui->advance->setDisabled(false);

    if(ui->videoSlider->isSliderDown()) {
        return;
    }

    double num_p = position;
    double num_d = Player->duration();

    ui->videoSlider->setSliderPosition(100 * num_p / num_d);

    QTime currentTime(0, 0, 0, 0);
    currentTime = currentTime.addMSecs(position);
    currentFormatTime = currentTime.toString("mm:ss");
    ui->BeginTime->setText(currentFormatTime);
}

// 获取视频时间信息
void MainWindow::GetDuration(qint64 duration) {
    QTime totalTime = QTime(0, 0, 0, 0);
    totalTime = totalTime.addMSecs(duration);
    totalFormatTime = totalTime.toString("mm:ss");
    ui->EndTime->setText(totalFormatTime);
}

void MainWindow::showListWidgetMenuSlot(QPoint) {
    Menu->exec(QCursor::pos());
}

// 清空列表
void MainWindow::deleteAllData() {
    DataList->clear();
    Player->stop();
    ui->Begin->setIcon(QPixmap(":/Icon/Icon/begin.png"));
    ui->Begin->setIconSize(QSize(20,20));
}

// 导入
void MainWindow::on_actionimport_file_triggered()
{
    QString strCurrentPath = QDir::homePath();
    QString stdDlgTitle = "请选择视频文件";
    QString strFilter = "MP4 File(*.mp4);;All File(*.*)";
    QString strAllFiles = QFileDialog::getOpenFileName(this, stdDlgTitle,
                                                       strCurrentPath,strFilter);

    if(strAllFiles.isEmpty()) {
        QMessageBox::information(this,"错误","打开视频文件失败,请重新检查",QMessageBox::Yes|QMessageBox::No);
        return;
    }

    QFileInfo fileInfos(strAllFiles);
    qDebug() << "File info: " << fileInfos.fileName() << ", path: " << fileInfos.filePath();

    DataList->addItem(fileInfos.filePath());

    Player->setMedia(QUrl::fromLocalFile(strAllFiles));
    Player->setVideoOutput(videoWidget);
    Player->play();
}

// 双击
void MainWindow::onItemDoubleClicked(QListWidgetItem * item) {
    QString itemStr = item->text();

    Player->setMedia(QUrl::fromLocalFile(itemStr));
    Player->setVideoOutput(videoWidget);
    Player->play();

}

// 开始/暂停
void MainWindow::on_Begin_clicked()
{
    if(Player->state() ==  QMediaPlayer::PlayingState) {
        ui->Begin->setIcon(QPixmap(":/Icon/Icon/begin.png"));
        Player->pause();
    } else {
        ui->Begin->setIcon(QPixmap(":/Icon/Icon/pause.png"));
        Player->play();
    }
}

// 回退
void MainWindow::on_back_clicked()
{
    qint64 currentpos = Player->position();
    Player->setPosition(currentpos - 10000);//在原来的基础上前进10s
}

// 前进
void MainWindow::on_advance_clicked()
{
    qint64 currentpos = Player->position();
    Player->setPosition(currentpos + 10000);//在原来的基础上前进10s
}

// 全屏
void MainWindow::on_fullScreen_clicked()
{
    if(this->isFullScreen()) {
        this->showNormal();
        ui->fullScreen->setIcon(QPixmap(":/Icon/Icon/magnify.png"));
    } else {
        this->showFullScreen();
        ui->fullScreen->setIcon(QPixmap(":/Icon/Icon/lessen.png"));
    }
}

// 倍速
void MainWindow::on_Speed_currentIndexChanged(const QString &arg1)
{
    Player->setPlaybackRate(arg1.toDouble());
}

// 一键静音
void MainWindow::on_volumeData_clicked()
{
    if(++flag_back_volume % 2 != 0) {
        back_volume = ui->volumeValue->text().toInt();
    }

    if(ui->volumeValue->text().toInt() != 0) {
        ui->volumeSlider->setValue(0);
        Player->setVolume(0);
        ui->volumeValue->setText(QString::number(0));
        ui->volumeData->setIcon(QPixmap(":/Icon/Icon/volumeCross.png"));
    } else {
        ui->volumeSlider->setValue(back_volume);
        Player->setVolume(back_volume);
        ui->volumeValue->setText(QString::number(back_volume));
        ui->volumeData->setIcon(QPixmap(":/Icon/Icon/volumeHigh.png"));
    }

}

// 更新音量
void MainWindow::ChangeVoice(int volumeData) {
    Player->setVolume(volumeData);
    ui->volumeValue->setText(QString::number(volumeData));
    if(volumeData == 0) {
        ui->volumeData->setIcon(QPixmap(":/Icon/Icon/volumeCross.png"));
    } else {
        ui->volumeData->setIcon(QPixmap(":/Icon/Icon/volumeHigh.png"));
    }
}

//更新视频进度
void MainWindow::MoveVideo(int videoData) {
    double num_d = Player->duration();
    Player->setPosition(videoData * 1000 * (num_d / 100000));

}


// 捕获键盘事件
void MainWindow::keyPressEvent(QKeyEvent *event) {
    qDebug() << event->key();
    switch (event->key()) {
    case Qt::Key_Escape:
        if(!this->isFullScreen()) {
            QMessageBox:: StandardButton result= QMessageBox::information(this, "information", "是否要关闭窗口?",QMessageBox::Yes|QMessageBox::No);
            if(result == QMessageBox::Yes) {
                this->close();
            }
        } else {
            on_fullScreen_clicked();
        }
        break;
    case Qt::Key_Space:
        on_Begin_clicked();
        break;
    default:
        break;
    }
}

void MainWindow::on_action_h_Help_triggered()
{
    QDesktopServices::openUrl(QUrl(QString("https://blog.csdn.net/LKHzzzzz?spm=1000.2115.3001.5343")));
}

ui设计:

编辑

缺点:

        我在最后的时候想实现一个鼠标预览并显示当前画面帧的功能,但是毕竟是QMediaPlayer解析的视频帧,而且QSlider并没有鼠标停留的这个信号,所以这两个类都需要我们去重写,虽然QMediaPlayer非常方便,但是在功能发展上确是有着不小的限制,如果我们使用一些协议类似于ffmpeg这种去解析感觉会更好,在解析速度优化上也可以更近一步。

整合资源包地址:

        微信关注嵌入式工程之家回复乌龟牌播放器即可获得整合包哦~

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。