QT 使用QMediaPlayer实现的简易视频播放器
效果如下:
功能点
- 播放指定视频
- 点击屏幕暂停/播放
- 开始/暂停/重置视频
- 拖拽到指定位置播放
类介绍
- 需要在配置文件中加入Multimedia, MultimediaWidgets这俩个库。
- Multimedia:提供了一套用于处理音频、视频、摄像头和广播数据的API。
- MultimediaWidgets:提供了一些与多媒体相关的图形界面组件。
- QVideoProbe是Qt多媒体模块中的一个类,它用于监控视频流的输出。这个类允许你接收视频帧的数据,而不需要直接与视频输出设备交互。
- QMediaPlayer 使用生产者-消费者模型来处理媒体内容。它从媒体源(如文件或网络流)获取数据,然后通过播放控制接口(如播放、暂停、停止)和播放状态接口(如当前播放位置、总时长)来控制媒体内容的播放。
- 使用 QMediaPlayer时,通常需要将其与一个或多个媒体输出组件结合使用,例如QVideoWidget用于视频播放,QAudioOutput用于音频播放。
注意:在Qt6中使用QMediaPlayer
时,使用的是setSource
函数设置视频资源,而Qt5中并没有这个函数,使用的是setMedia
函数。而且有个非常坑的地方,Qt6设置完QVideoWidget
直接使用没有问题,而Qt5就会存在问题。
信息栏会报错:
DirectShowPlayerService::doRender: Unresolved error code 0x80040266
在window上需安装LAV解码器的,并放在Qt的安装目录下。
在Linux上个人验证并不需要安装
解决办法:QT无法播放视频:报错:DirectShowPlayerService::doRender: Unresolved error code 0x80040266-CSDN博客
代码介绍
我们需要在pro文件中先添加:
随后我们添加一个C++类,基类选择QVideoWidget,来定义一些鼠标和键盘事件:
qmyselfvideo.h
#include<QVideoWidget>
#include<QObject>
#include<QWidget>
#include<QMediaPlayer>
#include<QKeyEvent>
#include<QMouseEvent>
class QMySelfVideo : public QVideoWidget
{
public:
QMySelfVideo(QWidget *parent=nullptr);
void SetMediaPlayer(QMediaPlayer *player);
private:
QMediaPlayer *theplayer;
protected:
void keyPressEvent(QKeyEvent *event);//键盘按键事件,当按键按下esc退出全屏
void mousePressEvent(QMouseEvent *event);//鼠标按键时间,点击暂停和播放
};
qmyselfvideo.cpp
#include "qmyselfvideo.h"
QMySelfVideo::QMySelfVideo(QWidget *parent):QVideoWidget(parent)
{
}
void QMySelfVideo::SetMediaPlayer(QMediaPlayer *player)
{
//设置播放器操作
theplayer=player;
}
void QMySelfVideo::keyPressEvent(QKeyEvent *event)//当播放器为全屏的时候,我们按下esc就可以退出全屏
{
if((event->key()==Qt::Key_Escape)&&(isFullScreen())){
setFullScreen(false);
event->accept();
QVideoWidget::keyPressEvent(event);
}
}
void QMySelfVideo::mousePressEvent(QMouseEvent *event)//按下左键设置播放和暂停
{
if(event->button()==Qt::LeftButton){
if(theplayer->state()==QMediaPlayer::PlayingState){
theplayer->pause();
}else{
theplayer->play();
}
}
QVideoWidget::mousePressEvent(event);
}
注意:我们要对graphicsView进行提升,提升的类名就是我们刚刚创建的C++类名,因为它的基类就是QVideoWidget。
代码初始化定义:
#include <QMainWindow>
#include"qmyselfvideo.h"
#include<QMediaPlayer>
#include<QMediaPlaylist>
#include<QVideoWidget>
#include<QFileDialog>
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;//播放器
QString drtTime;//视频文件长度
QString posTime;//播放视频的当前位置
private slots:
void OnStateButtonChanged(QMediaPlayer::State state);//控制按钮状态
void OndrtTimeChanged(qint64 drt);//视频文件时间长度,更新变化
void OnposTimeChanged(qint64 pos);//播放视频当前位置时间更新变化
}
定义我们所需要的量,以及一些我们需要的槽函数来处理一些变化。
代码功能分析:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
player=new QMediaPlayer(this);
player->setNotifyInterval(1000);
player->setVideoOutput(ui->graphicsView);//视频显示组件
ui->graphicsView->SetMediaPlayer(player);//设置显示组件的关联播放器
}
初始化,没什么好说的。
根据state的状态,来更新播放,暂停,停止按钮的状态:
void MainWindow::OnStateButtonChanged(QMediaPlayer::State state)
{
ui->pushButton_play->setEnabled(!(state==QMediaPlayer::PlayingState));
ui->pushButton_pause->setEnabled(state==QMediaPlayer::PlayingState);
ui->pushButton_stop->setEnabled(state==QMediaPlayer::PlayingState);
}
根据视频的长度来显示时长,格式:已经播放的时长/总时长。时间是:分:秒。将设置好的时长显示在我们添加的label中显示
void MainWindow::OndrtTimeChanged(qint64 drt)
{
ui->horizontalSlide_speedr->setMaximum(drt);
int sec=drt/1000;//总时长
int min=sec/60;//分
sec=sec%60;//秒
drtTime=QString::asprintf("%d:%d",min,sec);
ui->label_speed->setText(posTime+"|"+drtTime);
}
void MainWindow::OnposTimeChanged(qint64 pos)
{
if(ui->horizontalSlide_speedr->isSliderDown()){
return;//如果正在拖动滑动条,则直接退出
}
ui->horizontalSlide_speedr->setSliderPosition(pos);
int sec=pos/1000;
int min=sec/60;
sec=sec%60;
posTime=QString::asprintf("%d:%d",min,sec);
ui->label_speed->setText(posTime+"|"+drtTime);
}
槽函数链接:
connect(player,SIGNAL(stateChanged(QMediaPlayer::State)),this,SLOT(OnStateButtonChanged(QMediaPlayer::State)));
connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(OnposTimeChanged(qint64)));
connect(player,SIGNAL(durationChanged(qint64)),this,SLOT(OndrtTimeChanged(qint64)));
根据状态改变来连接相应的槽函数 。
按钮滑动条槽函数 :
void on_pushButton_open_clicked();//打开文件
void on_pushButton_play_clicked();//播放
void on_pushButton_pause_clicked();//暂停
void on_pushButton_stop_clicked();//停止
void on_pushButton_Volumn_clicked();//声音
void on_horizontalSlider_Volumn_valueChanged(int value);//声音滑动条
void on_horizontalSlide_speedr_valueChanged(int value);//进度条
对于open:
void MainWindow::on_pushButton_open_clicked()
{
QString currentpath=QDir::homePath();//获得系统当前目录
QString dlgtitle="请选择视频文件";
QString filter="所有文件(*.*);;mp4文件(*.mp4)";//文件过滤器
QString strfile=QFileDialog::getOpenFileName(this,dlgtitle,currentpath,filter);
if(strfile.isEmpty()){
return;
}
QFileInfo fileinfo(strfile);
ui->label_name->setText(fileinfo.fileName());
player->setMedia(QUrl::fromLocalFile(strfile));//设置播放文件
player->play();
}
我们首先获取文件的位置路径,在设置文件过滤器来获取我们所需要的MP4文件格式,最后设置播放文件进行播放。
其他开始,暂停等一些按钮槽函数:
void MainWindow::on_pushButton_play_clicked()
{
player->play();
}
void MainWindow::on_pushButton_pause_clicked()
{
player->pause();
}
void MainWindow::on_pushButton_stop_clicked()
{
player->stop();
}
void MainWindow::on_pushButton_Volumn_clicked()
{
bool bmute=player->isMuted();
player->setMuted(!bmute);
//根据是否静音来显示音量图标
if(bmute){
ui->pushButton_Volumn->setIcon(QIcon(":/icon/sound.png"));
}else{
ui->pushButton_Volumn->setIcon(QIcon(":/icon/mute.png"));
}
}
void MainWindow::on_horizontalSlider_Volumn_valueChanged(int value)
{
player->setVolume(value);
}
void MainWindow::on_horizontalSlide_speedr_valueChanged(int value)
{
player->setPosition(value);
}
总结:
只是一个简单视频播放器,博主能力有限还在学习当中。大家可自行尝试修改改进。