Qt+ffmpeg+libVlc 实现简单视频播放器

1.开发环境

vs2019 + Qt + ffmpeg + libVlic

2.功能模块

播放 暂停 停止 快进 后退 双击放大缩小 全屏 导入视频文件列表 进度条等基础功能的实现。

3.效果图

4.难点处理,获取每个视频图标当作listwidget的图标

代码示例:

cpp 复制代码
// 导入播放列表
void QVlcPlay::importPlaylist()
{
    QStringList filePaths = QFileDialog::getOpenFileNames(
        this,
        u8"选择视频文件",
        u8"C:/Users/86188/Desktop/素材", // 默认路径
        u8"视频文件 (*.mp4 *.avi *.mkv)"
    );

    if (filePaths.isEmpty()) {
        return; // 如果没有选择文件,直接返回
    }

    // 清空当前播放列表
    ui.listWidget->clear();
    playlist.clear();
    thumbnailMap.clear();

    // 设置 QListWidget 的图标大小
    ui.listWidget->setIconSize(QSize(64, 64)); // 设置所有图标的默认大小

    // 将文件添加到播放列表
    for (const QString& filePath : filePaths) {
        QFileInfo fileInfo(filePath);
        QString fileName = fileInfo.fileName(); // 获取文件名

        // 创建 ListWidgetItem
        QListWidgetItem* item = new QListWidgetItem(fileName);
        item->setData(Qt::UserRole, filePath); // 存储文件路径

        // 异步提取封面
        QtConcurrent::run([this, filePath, item]() {
            QPixmap thumbnail = extractVideoThumbnail(filePath);
            if (!thumbnail.isNull()) {
                // 调整图标大小
                thumbnail = thumbnail.scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation);

                // 在主线程中更新 UI
                QMetaObject::invokeMethod(this, [this, item, thumbnail]() {
                    item->setIcon(QIcon(thumbnail));
                    qDebug() << "Thumbnail set for:" << item->text();
                }, Qt::QueuedConnection);
            } else {
                qWarning() << "Failed to extract thumbnail for:" << filePath;
            }
        });

        // 添加到 ListWidget
        ui.listWidget->addItem(item);
        playlist.append(filePath); // 添加到 playlist
        thumbnailMap.insert(filePath, item); // 添加到映射
    }
}

QPixmap QVlcPlay::extractVideoThumbnail(const QString& filePath)
{
    // 临时封面文件路径
    QString thumbnailPath = QDir::tempPath() + "/thumbnail_" + QFileInfo(filePath).baseName() + ".jpg";
    qDebug() << "Extracting thumbnail to:" << thumbnailPath;

    // 使用 ffmpeg 提取封面
    QProcess ffmpegProcess;


    QString ffmpegPath = "C:/Users/86188/Desktop/ffmpeg/ffmpeg-7.1-essentials_build/bin/ffmpeg.exe"; 
    QStringList arguments;
    arguments << "-i" << filePath << "-ss" << "00:00:01" << "-vframes" << "1" << "-y" << thumbnailPath;
    ffmpegProcess.start(ffmpegPath, arguments);

    // 等待 ffmpeg 完成
    if (ffmpegProcess.waitForFinished(5000)) { 
        if (QFile::exists(thumbnailPath)) {
            qDebug() << "Thumbnail extracted successfully:" << thumbnailPath;
            QPixmap thumbnail(thumbnailPath);
            QFile::remove(thumbnailPath); 
            return thumbnail;
        }
        else {
            qWarning() << "Thumbnail file not found:" << thumbnailPath;
        }
    }
    else {
        qWarning() << "Failed to extract thumbnail:" << ffmpegProcess.errorString();
        qWarning() << "FFmpeg output:" << ffmpegProcess.readAllStandardOutput();
        qWarning() << "FFmpeg error:" << ffmpegProcess.readAllStandardError();
    }

    // 如果提取失败,返回默认图标
    return QPixmap(":/res/aa.png");
}

