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

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

QT版本:5.11.1

视频播放器成效:

image.gif 编辑

视频播放器功能:

       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)

image.gif 编辑

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

image.gif 编辑

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

image.gif

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")));
}

image.gif

ui设计:

image.gif 编辑

缺点:

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

整合资源包地址:

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

相关文章
|
2月前
【Qt 学习笔记】使用QtCreator创建及运行项目 | 项目初始代码解释
【Qt 学习笔记】使用QtCreator创建及运行项目 | 项目初始代码解释
208 1
|
2月前
|
存储 C语言 Windows
音视频使用qt测试ffmpeg接口时无法运行
音视频使用qt测试ffmpeg接口时无法运行
67 0
|
8月前
|
存储 Cloud Native API
C++ QT监测可执行文件exe是否运行
C++ QT监测可执行文件exe是否运行
|
2月前
|
编译器
QT creator开发环境下 界面更改后运行程序不能实时更新或者在源文件添加该控件后无法编译的问题
在使用QT Creator开发界面的过程中,偶尔会出现添加控件后,运行程序后,界面控件无法更新的情况,或者在源文件使用该控件却出现无法编译的情况,使用QT Creator 4.8.2也会出现这个情况,也不知道这种情况会不会在以后有所改善。
92 0
|
2月前
|
SQL 安全 数据库连接
【Qt运行流程详解】从启动到事件循环的深入解读
【Qt运行流程详解】从启动到事件循环的深入解读
196 2
|
10月前
|
Ubuntu 编译器 网络安全
RK3568开发笔记(七):在宿主机ubuntu上搭建Qt交叉编译开发环境,编译一个Demo,目标板运行Demo测试
在之前的博文中已经搭建好了一个比较完善的ubuntu宿主机,都很完善了但是发现没有Qt交叉编译开发环境,所以还需要搭建一套Qt交叉编译开发环境。
如何解决Qt工程在其他电脑上无法运行的问题!(error: cannot open C:\Users???\AppData\Local\Temp\main.obj.5136.0.jom)
如何解决Qt工程在其他电脑上无法运行的问题!(error: cannot open C:\Users???\AppData\Local\Temp\main.obj.5136.0.jom)
|
编译器 C++ Windows
Qt程序运行依赖环境打包方法:windeployqt方法
3分钟学会Qt程序运行依赖环境打包方法:windeployqt方法!
356 0
Qt程序运行依赖环境打包方法:windeployqt方法
|
计算机视觉
Qt 配置好OpenCV运行报错 The process was ended forcefully. exe Crashed.
Qt 配置好OpenCV运行报错 The process was ended forcefully. exe Crashed.
439 0
Qt 配置好OpenCV运行报错 The process was ended forcefully. exe Crashed.
|
XML C语言 数据格式
CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面
CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面
CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面

热门文章

最新文章