简介:这份资源是面向Windows 64位平台、希望在Qt环境中集成VLC播放能力的开发者与爱好者的编译产物,基于Qt5.15.2与VLC3.0.14,采用mingw8.1.0_64工具链构建,可省去自行交叉编译的繁琐过程,直接用于学习Qt与VLC的界面集成方案。压缩包共399个文件,约43.28MB,以338个dll动态库为主,另含38个h头文件、14个cmake配置、4个a静态库及pc、qmltypes、qmldir等辅助文件,覆盖运行库、开发头文件与CMake查找配置,便于二次开发与工程引用。目前已有435人浏览学习。对于想研究VLC-Qt封装结构、QML与Widgets双端调用方式,或需要快速搭建可运行示例的读者,这份包体提供了较完整的库文件与配置线索,可作为集成调试与排错思路的参考起点。
1. 拿到 vlc-qt_build_mingw64_install.zip 之后:它到底是什么,能省掉哪一步
如果你在 Windows 上做过 Qt 播放器,大概率经历过这个循环:想用 libvlc 做内核,又不想自己写一遍事件循环和窗口句柄绑定,于是去找 VLC-Qt;找到之后发现官方给的预编译包要么是 MSVC 的,要么版本对不上,最后卡在“编译 VLC-Qt 本身”这一步。vlc-qt_build_mingw64_install.zip这个包名本身就说明了它的定位——用 MinGW-w64 工具链构建好的 VLC-Qt 安装产物,解压后直接拿到头文件、库和 CMake 配置,跳过从源码编译 VLC-Qt 的过程。
它解决的不是“怎么播放视频”这种问题,libvlc 自己就能播;它解决的是“怎么让 Qt 界面和 libvlc 之间的胶水层不用自己维护”。适合两类人:一类是要在 Qt Widgets 或 QML 里嵌播放器、又不想被平台差异拖住的桌面开发者;另一类是已经有一份 MinGW 构建环境、只差 VLC-Qt 这一环的工程。前提是你得先有匹配的 Qt MinGW 套件和一份可用的 libvlc 运行时,这个包只负责 VLC-Qt 这一层,不负责 VLC 本体。
2. 先对齐三样东西:Qt 套件、MinGW 版本、libvlc 运行时
2.1 为什么 MinGW 构建的 VLC-Qt 不能随便配 MSVC 的 Qt
VLC-Qt 是 C++ 库,编译产物里的符号修饰、异常模型、STL 布局都和工具链绑定。MinGW-w64 用的是 GCC 体系,MSVC 用的是另一套 ABI,两者生成的.dll和.a不能互相链接。你拿一个 MinGW 构建的libVLCQtCore.dll去配 MSVC 的 Qt,链接阶段就会报一堆 unresolved external symbol,而且报的符号名看起来像乱码,这就是 ABI 不匹配的典型表现。
所以第一步不是急着解压,而是确认你现有的 Qt 是 MinGW 版还是 MSVC 版。在 Qt Creator 里看 Kits 面板,编译器那一栏写的是GCC (x86_64-w64-mingw32)还是Microsoft Visual C++。如果是后者,这个包对你没用,要么换 Qt 套件,要么去找 MSVC 版的 VLC-Qt 构建产物。
2.2 用命令行确认 MinGW 与 Qt 的版本对应关系
MinGW-w64 有多个发行版(比如不同来源的 GCC 构建),Qt 官方安装器自带的 MinGW 和系统里单独装的 MinGW 不一定是同一个。混用会出现“编译过了但运行崩”的情况。下面几条命令用来把版本信息摊开看:
# 查看当前 PATH 里 g++ 的版本和来源 g++ --version where g++ # 查看 Qt 套件里 qmake 的版本信息 qmake -v # 查看 Qt 安装目录下 MinGW 的版本(路径按实际安装位置调整) ls "C:/Qt/6.5.0/mingw_64/bin" | head逻辑说明:g++ --version输出里会带x86_64-w64-mingw32字样和 GCC 主版本号;qmake -v会告诉你这个 Qt 是用哪个 Qt 版本构建的。两者要能对上——Qt 6.5 的 mingw_64 套件通常配 GCC 11 或 12 系列的 MinGW。如果where g++指向的不是 Qt 自带的那个 MinGW,而是系统里另一个,就要在 CMake 里显式指定编译器路径,别让它自己猜。
参数说明:where在 Windows 上列出所有匹配的可执行文件路径,顺序就是 PATH 优先级;ls | head只是快速看目录内容,实际工程里不需要。
2.3 libvlc 运行时:VLC-Qt 只是壳,真正解码的是它
VLC-Qt 本身不含解码器,它调用的是 libvlc。你需要一份 VLC 的 Windows 构建,拿到libvlc.dll、libvlccore.dll和plugins目录。常见做法是装一个和 VLC-Qt 构建时所用版本相近的 VLC,然后把它的安装目录作为运行时依赖。
这里有个容易忽略的点:VLC-Qt 的头文件里会引用 libvlc 的头,如果 VLC-Qt 构建时用的 libvlc 版本和你本地 VLC 版本差太多,结构体布局可能变,运行时会出现莫名其妙的崩溃。稳妥做法是让 VLC-Qt 的构建版本和本地 VLC 主版本号一致,比如都是 3.0.x 系列。
| 组件 | 作用 | 版本对齐要求 |
|---|---|---|
| Qt MinGW 套件 | 提供 Qt 库和编译器 | 与 VLC-Qt 构建工具链一致 |
| MinGW-w64 | 编译链接 | GCC 主版本与 Qt 套件匹配 |
| libvlc 运行时 | 实际解码播放 | 主版本与 VLC-Qt 构建时一致 |
| VLC-Qt 安装包 | Qt 与 libvlc 的胶水层 | 本包提供 |
3. 解压之后怎么摆:目录结构、CMake 接入与第一个可运行窗口
3.1 解压后的目录长什么样,哪些是必须进工程搜索路径的
把vlc-qt_build_mingw64_install.zip解压到一个不含空格和中文的路径,比如D:/sdk/vlcqt-mingw64。典型安装产物会有这几个部分:
vlcqt-mingw64/ ├── include/ │ └── VLCQtCore/ VLCQtWidgets/ VLCQtQml/ ├── lib/ │ ├── libVLCQtCore.a │ ├── libVLCQtWidgets.a │ └── cmake/ │ └── VLCQtCore/VLCQtCoreConfig.cmake └── bin/ └── libVLCQtCore.dll 等include是头文件搜索路径,lib是链接路径,lib/cmake下的配置文件让 CMake 的find_package能直接找到它。bin里的 dll 在运行时需要和 exe 放一起,或者加到 PATH。
3.2 在 CMakeLists.txt 里接入 VLC-Qt 的最小写法
不要手动去写include_directories和target_link_libraries拼路径,优先用包自带的 CMake 配置。下面是一个最小可用的 CMakeLists.txt:
cmake_minimum_required(VERSION 3.16) project(VlcQtDemo LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) # 让 CMake 去 vlcqt-mingw64/lib/cmake 下找配置文件 list(APPEND CMAKE_PREFIX_PATH "D:/sdk/vlcqt-mingw64") find_package(Qt6 COMPONENTS Widgets REQUIRED) find_package(VLCQtCore REQUIRED) find_package(VLCQtWidgets REQUIRED) add_executable(VlcQtDemo main.cpp) target_link_libraries(VlcQtDemo PRIVATE Qt6::Widgets VLCQtCore VLCQtWidgets )逻辑说明:CMAKE_PREFIX_PATH告诉 CMake 除了系统路径还去这里找*Config.cmake;find_package(VLCQtCore REQUIRED)会加载VLCQtCoreConfig.cmake,里面定义了导入目标VLCQtCore,直接链接即可,不用自己写.a的完整路径。REQUIRED表示找不到就报错停止,避免后面链接阶段才暴露问题。
参数说明:CMAKE_AUTOMOC ON让 CMake 自动处理 Qt 的 moc,VLC-Qt 的类如果继承 QObject 也需要;CMAKE_PREFIX_PATH用正斜杠或双反斜杠,别用单反斜杠,否则会被当转义。
3.3 一个能弹出窗口并播放本地文件的最小 main.cpp
下面这段代码只做一件事:创建 VlcInstance、VlcMediaPlayer,绑定到一个 QWidget 上,然后播放指定文件。目的是验证整条链路通了。
#include <QApplication> #include <VLCQtCore/Common.h> #include <VLCQtCore/Instance.h> #include <VLCQtCore/Media.h> #include <VLCQtCore/MediaPlayer.h> #include <VLCQtWidgets/WidgetVideo.h> int main(int argc, char *argv[]) { QApplication app(argc, argv); // VlcCommon::args() 返回一组适合桌面播放的默认参数 VlcInstance *instance = new VlcInstance(VlcCommon::args(), &app); VlcMediaPlayer *player = new VlcMediaPlayer(instance); // WidgetVideo 是 VLC-Qt 提供的视频渲染窗口 WidgetVideo *videoWidget = new WidgetVideo(player); videoWidget->resize(800, 450); videoWidget->show(); // 换成你本地的测试文件路径 VlcMedia *media = new VlcMedia("D:/test/sample.mp4", true, instance); player->open(media); return app.exec(); }逻辑说明:VlcInstance是 libvlc 实例的封装,整个进程通常只需要一个;VlcMediaPlayer负责播放控制;WidgetVideo内部处理了窗口句柄到 libvlc 的绑定,这是 VLC-Qt 相比裸写 libvlc 最省事的地方。VlcMedia第二个参数true表示本地文件,如果是网络流则用false。
参数说明:VlcCommon::args()返回的是QStringList,里面包含一些默认的 libvlc 参数,比如禁用某些视频输出。如果你需要自定义,比如指定--no-video-title-show,可以在这个列表基础上追加。
3.4 构建与运行:把 dll 放到 exe 旁边
用 Qt Creator 打开 CMakeLists.txt 所在目录,选 MinGW 套件,配置后构建。构建成功后,exe 在build目录下,但直接双击会报缺 dll。需要把这几类 dll 复制到 exe 同目录:
- Qt 的 dll:
Qt6Core.dll、Qt6Gui.dll、Qt6Widgets.dll等,可以用windeployqt自动处理。 - VLC-Qt 的 dll:
libVLCQtCore.dll、libVLCQtWidgets.dll。 - libvlc 的 dll 和 plugins 目录:
libvlc.dll、libvlccore.dll、plugins/。
# 在构建输出目录执行,让 windeployqt 处理 Qt 依赖 windeployqt VlcQtDemo.exe # 手动复制 VLC-Qt 和 libvlc 的运行时(路径按实际调整) cp D:/sdk/vlcqt-mingw64/bin/*.dll . cp D:/VLC/*.dll . cp -r D:/VLC/plugins .逻辑说明:windeployqt只认 Qt 自己的依赖,不认 VLC-Qt 和 libvlc,所以后两者要手动复制。plugins目录必须整体复制,libvlc 靠它加载解码器和输出模块,缺了会黑屏或直接报错。
4. 避坑与排查:MinGW 构建 VLC-Qt 最容易翻车的五个地方
4.1 现象:链接时报 undefined reference to_imp__vlc_xxx
原因:链接器找不到 libvlc 的导入库。VLC-Qt 的.a里引用了 libvlc 的符号,但你没有把 libvlc 的.lib或.a加进链接路径。MinGW 下通常需要libvlc.lib或libvlc.dll.a。
解决:确认 VLC 安装目录的sdk/lib下有对应的导入库,并在 CMake 里把它加进target_link_libraries。如果 VLC-Qt 的 CMake 配置已经处理了,检查VLCQtCoreConfig.cmake里的INTERFACE_LINK_LIBRARIES是否指向了正确路径。
4.2 现象:编译通过,运行时弹窗后立即崩溃,无任何提示
原因:多半是 dll 版本不匹配。VLC-Qt 的 dll 和 libvlc 的 dll 来自不同构建,或者 Qt 的 dll 混入了 MSVC 版本。
解决:用 Dependency Walker 或objdump -p看 exe 依赖的 dll 列表,逐个确认来源。重点看libvlccore.dll和Qt6Core.dll的位数是否都是 64 位,以及是否都来自 MinGW 构建。
4.3 现象:视频窗口一片黑,但音频正常
原因:libvlc 的 plugins 目录没找到,或者视频输出模块没加载。libvlc 默认会去 exe 同目录的plugins下找,找不到就退化成无视频输出。
解决:确认plugins目录和 exe 同级,且目录里有libvout_*.dll之类的文件。也可以在VlcCommon::args()里显式加--plugin-path=D:/path/to/plugins来指定。
4.4 现象:CMake 配置阶段报Could not find a package configuration file provided by "VLCQtCore"
原因:CMAKE_PREFIX_PATH没设对,或者解压后的目录里根本没有lib/cmake这一层。
解决:手动确认vlcqt-mingw64/lib/cmake/VLCQtCore/VLCQtCoreConfig.cmake是否存在。如果不存在,说明这个包不是 CMake 配置完整的安装产物,需要退回到手动指定 include 和 lib 路径的方式。
4.5 现象:播放网络流正常,播放本地大文件卡顿
原因:MinGW 构建的 VLC-Qt 默认可能没开硬件加速,或者 libvlc 的缓存参数偏小。
解决:在VlcCommon::args()里追加--file-caching=1000之类的参数,增大文件缓存。硬件加速取决于 libvlc 构建时是否启用了对应模块,这个不是 VLC-Qt 层能控制的,需要换一份带硬解的 libvlc。
5. 进阶:把 VLC-Qt 封装成可复用的播放器组件
5.1 用信号槽把播放状态暴露给上层界面
裸用 VlcMediaPlayer 时,上层界面要自己轮询状态。更好的做法是包一层 QObject,把 VLC-Qt 的信号转成业务信号。下面是一个简化的封装:
class PlayerController : public QObject { Q_OBJECT public: explicit PlayerController(QObject *parent = nullptr) : QObject(parent) { m_instance = new VlcInstance(VlcCommon::args(), this); m_player = new VlcMediaPlayer(m_instance); m_videoWidget = new WidgetVideo(m_player); // 把底层信号转成业务信号 connect(m_player, &VlcMediaPlayer::stateChanged, this, &PlayerController::onStateChanged); connect(m_player, &VlcMediaPlayer::positionChanged, this, &PlayerController::positionChanged); } WidgetVideo *videoWidget() const { return m_videoWidget; } void playFile(const QString &path) { auto *media = new VlcMedia(path, true, m_instance); m_player->open(media); } signals: void positionChanged(float pos); void stateChanged(int state); private slots: void onStateChanged() { emit stateChanged(static_cast<int>(m_player->state())); } private: VlcInstance *m_instance = nullptr; VlcMediaPlayer *m_player = nullptr; WidgetVideo *m_videoWidget = nullptr; };逻辑说明:VlcMediaPlayer::stateChanged是 VLC-Qt 提供的信号,直接转发即可;positionChanged是播放进度,单位是 0.0 到 1.0 的浮点。上层界面只依赖PlayerController,不直接碰 VLC-Qt 的类,将来换播放内核时改动面小。
参数说明:VlcMedia对象在open之后由 player 接管生命周期,不要手动 delete,否则会重复释放。WidgetVideo的父对象设成 player 是 VLC-Qt 的约定,别改成别的。
5.2 验证封装是否可靠:三个必测场景
封装完之后,至少跑这三个场景来验证:
| 场景 | 操作 | 预期 |
|---|---|---|
| 连续切换文件 | 快速调用 playFile 五次 | 不崩溃,最后一次正常播放 |
| 播放中关闭窗口 | 播放时直接关主窗口 | 进程正常退出,无残留 |
| 无 plugins 启动 | 临时移走 plugins 目录 | 有明确报错或黑屏但不崩 |
这三个场景能覆盖大部分资源管理和生命周期问题。尤其是连续切换文件,如果 VlcMedia 对象没处理好,很容易在第三次或第四次切换时崩。
5.3 一个我自己的习惯:先跑通再封装
我早期做这类集成时,总想一步到位把封装写漂亮,结果底层还没跑通就陷在架构里。后来固定成一个习惯:先用最小 main.cpp 把“能播一个文件”跑通,确认 dll、plugins、CMake 路径全对,再动手封装。这个顺序看起来笨,但省掉了大量“到底是封装错了还是环境错了”的排查时间。vlc-qt_build_mingw64_install.zip这类包的价值就在于把环境这一层压缩到最小,让你能快速到达“能播”这个状态,剩下的才是工程问题。希望帮到你。
本文还有配套的精品资源,点击获取