一、Qt框架相关

  1. QPixmap类

    • 用于处理图像。在这个函数中,通过QPixmap thumbnail(thumbnailPath);创建了一个QPixmap对象,它会从指定的路径(thumbnailPath)加载图像。这使得函数能够将提取出的视频封面以图像的形式返回。
  2. QDir类

    • 用于操作目录。QDir::tempPath()获取系统的临时目录路径。这是为了生成临时封面文件存储的位置,避免在程序的主目录或其他重要目录中产生临时文件,从而保持程序的整洁性和系统的稳定性。
  3. QFileInfo类

    • 用于获取文件信息。QFileInfo(filePath).baseName()获取输入视频文件路径(filePath)的文件基础名称(不包含扩展名和路径)。这样可以为临时封面文件生成一个与视频文件相关联但又具有唯一性的名称,例如视频文件名为"example.mp4",那么临时封面文件名可能是"thumbnail_example.jpg"。
  4. QProcess类

    • 用于启动外部程序。在这个函数中,通过QProcess ffmpegProcess;创建了一个QProcess对象来运行ffmpeg命令。ffmpegProcess.start(ffmpegPath, arguments);启动ffmpeg进程,其中ffmpegPath是ffmpeg可执行文件的路径,arguments是传递给ffmpeg的参数列表。这使得函数能够调用外部的ffmpeg工具来完成视频封面提取的任务,而不是在Qt程序内部实现复杂的视频处理逻辑。
  5. QFile类

    • 用于文件操作。QFile::exists(thumbnailPath)检查临时封面文件是否存在。如果存在,说明ffmpeg成功提取了封面,然后通过QFile::remove(thumbnailPath);删除这个临时文件,避免占用磁盘空间。同时,QPixmap(":/res/aa.png")使用QFile的资源系统功能,加载程序资源文件中的默认图标图像。
  6. qDebug()、qWarning()函数

    • 用于输出调试信息和警告信息。例如qDebug() << "Extracting thumbnail to:" << thumbnailPath;输出正在提取封面到指定路径的信息,方便开发者了解程序运行状态。而qWarning() << "Failed to extract thumbnail:" << ffmpegProcess.errorString();输出提取封面失败的警告信息,包括错误原因,便于调试和排查问题。

二、视频处理相关

  1. ffmpeg工具的使用

    • ffmpeg是一个非常强大的音视频处理工具。在这个函数中,通过构建参数列表arguments << "-i" << filePath << "-ss" << "00:00:01" << "-vframes" << "1" << "-y" << thumbnailPath;来指定ffmpeg的行为。其中,"-i"指定输入文件(视频文件路径),"-ss"指定从视频的第1秒开始提取封面("00:00:01"),"-vframes"指定提取1帧视频图像作为封面,"-y"表示覆盖输出文件(如果临时封面文件已存在)。这些参数组合起来使得ffmpeg能够从视频中提取出一张封面图像并保存到指定的临时路径。

三、其他知识点

  1. 字符串操作

    • 在构建临时封面文件路径QString thumbnailPath = QDir::tempPath() + "/thumbnail_" + QFileInfo(filePath).baseName() + ".jpg";时,使用了字符串拼接操作。通过将临时目录路径、固定前缀"thumbnail_"、视频文件基础名称和文件扩展名".jpg"拼接起来,生成一个完整的文件路径。这是基本的字符串处理技巧,在很多编程场景中都会用到,用于生成符合要求的字符串格式。
相关推荐
一只小灿灿1 分钟前
探索 C++ 与 LibUSB:开启 USB 设备交互的奇幻之旅
c++·交互·策略模式
KuaCpp11 分钟前
算法初学者(图的存储)链式前向星
c++·算法
编程小筑39 分钟前
R语言的语法糖
开发语言·后端·golang
Nil_cxc1 小时前
机器学习周报-GNN模型学习
人工智能·学习·机器学习
芝士就是力量啊 ೄ೨1 小时前
Kotlin 循环语句详解
android·java·开发语言·kotlin
Alex老夫子1 小时前
kotlin sortedBy 与sortedWith的区别
android·开发语言·kotlin
云端 架构师1 小时前
Python语言的编程范式
开发语言·后端·golang
bbqz0071 小时前
浅说 c++20 coroutine
c++·c++20·协程·coroutine·co_await·stackless
隼玉1 小时前
【STM32-学习笔记-9-】SPI通信
c语言·笔记·stm32·学习
云端 架构师2 小时前
Python语言的字符串处理
开发语言·后端·golang