Qt FLV 播放器开发 (C++实现)
·
Qt FLV 播放器开发 (C++实现)
以下是使用 Qt 和 C++ 开发 FLV 文件播放器的完整实现方案:
1. 核心组件选择
方案一:使用 QtMultimedia + 自定义解析(推荐)
方案二:集成 FFmpeg 库
2. 项目配置 (.pro 文件)
QT += core gui multimedia multimediawidgets
CONFIG += c++17
# 如果需要使用FFmpeg
unix:!macx {
LIBS += -lavcodec -lavformat -lavutil -lswscale
}
win32 {
LIBS += -lavcodec.lib -lavformat.lib -lavutil.lib -lswscale.lib
}
3. 基础播放器类头文件
// flvplayer.h
#ifndef FLVPLAYER_H
#define FLVPLAYER_H
#include <QMainWindow>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QFileDialog>
#include <QSlider>
#include <QPushButton>
#include <QLabel>
class FLVPlayer : public QMainWindow
{
Q_OBJECT
public:
FLVPlayer(QWidget *parent = nullptr);
~FLVPlayer();
private slots:
void openFile();
void play();
void pause();
void stop();
void onPositionChanged(qint64 position);
void onDurationChanged(qint64 duration);
void seek(int position);
private:
void setupUI();
void setupConnections();
bool isFLVFile(const QString &filePath);
QMediaPlayer *mediaPlayer;
QVideoWidget *videoWidget;
QSlider *positionSlider;
QPushButton *openButton;
QPushButton *playButton;
QPushButton *pauseButton;
QPushButton *stopButton;
QLabel *timeLabel;
};
#endif // FLVPLAYER_H
4. 播放器实现文件
// flvplayer.cpp
#include "flvplayer.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTime>
#include <QFileInfo>
FLVPlayer::FLVPlayer(QWidget *parent)
: QMainWindow(parent)
{
setupUI();
setupConnections();
mediaPlayer = new QMediaPlayer(this);
mediaPlayer->setVideoOutput(videoWidget);
setWindowTitle("FLV 播放器");
resize(800, 600);
}
FLVPlayer::~FLVPlayer()
{
}
void FLVPlayer::setupUI()
{
videoWidget = new QVideoWidget(this);
setCentralWidget(videoWidget);
// 控制按钮
openButton = new QPushButton("打开文件", this);
playButton = new QPushButton("播放", this);
pauseButton = new QPushButton("暂停", this);
stopButton = new QPushButton("停止", this);
// 进度条
positionSlider = new QSlider(Qt::Horizontal, this);
positionSlider->setRange(0, 0);
// 时间标签
timeLabel = new QLabel("00:00:00 / 00:00:00", this);
// 布局
QHBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->addWidget(openButton);
controlLayout->addWidget(playButton);
controlLayout->addWidget(pauseButton);
controlLayout->addWidget(stopButton);
controlLayout->addWidget(positionSlider);
controlLayout->addWidget(timeLabel);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(videoWidget);
mainLayout->addLayout(controlLayout);
QWidget *centralWidget = new QWidget(this);
centralWidget->setLayout(mainLayout);
setCentralWidget(centralWidget);
}
void FLVPlayer::setupConnections()
{
connect(openButton, &QPushButton::clicked, this, &FLVPlayer::openFile);
connect(playButton, &QPushButton::clicked, this, &FLVPlayer::play);
connect(pauseButton, &QPushButton::clicked, this, &FLVPlayer::pause);
connect(stopButton, &QPushButton::clicked, this, &FLVPlayer::stop);
connect(positionSlider, &QSlider::sliderMoved, this, &FLVPlayer::seek);
}
void FLVPlayer::openFile()
{
QString fileName = QFileDialog::getOpenFileName(this,
"打开FLV文件", "", "FLV文件 (*.flv);;所有文件 (*.*)");
if (!fileName.isEmpty() && isFLVFile(fileName)) {
mediaPlayer->setMedia(QUrl::fromLocalFile(fileName));
play();
}
}
bool FLVPlayer::isFLVFile(const QString &filePath)
{
QFileInfo fileInfo(filePath);
return fileInfo.suffix().toLower() == "flv";
}
void FLVPlayer::play()
{
mediaPlayer->play();
}
void FLVPlayer::pause()
{
mediaPlayer->pause();
}
void FLVPlayer::stop()
{
mediaPlayer->stop();
}
void FLVPlayer::onPositionChanged(qint64 position)
{
positionSlider->setValue(position);
QTime currentTime((position / 3600000) % 60, (position / 60000) % 60,
(position / 1000) % 60, position % 1000);
QTime totalTime((mediaPlayer->duration() / 3600000) % 60,
(mediaPlayer->duration() / 60000) % 60,
(mediaPlayer->duration() / 1000) % 60,
mediaPlayer->duration() % 1000);
QString format = "hh:mm:ss";
if (mediaPlayer->duration() > 3600000) {
format = "hh:mm:ss";
}
timeLabel->setText(currentTime.toString(format) + " / " +
totalTime.toString(format));
}
void FLVPlayer::onDurationChanged(qint64 duration)
{
positionSlider->setRange(0, duration);
}
void FLVPlayer::seek(int position)
{
mediaPlayer->setPosition(position);
}
5. 主函数
// main.cpp
#include "flvplayer.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 设置应用程序信息
QApplication::setApplicationName("FLV Player");
QApplication::setApplicationVersion("1.0");
QApplication::setOrganizationName("YourCompany");
FLVPlayer player;
player.show();
return app.exec();
}
6. 高级功能:使用 FFmpeg 增强
如果需要更底层的控制,可以集成 FFmpeg:
// ffmpeghandler.h
#ifndef FFMPEGHANDLER_H
#define FFMPEGHANDLER_H
#include <QObject>
#include <QImage>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
class FFmpegHandler : public QObject
{
Q_OBJECT
public:
explicit FFmpegHandler(QObject *parent = nullptr);
~FFmpegHandler();
bool openFile(const QString &filename);
void closeFile();
QImage getNextFrame();
bool seek(qint64 position);
signals:
void frameReady(const QImage &frame);
private:
AVFormatContext *formatContext;
AVCodecContext *codecContext;
int videoStreamIndex;
SwsContext *swsContext;
};
#endif // FFMPEGHANDLER_H
7. 自定义视频渲染器
// customvideowidget.h
#ifndef CUSTOMVIDEOWIDGET_H
#define CUSTOMVIDEOWIDGET_H
#include <QWidget>
#include <QImage>
class CustomVideoWidget : public QWidget
{
Q_OBJECT
public:
explicit CustomVideoWidget(QWidget *parent = nullptr);
public slots:
void setFrame(const QImage &frame);
protected:
void paintEvent(QPaintEvent *event) override;
private:
QImage currentFrame;
};
#endif // CUSTOMVIDEOWIDGET_H
// customvideowidget.cpp
#include "customvideowidget.h"
#include <QPaintEvent>
#include <QPainter>
CustomVideoWidget::CustomVideoWidget(QWidget *parent)
: QWidget(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
void CustomVideoWidget::setFrame(const QImage &frame)
{
currentFrame = frame;
update(); // 触发重绘
}
void CustomVideoWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
if (!currentFrame.isNull()) {
// 保持宽高比缩放
QImage scaled = currentFrame.scaled(size(), Qt::KeepAspectRatio,
Qt::SmoothTransformation);
painter.drawImage((width() - scaled.width()) / 2,
(height() - scaled.height()) / 2, scaled);# Qt FLV 播放器开发 (C++实现)
以下是使用 Qt 和 C++ 开发 FLV 文件播放器的完整实现方案:
## 1. 核心组件选择
### 方案一:使用 QtMultimedia + 自定义解析(推荐)
### 方案二:集成 FFmpeg 库
## 2. 项目配置 (.pro 文件)
```qmake
QT += core gui multimedia multimediawidgets
CONFIG += c++17
# 如果需要使用FFmpeg
unix:!macx {
LIBS += -lavcodec -lavformat -lavutil -lswscale
}
win32 {
LIBS += -lavcodec.lib -lavformat.lib -lavutil.lib -lswscale.lib
}
3. 基础播放器类头文件
// flvplayer.h
#ifndef FLVPLAYER_H
#define FLVPLAYER_H
#include <QMainWindow>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QFileDialog>
#include <QSlider>
#include <QPushButton>
#include <QLabel>
class FLVPlayer : public QMainWindow
{
Q_OBJECT
public:
FLVPlayer(QWidget *parent = nullptr);
~FLVPlayer();
private slots:
void openFile();
void play();
void pause();
void stop();
void onPositionChanged(qint64 position);
void onDurationChanged(qint64 duration);
void seek(int position);
private:
void setupUI();
void setupConnections();
bool isFLVFile(const QString &filePath);
QMediaPlayer *mediaPlayer;
QVideoWidget *videoWidget;
QSlider *positionSlider;
QPushButton *openButton;
QPushButton *playButton;
QPushButton *pauseButton;
QPushButton *stopButton;
QLabel *timeLabel;
};
#endif // FLVPLAYER_H
4. 播放器实现文件
// flvplayer.cpp
#include "flvplayer.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTime>
#include <QFileInfo>
FLVPlayer::FLVPlayer(QWidget *parent)
: QMainWindow(parent)
{
setupUI();
setupConnections();
mediaPlayer = new QMediaPlayer(this);
mediaPlayer->setVideoOutput(videoWidget);
setWindowTitle("FLV 播放器");
resize(800, 600);
}
FLVPlayer::~FLVPlayer()
{
}
void FLVPlayer::setupUI()
{
videoWidget = new QVideoWidget(this);
setCentralWidget(videoWidget);
// 控制按钮
openButton = new QPushButton("打开文件", this);
playButton = new QPushButton("播放", this);
pauseButton = new QPushButton("暂停", this);
stopButton = new QPushButton("停止", this);
// 进度条
positionSlider = new QSlider(Qt::Horizontal, this);
positionSlider->setRange(0, 0);
// 时间标签
timeLabel = new QLabel("00:00:00 / 00:00:00", this);
// 布局
QHBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->addWidget(openButton);
controlLayout->addWidget(playButton);
controlLayout->addWidget(pauseButton);
controlLayout->addWidget(stopButton);
controlLayout->addWidget(positionSlider);
controlLayout->addWidget(timeLabel);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(videoWidget);
mainLayout->addLayout(controlLayout);
QWidget *centralWidget = new QWidget(this);
centralWidget->setLayout(mainLayout);
setCentralWidget(centralWidget);
}
void FLVPlayer::setupConnections()
{
connect(openButton, &QPushButton::clicked, this, &FLVPlayer::openFile);
connect(playButton, &QPushButton::clicked, this, &FLVPlayer::play);
connect(pauseButton, &QPushButton::clicked, this, &FLVPlayer::pause);
connect(stopButton, &QPushButton::clicked, this, &FLVPlayer::stop);
connect(positionSlider, &QSlider::sliderMoved, this, &FLVPlayer::seek);
}
void FLVPlayer::openFile()
{
QString fileName = QFileDialog::getOpenFileName(this,
"打开FLV文件", "", "FLV文件 (*.flv);;所有文件 (*.*)");
if (!fileName.isEmpty() && isFLVFile(fileName)) {
mediaPlayer->setMedia(QUrl::fromLocalFile(fileName));
play();
}
}
bool FLVPlayer::isFLVFile(const QString &filePath)
{
QFileInfo fileInfo(filePath);
return fileInfo.suffix().toLower() == "flv";
}
void FLVPlayer::play()
{
mediaPlayer->play();
}
void FLVPlayer::pause()
{
mediaPlayer->pause();
}
void FLVPlayer::stop()
{
mediaPlayer->stop();
}
void FLVPlayer::onPositionChanged(qint64 position)
{
positionSlider->setValue(position);
QTime currentTime((position / 3600000) % 60, (position / 60000) % 60,
(position / 1000) % 60, position % 1000);
QTime totalTime((mediaPlayer->duration() / 3600000) % 60,
(mediaPlayer->duration() / 60000) % 60,
(mediaPlayer->duration() / 1000) % 60,
mediaPlayer->duration() % 1000);
QString format = "hh:mm:ss";
if (mediaPlayer->duration() > 3600000) {
format = "hh:mm:ss";
}
timeLabel->setText(currentTime.toString(format) + " / " +
totalTime.toString(format));
}
void FLVPlayer::onDurationChanged(qint64 duration)
{
positionSlider->setRange(0, duration);
}
void FLVPlayer::seek(int position)
{
mediaPlayer->setPosition(position);
}
5. 主函数
// main.cpp
#include "flvplayer.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 设置应用程序信息
QApplication::setApplicationName("FLV Player");
QApplication::setApplicationVersion("1.0");
QApplication::setOrganizationName("YourCompany");
FLVPlayer player;
player.show();
return app.exec();
}
6. 高级功能:使用 FFmpeg 增强
如果需要更底层的控制,可以集成 FFmpeg:
// ffmpeghandler.h
#ifndef FFMPEGHANDLER_H
#define FFMPEGHANDLER_H
#include <QObject>
#include <QImage>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
class FFmpegHandler : public QObject
{
Q_OBJECT
public:
explicit FFmpegHandler(QObject *parent = nullptr);
~FFmpegHandler();
bool openFile(const QString &filename);
void closeFile();
QImage getNextFrame();
bool seek(qint64 position);
signals:
void frameReady(const QImage &frame);
private:
AVFormatContext *formatContext;
AVCodecContext *codecContext;
int videoStreamIndex;
SwsContext *swsContext;
};
#endif // FFMPEGHANDLER_H
7. 自定义视频渲染器
// customvideowidget.h
#ifndef CUSTOMVIDEOWIDGET_H
#define CUSTOMVIDEOWIDGET_H
#include <QWidget>
#include <QImage>
class CustomVideoWidget : public QWidget
{
Q_OBJECT
public:
explicit CustomVideoWidget(QWidget *parent = nullptr);
public slots:
void setFrame(const QImage &frame);
protected:
void paintEvent(QPaintEvent *event) override;
private:
QImage currentFrame;
};
#endif // CUSTOMVIDEOWIDGET_H
// customvideowidget.cpp
#include "customvideowidget.h"
#include <QPaintEvent>
#include <QPainter>
CustomVideoWidget::CustomVideoWidget(QWidget *parent)
: QWidget(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}
void CustomVideoWidget::setFrame(const QImage &frame)
{
currentFrame = frame;
update(); // 触发重绘
}
void CustomVideoWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
if (!currentFrame.isNull()) {
// 保持宽高比缩放
QImage scaled = currentFrame.scaled(size(), Qt::KeepAspectRatio,
Qt::SmoothTransformation);
painter.drawImage((width() - scaled.width()) / 2,
(height() - scaled.height()) / 2, scaled);
} else {
painter.fillRect(rect(), Qt::black);
painter.setPen(Qt::white);
painter.drawText(rect(), Qt::AlignCenter, "无视频信号");
}
}
8. 构建和运行
安装依赖(Ubuntu)
sudo apt-get install qtmultimedia5-dev libavcodec-dev libavformat-dev libswscale-dev
项目构建
qmake
make
./FLVPlayer
9. 功能扩展建议
- 播放列表支持:添加多个 FLV 文件播放队列
- 音量控制:添加音量滑块
- 全屏模式:支持全屏播放
- 快捷键:添加键盘控制(空格播放/暂停,ESC退出等)
- 网络流支持:支持 RTMP/HTTP FLV 流播放
- 硬件加速:使用 GPU 加速解码
这个实现提供了基本的 FLV 文件播放功能。对于更复杂的需求,建议使用专业的媒体框架如 VLCKit 或集成更完整的 FFmpeg 解决方案。 } else { painter.fillRect(rect(), Qt::black); painter.setPen(Qt::white); painter.drawText(rect(), Qt::AlignCenter, "无视频信号"); } }
## 8. 构建和运行
### 安装依赖(Ubuntu)
```bash
sudo apt-get install qtmultimedia5-dev libavcodec-dev libavformat-dev libswscale-dev
项目构建
qmake
make
./FLVPlayer
9. 功能扩展建议
- 播放列表支持:添加多个 FLV 文件播放队列
- 音量控制:添加音量滑块
- 全屏模式:支持全屏播放
- 快捷键:添加键盘控制(空格播放/暂停,ESC退出等)
- 网络流支持:支持 RTMP/HTTP FLV 流播放
- 硬件加速:使用 GPU 加速解码
这个实现提供了基本的 FLV 文件播放功能。对于更复杂的需求,建议使用专业的媒体框架如 VLCKit 或集成更完整的 FFmpeg 解决方案。
更多推荐

所有评论(0)