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. 功能扩展建议

  1. 播放列表支持:添加多个 FLV 文件播放队列
  2. 音量控制:添加音量滑块
  3. 全屏模式:支持全屏播放
  4. 快捷键:添加键盘控制(空格播放/暂停,ESC退出等)
  5. 网络流支持:支持 RTMP/HTTP FLV 流播放
  6. 硬件加速:使用 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. 功能扩展建议

  1. 播放列表支持:添加多个 FLV 文件播放队列
  2. 音量控制:添加音量滑块
  3. 全屏模式:支持全屏播放
  4. 快捷键:添加键盘控制(空格播放/暂停,ESC退出等)
  5. 网络流支持:支持 RTMP/HTTP FLV 流播放
  6. 硬件加速:使用 GPU 加速解码

这个实现提供了基本的 FLV 文件播放功能。对于更复杂的需求,建议使用专业的媒体框架如 VLCKit 或集成更完整的 FFmpeg 解决方案。

更多推荐