简介:对于在Windows下编译VLC-Qt的开发者,这份资源是一套能直接借用的编译成果。VLC-Qt是基于Qt的VLC媒体播放框架,Windows下从源码编译时,通常需要先准备好VLC库,再处理CMake配置和依赖路径,链路较长且容易出错。这份压缩包内含VLC 3.0.0 64位运行环境、VLC-Qt 1.1.1原始源码,以及作者已经编译完成的debug和release版本动态库与静态库,覆盖VLCQtCore、VLCQtWidgets、VLCQtQml等核心模块,可直接放入Qt工程的lib和include目录进行链接,省去自行下载依赖、调整生成器和解决链接报错的时间,对于需要快速在Qt项目里接入视频播放功能的桌面应用开发很实用。资源共77个文件,以头文件、CMake脚本、DLL动态链接库和LIB导入库为主,另保留原始7z压缩包与tar.gz源码包,整体体积36.71MB,目录按include、lib、bin、cmake组织,方便对照查看编译产物与源码结构,无论是直接链接使用还是对照源码研究,都能满足需求。已有1918人学习下载,可作为Windows下VLC-Qt编译集成时的一份参考基准。
1. windows下编译vlc-qt:为什么“最新”两个字让难度翻倍
很多 Qt 开发者接触 vlc-qt 时的第一反应是:VLC 官方明明给了 SDK,为什么还要多套一层封装?因为 libvlc 的 C API 用起来太“裸”了,事件回调、媒体状态、播放器实例都要自己管;vlc-qt 把它包装成 Qt 风格的类,接一个视频窗口只要几行代码。但在 Windows 下编译 vlc-qt 的“最新”版,第一次尝试大概率要翻车——这里说的“最新”有两个含义:一是 vlc-qt 主线代码的最新提交,二是与之匹配的 VLC SDK 最新发布版。两个都是移动靶,依赖路径、ABI 匹配、插件目录三个坎,任何一个没对准,程序就可能在运行期黑屏或闪退。这篇文章就按我在 Windows 上实际走通的顺序,从 SDK 准备到 CMake 配置、再到运行时部署,把每一步的命令和参数讲透,最后单独整理一份避坑记录。适合两类人:一是要在 Qt 项目里嵌入本地播放或 RTSP 拉流能力、又不想用系统自带解码器的人;二是想把 VLC 封装库升级到最新版、又不敢盲改依赖的人。
2. 编译前的三件准备:Qt、VLC SDK、编译器匹配
2.1 先把 Qt 位数和编译器定死,后面少走一半弯路
在 Windows 下编译 vlc-qt,第一步不是拉源码,而是确定 Qt 是用哪套环境构建的。常见做法是 Qt 5.15 之后的 LTS 版本配 MinGW 或 MSVC 编译器,位数选 64 位还是 32 位,直接决定了后面 VLC SDK 的选型。位数不匹配的后果很直接:链接阶段报一堆“无法解析的外部符号”,或者运行时报 0xc000007b 这种与位数相关的经典错误。
我一般会先执行下面的命令,确认本机 Qt 的安装信息,再决定后面所有路径怎么写。
qmake -query逻辑说明:qmake -query会输出当前 Qt 套件的安装根目录(QT_HOST_PREFIX)、架构信息(QT_ARCH)以及实际安装路径(QT_INSTALL_PREFIX)。这些字段在后续配置 CMake 的CMAKE_PREFIX_PATH时直接拿来拼路径,不需要手猜。参数说明:这里最关键的字段是QT_ARCH——如果输出x86_64,那后面 VLC SDK 必须选 64 位版本;如果输出win32,VLC SDK 就要选 32 位。另一个关键字段是QT_INSTALL_HEADERS,它告诉你 Qt 头文件的实际位置,避免 CMake 自动找到一套、编译器又去另一套头文件里找。
确认完架构后,编译器也要一并定死。MSVC 对应 Visual Studio 的生成器,MinGW 对应MinGW Makefiles。两者编译出来的 vlc-qt 库不通用,而且连锁影响后面 VLC 导入库的处理方式:MSVC 直接吃.lib,MinGW 通常需要.a或直接链接 DLL。这节如果没定好,后面每一层的依赖都会跟着乱。
2.2 备齐 VLC SDK:libvlc 的头文件、导入库和插件目录
vlc-qt 本身不包含 libvlc 的二进制,它只是封装,真正的解码、播放、渲染全在 libvlc 里。VLC 的官方二进制发布包通常分两套:一套是 dev 开发包,提供include/vlc/*.h头文件和导入库;另一套是 runtime 运行包,提供libvlc.dll、libvlccore.dll和plugins目录。编译时只需要 dev 部分,但运行时的程序必须同时拿到 runtime 的 DLL 和插件目录。
很多人在这里只下载了一个 runtime DLL,丢进系统目录,然后 CMake 报找不到VLC_LIBRARY。正确的做法是先把 SDK 整理成一个固定目录,例如:
D:\vlcsdk\ include\vlc\libvlc.h include\vlc\libvlc_media.h include\vlc\libvlc_events.h lib\ plugins\ bin\libvlc.dll逻辑说明:这个目录结构的核心意义是把“编译期用到的头文件和导入库”与“运行期用到的 DLL 和插件”分开,但放在同一个 SDK 根下统一管理。include\vlc是 CMake 查找头文件时的搜索目标,lib下放导入库,plugins是 VLC 运行时加载解码器的目录,bin下放libvlc.dll和libvlccore.dll。如果下载的 VLC 包目录结构不同,建议手动整理成这个形式,否则后面 CMake 变量要写很多层路径。
参数说明:VLC SDK 的位数必须和 Qt 一致,这是整条链路最不能妥协的点。另外注意plugins目录和 DLL 同级存放,很多版本的 VLC 会按 DLL 所在目录的相对路径来找plugins,如果你把 plugins 单独挪个位置,运行时会无声无息地丢掉解码器。
2.3 环境变量清单:把 CMAKE_PREFIX_PATH 指到 Qt 根目录
vlc-qt 的 CMake 构建脚本里用find_package(Qt5 REQUIRED)这种方式定位 Qt,而find_package查找 Qt 时最关键的变量就是CMAKE_PREFIX_PATH。它必须指向 Qt 的安装根目录,也就是包含lib/cmake/Qt5的那一层,不是bin,也不是lib。指向错了,CMake 会跳过你指定的 Qt,转而去 PATH 里碰运气找另一套。
set CMAKE_PREFIX_PATH=D:/Qt/Qt5.15.2/5.15.2/msvc2019_64 set PATH=D:/vlcsdk/bin;%PATH%逻辑说明:第一行让 CMake 能唯一定位到 Qt 的 CMake 配置目录;第二行把 VLC 的bin加入 PATH,作用是让编译产物在开发阶段能直接找到libvlc.dll,不用每次手动拷贝到 exe 目录。参数说明:路径要根据你自己的 Qt 安装位置改,关键是必须指到套件根目录,也就是能看到bin/qmake.exe的上一层。PATH 里加入 vlc SDK 的 bin 只是开发期权宜之计,正式交付时还是要靠拷贝 DLL,这点后面单独说。
提示:环境变量设置作用于当前命令行窗口,换一个终端就要重新设。如果反复编译多个项目,建议直接写进项目级的环境变量,或者做一个
env.bat,每次编译前统一执行。
3. 拉取 vlc-qt 源码:分支选择与项目结构拆解
3.1 拉主线还是拉稳定标签:我一般怎么选
既然标题说的是“最新”,那就意味着你不想困在旧分支上。但 vlc-qt 对 VLC 新版本的适配往往有滞后:VLC SDK 头文件里改了一个字段,vlc-qt 那边的结构体可能还没来得及同步。从稳定角度看,选接近最新发布的 tag 会稳一点;从兼容角度看,主线最新代码往往已经修掉了旧 tag 里的编译错误。我一般会直接用主线最新提交,因为至少能确认这套代码在持续跟进 VLC 的新接口。
git clone <vlc-qt仓库地址> cd vlc-qt git checkout master git pull --ff-only git submodule update --init --recursive逻辑说明:前三条是拉主线并保持最新,--ff-only表示只允许快进合并,不产生额外的 merge commit,这样回溯版本时历史是干净的。最后一条初始化子模块,因为 vlc-qt 在 Windows 上编译时某些辅助组件依赖子模块内容,漏了这一步,CMake 配置阶段可能缺少文件。参数说明:--ff-only在本地有未提交改动时会直接失败,这其实是个保护机制——强制你先处理本地改动,避免半合并状态。如果你只是临时看代码,git submodule update --init不加--recursive也行,但编译前补全总没坏处。
拉完代码后先别急着配置,打开目录看一眼顶层结构。一个典型的 vlc-qt 仓库会包含src/core、src/widgets、src/qml、examples和tests等目录。src/core是封装 libvlc 的核心模块,不管你用不用界面组件,这个模块都会编;src/widgets是 Qt Widgets 风格的播放控件;src/qml是 QML 模块,不需要的话可以在 CMake 里关掉。
3.2 读一遍 CMakeLists.txt:哪些组件会默认一起编
初次编译 vlc-qt,最容易忽略的是顶层CMakeLists.txt里那些BUILD_*开关。默认情况下,QML 模块、示例程序、测试代码可能都是开启的,如果不关掉,编译时间会拉长一半以上,而且 tests 模块在 Windows 上经常因为权限问题或框架缺失而编译失败,白白劝退新手。
cmake -LA . 2>nul | findstr /I "BUILD"逻辑说明:这条命令在 Windows 的 cmd 下运行,cmake -LA会列出所有缓存变量的名称和类型,管道交给findstr过滤带BUILD的行,快速看到这个版本里有哪些构建开关。参数说明:-LA里的L表示 list cache variables,A表示 advanced,只加-L会漏掉 advanced 变量,建议组合使用。如果你用的 PowerShell,findstr换成Select-String -Pattern就行。
看到开关列表后,通常值得重点关注的是:BUILD_QML(QML 模块,不需要就关)、BUILD_EXAMPLES(示例程序,第一次可以开)、BUILD_TESTS(单元测试,Windows 下默认关掉更省心)。还有个关键点是这几个开关的名字在不同小版本里可能略有差异,比如有的版本用WITH_QML或类似命名,以你实际拉到的代码为准。
3.3 examples 和 tests 的取舍:留最小的验证面
我第一次编译 vlc-qt 时把BUILD_EXAMPLES和BUILD_TESTS全关了,结果编译很快通过,但当我想验证播放功能时,发现手头没有现成的调用示例,只能边翻头文件边猜接口,反而浪费了更多时间。后来我改成一个折中做法:第一次编译只开BUILD_EXAMPLES,不开BUILD_TESTS,这样既不会卡在测试框架的编译上,又能拿到官方写好的播放器示例,直接运行就能验证整个链路通不通。
如果你是新手,建议照这个配置走。BUILD_TEST依赖的测试框架引入的第三方依赖在 Windows 下很容易出幺蛾子,而且它对验证“vlc-qt 能不能播放视频”这个目标没直接帮助,等以后需要做回归测试再开也不迟。examples 就不同,它几乎是现成的验收工具——编译完跑起来,能放视频就说明链接、插件路径、事件循环全部就位;不能放,也容易定位是哪一层的问题。
4. 用 CMake 把编译跑通:一条配置命令加三处重点参数
4.1 配置命令与各参数含义
准备工作做完后,接下来的核心动作就是 CMake 配置。这里我给出一条完整的命令,覆盖了 Qt 路径、VLC SDK 路径、构建开关三处最容易出问题的位置:
cmake -S . -B build ^ -G "Visual Studio 17 2022" -A x64 ^ -DCMAKE_PREFIX_PATH="D:/Qt/Qt5.15.2/5.15.2/msvc2019_64" ^ -DVLC_INCLUDE_DIR="D:/vlcsdk/include/vlc" ^ -DVLC_LIBRARY="D:/vlcsdk/lib/libvlc.lib" ^ -DBUILD_QML=OFF ^ -DBUILD_EXAMPLES=ON ^ -DBUILD_TESTS=OFF逻辑说明:-S . -B build指定源码目录和构建目录,之后的配置全部写入build/CMakeCache.txt。-G指定 Visual Studio 2022 生成器,-A x64指定 64 位架构,这一步必须和 Qt 套件一致。CMAKE_PREFIX_PATH指向 Qt 根目录,VLC_INCLUDE_DIR和VLC_LIBRARY是 vlc-qt 的FindVLC.cmake模块查找 VLC 时用的两个关键变量,显式指定可以避免它跑到错误位置去翻库。构建开关里关掉 QML 和测试,打开示例,正好对应上一章说到的策略。
参数说明:VLC_LIBRARY的写法取决于你用的编译器。如果是 MSVC,直接指到.lib文件;如果是 MinGW,这个变量应该指向 VLC SDK 里由dlltool生成的.a导入库,或者直接指到libvlc.dll的完整路径,让 MinGW 在链接时直接使用 DLL 导出表。另外,不同小版本里VLC_LIBRARY的查找逻辑可能略有不同,配置完以后建议用cmake -LA build复查一下,确认这两个变量确实被设置成你指定的值,而不是被自动找到的老版本 SDK。
4.2 编译与安装:从 make 到 DLL 落地的完整动作
配置无误后,编译这一步反而没那么容易出问题,真正要留神的是“编译”和“安装”是两回事。很多人 cmake 编译成功就以为完了,结果在自己的工程里find_package(VLCQt)找不到库,因为根本没执行 install 这一步。
cmake --build build --config Release --parallel 8 cmake --install build --config Release --prefix D:/vlcqt-install逻辑说明:第一条命令会编译整个解决方案,--config Release指定产出 Release 配置,--parallel 8开启 8 线程并行编译,时间能缩到单线程的六分之一左右。第二条命令将编译产物安装到D:/vlcqt-install,这一步会把头文件、导入库、DLL 按标准的include、lib、bin结构整理好,方便之后被别的 CMake 工程通过CMAKE_PREFIX_PATH找到。参数说明:--prefix不写的话默认装到系统目录,在 Windows 下大概率没有写入权限,所以一定要手动指到自己的目录。如果你用的是 MinGW 生成器,--config Release这个参数可以直接省掉,因为MinGW Makefiles只产出一种配置,加了这个参数反而可能告警。
安装完成后检查一下D:/vlcqt-install的结构,lib目录应该能看到VLCQtCore.lib和VLCQtWidgets.lib,bin目录下应该有对应的 DLL。如果你的工程需要 QML 模块,那lib下还会多一个VLCQtQml.lib。
4.3 运行时路径的最后一公里:Qt 插件与 VLC 插件
编译完、安装完,程序仍然可能跑不起来,这跟代码逻辑没关系,纯粹是Windows 下 DLL 搜索路径和插件路径的坑。Qt 程序需要 Qt 自己的插件(比如platforms/qwindows.dll),VLC 需要 VLC 自己的插件目录;这两个目录缺一个,表现截然不同——缺 Qt 插件,程序在启动时直接起不来;缺 VLC 插件,程序能起来但画面黑屏。
一个最小可交付的目录结构大致长这样:
D:\player\ app.exe VLCQtCore.dll VLCQtWidgets.dll libvlc.dll libvlccore.dll platforms\qwindows.dll plugins\逻辑说明:VLCQtCore.dll和VLCQtWidgets.dll来自 vlc-qt 的安装目录,libvlc.dll和libvlccore.dll来自 VLC 的 runtime 包,platforms目录从 Qt 安装目录的plugins\platforms下拷贝,plugins是 VLC 的插件目录整体复制过来。把它们放在 exe 同级,是为了让 Windows 默认的 DLL 搜索顺序直接命中。参数说明:VLC 的插件目录查找机制是相对libvlc.dll所在目录来找,所以plugins必须和libvlc.dll保持同级关系,不能单独扔到别处。
注意:如果
libvlc.dll是放在另一个子目录里通过 PATH 找到的,那plugins目录也要跟着放在那个子目录下。开发调试时可以靠 PATH 暂时顶着,但交付时把 DLL 和插件全部拉回 exe 同级是最稳定的方案。
5. Windows 下编译 vlc-qt 的避坑记录与排查思路
5.1 现象:链接器不认 libvlc.lib 的格式
第一次用 MinGW 编译 vlc-qt 时,链接阶段报错,大意是“file format not recognized”,或者 MSVC 下报LNK1107说文件不是有效的 DLL 或对象文件。这个报错单独看很容易让人懵,因为libvlc.lib明明就在那里,路径也没写错。
原因:VLC 官方 SDK 里给的.lib导入库是 MSVC 风格,MinGW 的链接器不认这种格式。反过来的情况也常见——你下载的 VLC 包是 MinGW 风格,拿给 MSVC 去链接一样报格式错误。本质上是两个编译器家族对导入库的格式约定不同。
解决:最省事的办法是统一编译器家族——用 MSVC 的 Qt 就搭配 MSVC 编译的 VLC SDK,用 MinGW 就找 MinGW 版本的 VLC 包。如果只能拿到单一格式的 SDK,可以用工具转换:
gendef libvlc.dll dlltool -d libvlc.def -D libvlc.dll -l libvlc.a -k逻辑说明:gendef从 DLL 导出表生成.def文件,dlltool再用.def生成 MinGW 风格的导入库libvlc.a,然后把 CMake 里的VLC_LIBRARY指到这个.a文件。参数说明:-k表示生成内核导入库,有些符号带__imp_前缀,不加-k链接时可能找不到符号。
5.2 现象:运行时找不到 libvlc,程序直接退出
程序编译成功后,双击运行,弹窗“无法启动此程序,因为计算机中丢失 libvlc.dll”,或者 Qt Creator 直接输出“进程异常退出”。
原因:vcl-qt 的 DLL 是动态链接到libvlc.dll的,可执行文件启动时,Windows 需要按固定顺序搜索这个 DLL:exe 所在目录、系统目录、PATH 环境变量中的目录。三者任何一个没有,启动就会失败。
解决:把libvlc.dll和libvlccore.dll复制到 exe 同级目录,或者开发期间把D:\vlcsdk\bin加进 PATH。另一个容易被忽略的细节是位匹配:64 位程序必须加载 64 位版本的libvlc.dll,如果把 32 位 DLL 放进 64 位 exe 目录,同样会报错,而且报错信息可能和丢失 DLL 完全一样,排查时先确认位数。
5.3 现象:画面黑屏但没报错,日志停在 open
调用了播放接口,窗口能弹出来,但画面一直是黑的,事件日志里没有任何异常,甚至 VLC 自己的日志都只在open这一步,后面就没有下文了。
原因:VLC 插件目录没被找到。libvlc 启动时如果找不到 plugins 目录,它会退回最小能力模式,很多解码器不可用,于是媒体文件打不开,但接口层面并不抛错,表现就是黑屏。这个问题最容易出现在刚切换 VLC SDK 版本的时候——SDK 包确实带了 plugins,但没放在 DLL 同级目录,或者路径拼接少了个plugins子目录。
解决:在程序启动时显式指定插件路径:
#if defined(_WIN32) VlcCommon::setPluginPath(QStringLiteral("D:/vlcsdk/plugins")); #endif逻辑说明:VlcCommon::setPluginPath是 vlc-qt 提供的静态方法,在创建播放器实例之前调用,把这个路径透传给 libvlc,避免依赖相对路径的默认查找逻辑。参数说明:路径写成绝对路径在开发时最省心;正式交付时,可以把路径改成相对于QCoreApplication::applicationDirPath()的拼接结果,比如appDir + "/plugins",这样换机器也不用改代码。
5.4 现象:moc 文件报错,提示 Qt 头文件版本不一致
编译到某个含Q_OBJECT宏的文件时,moc 生成的 cpp 文件报错,错误信息指向 Qt 头文件里的某个类“不完整”或“未定义”,换了干净的 Qt 环境却一切正常。这种报错常被当成玄学,其实是头文件污染。
原因:多版本 Qt 并存。PATH 环境变量里同时存在 Qt 5.15 和别的版本,或者CMAKE_PREFIX_PATH里写了两个 Qt 路径,find_package找到了第一个 Qt,编译器却因为 PATH 的顺序去另一个 Qt 的头文件里找qobject.h,两者版本不一致,moc 生成的元数据自然对不上。
解决:清空 CMake 缓存,重新配置,并严格控制只保留一个 Qt 路径。先执行cmake --build build --target clean或者直接删除整个build目录,然后用cmake -LA确认CMAKE_PREFIX_PATH里只有一个路径。同时检查 PATH 环境变量,把多余的 Qt 路径从 PATH 中临时移除,再重新配置、编译。
5.5 现象:Debug 能跑 Release 崩,或者反过来
同一个工程,Debug 配置下播放正常,Release 配置下点击播放就崩溃;或者反过来 Release 正常 Debug 崩。两种表现背后的原因往往相同。
原因:混用了不同配置的库。比如链接了 Release 版的 VLCQt 库,但 Qt 运行时用的 Debug 版,或者调用setPluginPath的代码被#ifdef _DEBUG包住了,Release 构建下根本没执行插件路径设置,VLC 找不到解码器,导致后续调用链拿到空指针。
解决:先检查代码里有没有按 Debug/Release 分支处理插件路径或 VLC 参数的逻辑,有就统一去掉条件编译,让两个配置走同一条路径。再检查链接的 VLCQt 导入库和生成的 VLCQt DLL 是否是同一个配置的产物——用dumpbin /headers查看 DLL 的镜像头,能确认这个 DLL 是 Debug 还是 Release 编译的,Debug 会包含_DEBUG相关的特征信息。
6. 用一个 20 行的播放器验证整条工具链
6.1 最小验证工程的代码骨架
前面所有步骤都走完之后,不要急着往大项目里集成,先写一个最小的播放器验证整条链路。验证目标只有三个:VLC 插件能被加载、vlc-qt 库能被正确链接、Qt 事件循环能和 libvlc 的播放循环互通。一个能播本地文件的最小程序,代码量大约 20 行:
#include <QApplication> #include <QMainWindow> #include <QVideoWidget> #include <VLCQtCore/Common.h> #include <VLCQtCore/Instance.h> #include <VLCQtCore/Media.h> #include <VLCQtCore/MediaPlayer.h> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 必须在创建 VlcInstance 之前指定插件路径 VlcCommon::setPluginPath(QStringLiteral("D:/vlcsdk/plugins")); QMainWindow window; QVideoWidget video(&window); window.setCentralWidget(&video); window.resize(960, 540); QStringList vlcArgs; vlcArgs << QStringLiteral("--no-video-title-show"); VlcInstance instance(vlcArgs); VlcMedia media(&instance, QStringLiteral("D:/sample.mp4")); VlcMediaPlayer player(&instance); player.setVideoWidget(&video); player.open(&media); player.play(); window.show(); return app.exec(); }逻辑说明:setPluginPath必须放在创建VlcInstance之前,否则插件路径不会生效。VlcInstance对应 libvlc 的实例,VlcMedia表示要播放的媒体,VlcMediaPlayer是播放控制的核心对象。setVideoWidget把视频输出绑定到QVideoWidget上,这是 Qt 界面层看到画面的前提。参数说明:vlcArgs里传的--no-video-title-show是 libvlc 的播放参数,可以按需继续追加,比如--rtsp-tcp可以强制 RTSP 走 TCP,这些参数会原样传给 libvlc。
6.2 把 DLL 依赖写成清单,方便交付分发
验证通过后,交付前还有一个动作值得养成习惯——生成 DLL 依赖清单。手动拷贝 DLL 容易漏,特别是在依赖链变长之后:VLCQtCore.dll 依赖 libvlc.dll,VLCQtWidgets.dll 依赖 VLCQtCore.dll 和 Qt5Widgets.dll,中间任何一环断了,目标机器上就会弹出“缺少 DLL”的提示。
dumpbin /dependents D:\player\app.exe逻辑说明:dumpbin /dependents会列出 exe 直接依赖的所有 DLL 名称,把这些名称逐一对照当前目录的 DLL 清单,就能找出漏掉的那几个。参数说明:dumpbin自带在 Visual Studio 的开发者命令行里,普通 cmd 里敲不了;如果没装 Visual Studio,可以用 Dependencies 这类图形化工具,效果相同。检查完后,把非系统自带的 DLL 全部放进 exe 同级目录,最后在另一台干净机器上跑一遍,才算真正交付。
我现在接手 Windows 平台 Qt 播放器相关的需求时,已经把这条编译链路的每一步固化成一段脚本,而不是每次靠记忆重新走一遍。“最新”版本永远在变,但准备 SDK、定编译器、配插件路径、验证最小例程这套流程是不变的。希望这篇笔记能让你在编译 vlc-qt 时少走几条弯路,至少不用再因为一个.lib格式问题折腾一下午。希望帮到你。
本文还有配套的精品资源,点击获取