简介针对 Windows 下 Qt 开发者的 FFmpeg RTSP 实时播放示例包基于 Qtmingw32 环境编写解决在界面中拉取并显示 RTSP 视频流的核心问题特别适合已有 Qt 基础、想快速接入视频流的开发者。压缩包共 103 个文件、11.58MB以 h 头文件与 cpp 源码为主附带 avcodec/avformat 等依赖库文件dll/a、窗体 UI 文件及工程配置pro/qrc/qss/ico从文件构成可清晰看出接口封装、播放逻辑与界面资源的组织方式Windows 下可直接完成编译运行。功能上支持三通道同步显示同一视频流单击截图按钮可将当前画面保存至最后一个通道双击单通道即可最大化视频响应速度优于 VLC、QTAV 等常见播放方案。示例聚焦实时显示流程不含存储与回放功能使用前需在 Qt Creator 中取消影子构建Linux 环境需替换对应 FFmpeg 库文件。目前已有 1163 人学习/下载无论是学习 Qt 多线程拉流还是参考多路预览与截图交互设计都能缩短环境配置和界面联调时间适合作为二次开发底座。1. 项目概述这条技术链到底在解决什么先说结论qt mingw32 windows ffmpeg rtsp这一串关键词组合在一起本质上是想实现一件事——在 Windows 环境下用 Qt 做界面通过 FFmpeg 拉取 RTSP 视频流再显示到界面上而且整个工程要保证“编译可用”不是跑一遍就崩也不是换个机器就起不来。这类需求在实际开发中出现频率相当高。做安防监控平台的要对接海康、大华的摄像头RTSP 是最常见的取流协议做工业组态软件的需要在界面上嵌入实时视频窗口多半也会走这条链路还有做教学 demo 或毕业设计的更是绕不开这一套。问题是网上能找到的教程要么是 Linux 下的要么用的是 MSVC 编译器真正用MinGW32这套组合完整走通的人不多资料也零散踩起坑来特别费时间。我最初接到这个需求是帮一个做巡检机器人的朋友搭上位机原型。他们那边摄像头输出的 RTSP 流需要在 Windows 工控机上实时显示、截图还要叠加一些时间戳信息。机器上装的是 Qt 5.15 MinGW 32 位工具链不想换 MSVC因为整套部署脚本都基于这套环境。这也就意味着FFmpeg 的库、头文件、依赖的 DLL全部要适配 MinGW32一个都不能少。先说清楚这篇文章适合谁正准备在 Windows 上用 Qt 做视频播放或流媒体接入的开发者尤其是对编译环境吃不准、希望一次性把环境跑通、避免反复折腾的人。已经熟悉 MSVC 工具链但想切到 MinGW 的也能从里面找到你需要的关键差异。下面我会按照从环境准备到代码落地的顺序把这条链路的完整过程拆开讲包括我实际踩过的坑、验证过的配置、以及为什么某些操作必须这么做。2. 方案选型与依赖分析为什么这套组合容易出问题要保证“编译可用”必须先把四个核心组件之间的兼容关系理清楚否则任何一个环节版本不匹配都会导致后面报一堆看不懂的错误。2.1 工具链版本匹配MinGW 的位数和 Qt 的位数必须对齐这里有一个新手最容易忽略的点Qt 安装时选择的编译器套件决定了你后续所有库的位数和 ABI。Qt 5.15 的在线安装包里MinGW 32-bit 对应的是mingw730_32或mingw810_32这类目录不同小版本带的编译器版本不太一样。我实测下来最稳的组合是组件推荐版本说明Qt5.15.2长期维护版资料最多MinGW8.1.0 32-bitQt 自带的版本即可FFmpeg4.4 或 5.1BtbN 的 Windows Builds 比较省心编译位数32 位与标题中的 mingw32 对应为什么强调 32 位因为标题里写的是mingw32——这有两种理解一是 MinGW 本身 32 位工具链二是 MinGW 项目统称。如果目标是 64 位那实际上应该用mingw64或 Qt 的mingw730_64套件。但既然标题明确写了 32下面所有配置都按 32 位来。这也会影响 FFmpeg 下载包的选择——必须选win32版本而不是win64。这里顺便解释一下为什么推荐用 5.15.2 的 Qt。新版的 Qt 6 虽然性能更好但工程文件.pro的写法、部分 API 有变化很多旧项目直接迁移会遇到兼容性问题。而 5.15.2 是 Qt 5 系列的最后一个 LTS 版本生态成熟、按资料齐全、坑基本都被踩平了对于要“保证编译可用”的诉求来说是最保险的选择。2.2 FFmpeg 库的选择shared 还是 devstatic 还是 gplFFmpeg 在 Windows 下的预编译包通常分三种shared包含 DLL 和导入库、dev包含头文件和导入库、static直接编进去不需要额外 DLL。很多人一开始图省事选 static觉得“打成一个 exe 多干净”但实际在 Qt MinGW 下会碰到一个很尴尬的问题static 版本通常是用 MSVC 编的MinGW 链接不了。BtbN 的构建相对友好区分了win32和win64、gpl和lgpl。我在项目中用的是一个 win32 的 shared 版本关键文件包括ffmpeg-5.1-win32-shared目录下的bin、include、libbin里有avcodec-59.dll、avformat-59.dll、avutil-57.dll、swscale-6.dll等lib里有对应的.dll.a导入库文件MinGW 风格的后缀注意区分MinGW 的导入库后缀是.dll.aMSVC 的是.lib。如果拿到的是.libMinGW 的g是链接不过的这是百分之百会遇到的第一个坑。所以选择 FFmpeg 包时一定要确认它是MinGW 可用的版本而不是 MSVC 专用包。2.3 RTSP 协议层面的准备需要知道的基本概念RTSPReal Time Streaming Protocol本身是一个控制协议负责建立会话、播放、暂停、停止等操作。实际的视频数据是通过 RTP 协议传输的。FFmpeg 内部封装好了这套流程开发者不需要自己解析 RTP 包只需要调用avformat_open_input传入rtsp://地址然后按常规流程读取数据包、解码、显示即可。这就引出一个关键点你其实不需要为 RTSP 单独引入任何库FFmpeg 已经内置了 RTSP 的解复用支持。前提是编译 FFmpeg 时开启了网络支持和 RTSP 协议通常默认开启。所以真正要做的工作就集中在两件事一是把 FFmpeg 在 MinGW32 环境下编译/配置好二是用 Qt 的QImage或 OpenGL 把解码出的帧渲染到界面上。在动手之前确认一下你的 FFmpeg 是否支持 RTSP打开终端执行ffmpeg -protocols | grep rtsp如果能看到rtsp输出就说明支持。若用的是预编译包这一步可省略因为常见的构建都默认开启。3. 编译环境搭建一步步配置 Qt MinGW32 FFmpeg这是整个过程中最容易出问题的环节也是最值得花时间彻底搞清楚的环节。我会把每一步的操作细节和验证方法都写出来按这个顺序走理论上半小时内能跑通。3.1 Qt 和 MinGW 的环境安装与 PATH 配置如果你的 Qt 已经安装了 MinGW 32 位套件那么恭喜你编译器本身不用单独装了。Qt 安装器里会自带对应的 MinGW 工具链比如放在C:\Qt\Tools\mingw810_32\里面包含gcc.exe、g.exe、mingw32-make.exe等。要保证命令行下能直接调用g和mingw32-make需要把以下路径加入系统 PATH按你的实际安装目录调整C:\Qt\Tools\mingw810_32\bin C:\Qt\5.15.2\mingw81_32\bin第一行是编译器第二行是 Qt 工具如qmake、moc、rcc。配置完 PATH 后打开一个新的终端执行验证g --version qmake --version能正常打印出版本信息就说明环境变量配置没问题。如果显示“不是内部或外部命令”检查 PATH 是否真的生效或者新开的终端是否继承了最新的环境变量。3.2 FFmpeg 的头文件、库文件与 DLL 布署FFmpeg 下载解压后要做的第一件是把核心目录整理到一个固定的位置。我的习惯是创建一个third_party/ffmpeg目录把include、lib、bin拷贝进去这样工程文件里引用路径清晰不会出现在桌面上到处找 DLL 的情况。路径准备好了还需要把bin下的所有 DLL 拷贝到 Qt 可执行程序所在的目录比如 Qt Creator 的构建输出目录build-xxx-Desktop_Qt_5_15_2_MinGW_32_bit-Debug/debug/。如果不拷贝编译能通过但一运行就报“找不到 avcodec-59.dll”之类的错误。这里补充一个经验不要只拷贝用得到的 DLL干脆全拷贝过去。因为 FFmpeg 的库之间是存在依赖链的比如avformat依赖avcodec、avutil如果你只拷贝了avformat运行时照样会报缺 DLL。一次性把整个bin目录的内容放进去能省掉很多排查时间。建议把上面的路径整理成一张表方便快速对照配置项路径示例Qt 安装目录C:\Qt\5.15.2\mingw81_32MinGW 编译器C:\Qt\Tools\mingw810_32\binFFmpeg includeD:\dev\third_party\ffmpeg\includeFFmpeg libD:\dev\third_party\ffmpeg\libFFmpeg DLL拷贝到 exe 所在目录3.3 工程文件.pro的写入与链接参数解析在.pro文件里核心要写清楚两件事头文件路径和库文件路径、链接的具体库。这是我验证过可直接用的写法QT core gui widgets TARGET RtspPlayer TEMPLATE app # FFmpeg 路径 FFMPEG_HOME D:/dev/third_party/ffmpeg INCLUDEPATH $$FFMPEG_HOME/include LIBS -L$$FFMPEG_HOME/lib \ -lavformat \ -lavcodec \ -lavutil \ -lswscale SOURCES main.cpp \ playerwidget.cpp HEADERS playerwidget.h几个需要特别说明的细节库名不能带.dll.a后缀也不用加lib前缀。比如libavformat.dll.a在 LIBS 里写的是-lavformat。这是 MinGW 链接的习惯和 MSVC 的avformat.lib写法完全不同。链接顺序有讲究。-l的排列顺序一般是依赖关系从上层往下层avformat在最前面avutil在最后面。如果顺序反了链接阶段可能会报undefined reference但不是真的缺少函数而是链接器从左到右解析符号时还没看到定义。大小写敏感。库文件名是avformat全小写在 LIBS 里也要全小写。Windows 文件系统不区分大小写但 MinGW 链接器的符号匹配可能会受影响稳妥起见保持统一。4. 核心代码实现RTSP 拉流、解码与 Qt 界面显示环境就绪后代码层面的核心就是三个环节初始化 FFmpeg 并打开 RTSP 地址、循环读取数据帧并解码、把解码后的图像转成 QImage 刷新到界面上。我按这个顺序逐一拆开讲。4.1 初始化与打开 RTSP 流关键结构体和函数调用初始化的代码比较固定核心是AVFormatContext、AVCodecContext和SWScale三个对象的创建与配置。下面是最小可执行的版本extern C { #include libavcodec/avcodec.h #include libavformat/avformat.h #include libswscale/swscale.h } AVFormatContext* fmtCtx nullptr; AVCodecContext* codecCtx nullptr; AVCodecParameters* codecParams nullptr; SwsContext* swsCtx nullptr; // 1. 注册所有组件FFmpeg 4.x 其实可省略但保留无妨 avformat_network_init(); // 2. 打开输入流 AVDictionary* options nullptr; av_dict_set(options, rtsp_transport, tcp, 0); av_dict_set(options, stimeout, 5000000, 0); // 5秒超时 int ret avformat_open_input(fmtCtx, url.toStdString().c_str(), nullptr, options); if (ret ! 0) { qDebug() open failed: ret; return false; } // 3. 查找流信息 ret avformat_find_stream_info(fmtCtx, nullptr); if (ret 0) return false; // 4. 找到视频流索引 int videoStream -1; for (unsigned i 0; i fmtCtx-nb_streams; i) { if (fmtCtx-streams[i]-codecpar-codec_type AVMEDIA_TYPE_VIDEO) { videoStream i; break; } } if (videoStream -1) return false; // 5. 获取解码器参数并打开解码器 codecParams fmtCtx-streams[videoStream]-codecpar; const AVCodec* decoder avcodec_find_decoder(codecParams-codec_id); codecCtx avcodec_alloc_context3(decoder); avcodec_parameters_to_context(codecCtx, codecParams); ret avcodec_open2(codecCtx, decoder, nullptr); if (ret 0) return false;这里有两个容易踩的坑第一个坑rtsp_transport参数最好显式指定为 tcp。如果不指定FFmpeg 默认走 UDP。UDP 在弱网环境下丢包严重画面会花、卡。TCP 传输虽然延迟略高但稳定性好很多。在局域网这类丢包率偏高的场景TCP 是更实际的默认选择。第二个坑stimeout参数直接影响断线检测的灵敏度。单位是微秒5000000表示 5 秒。RTP 流本身是持续的如果摄像头断线或网络中断FFmpeg 可能卡在av_read_frame里一直读不到数据如果没有超时机制程序会假死。设置这个参数后5 秒内没数据会自动报错返回方便后续重连逻辑的实现。4.2 解码循环与图像格式转换从 AVFrame 到 QImage拉流成功后接下来进入主循环不断读取数据包找到视频流的数据包后交给解码器解码得到一帧原始图像通常为 YUV420P再用sws_scale转成 RGB888最后封装成QImage显示。AVPacket* packet av_packet_alloc(); AVFrame* frame av_frame_alloc(); AVFrame* rgbFrame av_frame_alloc(); // RGB frame 的 buffer 初始化 int w codecCtx-width; int h codecCtx-height; int numBytes avpicture_get_size(AV_PIX_FMT_RGB24, w, h); uint8_t* buffer (uint8_t*)av_malloc(numBytes); avpicture_fill((AVPicture*)rgbFrame, buffer, AV_PIX_FMT_RGB24, w, h); while (av_read_frame(fmtCtx, packet) 0) { if (packet-stream_index videoStream) { int ret avcodec_send_packet(codecCtx, packet); if (ret 0) { while (avcodec_receive_frame(codecCtx, frame) 0) { // YUV - RGB sws_ctx sws_getContext(w, h, codecCtx-pix_fmt, w, h, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr); sws_scale(sws_ctx, frame-data, frame-linesize, 0, h, rgbFrame-data, rgbFrame-linesize); QImage img(rgbFrame-data[0], w, h, rgbFrame-linesize[0], QImage::Format_RGB888); QPixmap pixmap QPixmap::fromImage(img.copy()); ui-videoLabel-setPixmap(pixmap.scaled(ui-videoLabel-size(), Qt::KeepAspectRatio)); } } } av_packet_unref(packet); }补充一个容易被忽略的性能细节sws_getContext不要在每一帧里都调用。它创建转换上下文是需要计算滤波器系数、分配临时缓冲区的成本很高。正确做法是在解码器初始化完成后创建一次放进循环外面复用。上面的代码为了演示简洁放在循环里实际项目里务必把它提升到循环之前。另一个细节是我在实际项目里发现的摄像头画面在 Qt 的QLabel上显示时如果源视频的分辨率很大比如 1920x1080而界面只有几百像素直接用setPixmap会造成很大的缩放开销。更稳妥的做法是用QPixmap::scaled加上Qt::KeepAspectRatio保持长宽比不变形。4.3 断线重连与资源释放容易被忽略的稳定性问题编译可用只是第一步要真正用于生产环境断线重连是必须考虑的。我的做法是把整个拉流解码逻辑封装成一个OpenVideoLoop函数放在一个单独的QThread里跑。主线程收到界面上“连接失败”或“播放中断”的信号后触发重连逻辑。核心重连代码大致这样void PlayerThread::run() { while (!m_stop) { if (open_rtsp(m_url)) { // 正常读取循环 decode_loop(); } // 到这里说明连接断开或读取失败 msleep(3000); // 3秒后重连 } }注意三个要点重连前要完整释放上次的上下文。avformat_close_input和avcodec_free_context都要调用否则内存泄漏和句柄泄漏会积累到崩溃。重连间隔要有退避策略。如果摄像头断电会持续请求失败。固定 3 秒间隔做简单重试可以接受如果接入的摄像头节点多建议用指数退避比如 3 秒、6 秒、12 秒递增。m_stop标志必须用原子变量或加锁。直接在主线程写一个 bool工作线程同时读在 C 里是多线程数据竞争用std::atomicint或volatile可以避免。资源释放的顺序也有讲究。正确的顺序是先avcodec_close再avformat_close_input最后释放sws_ctx。如果反过来先关输入再关解码器有概率在解码器内部访问到已经释放的流信息导致崩溃或异常退出。5. 常见编译错误与排查技巧实录我把这套组合在实际编译过程中最常遇到的错误整理成一张表每条都标注了原因和解决方向。你如果真遇到了问题可以按图索骥省得从头翻资料。错误现象根本原因解决方法cannot find -lavformat找不到导入库文件确认-L路径正确且库里存在libavformat.dll.aundefined reference to __imp_avformat_open_input链接的库是 MSVC 导入库.lib不是 MinGW 的 .dll.a重新下载 MinGW 可用的 FFmpeg 包avcodec-59.dll not found运行库 DLL 没有拷贝到 exe 所在目录把 FFmpeg bin 目录下所有 DLL 复制到构建输出目录moc: ... not built/unknown type name Q_OBJECT有 Q_OBJECT 宏的类没执行 moc 步骤在 .pro 里确认 HEADERS 已加入对应头文件Qt Creator 默认会处理若手动编译需手动执行moc运行时崩溃显示qt_assert或double free多半是 FFmpeg 库版本不一致或者创建了多份SwsContext未释放统一 FFmpeg 包版本只创建一次 sws 上下文退出时正常释放无效的参数错误avformat_open_input返回负数网络不通、RTSP 地址错误、协议未开启先用 VLC 验证地址可访问在代码里打印av_strerror(ret)查看具体错误码我把几个典型的排查场景展开来细说因为不少问题虽然现象不同但排查思路是相通的。5.1 排查“找不到库”类错误cannot find -lavformat这个报错的排查路径是先确认 FFmpeg 解压目录下lib文件夹里的文件清单是不是存在libavformat.dll.a。如果发现只有avformat.lib而没有.dll.a说明下载的是 MSVC 专用包直接换包路劲。这里有一个常见文件系统坑Windows 的资源管理器默认隐藏文件扩展名所以libavformat.dll.a可能显示成libavformat.dll且不会显示.a后缀。这时候用命令行的dir查看才是准确的dir D:\dev\third_party\ffmpeg\lib实际的输出应该类似libavformat.dll.a、libavcodec.dll.a这种形态。如果完全找不到.a后缀的文件几乎可以断定包选错了。5.2 排查“运行时缺 DLL”类错误编译通过、运行时报 DLL 缺失这是新手阶段最常见的情况。通常错误弹窗会明确提示缺哪个 DLL。解决思路很简单把 FFmpeg 的 bin 目录加入 PATH或者把所有 DLL 拷贝到 exe 所在目录。我推荐后者因为部署到别的机器上时不用依赖系统 PATH 环境变量。还有一个容易遗漏的点FFmpeg 运行依赖的未必只有它自己的 DLL还可能依赖libgcc_s_dw2-1.dll、libwinpthread-1.dll这类 MinGW 运行库。这些文件在 MinGW 编译器的bin目录下需要一并拷贝。如果你用的是 Qt 自带的 MinGW可以在C:\Qt\Tools\mingw810_32\bin找到它们。把整个bin目录下所有 DLL 一次性复制出来是最省心、也最稳妥的部署策略。5.3 排查链接错误区分“缺符号”和“库顺序错误”链接阶段最让人头疼的报错是undefined reference to avcodec_send_packet(...)。这类错误有两种可能一是库真的没链接进来二是链接顺序不对。验证方法很简单在已有的-lavformat、-lavcodec、-lavutil基础上把每个库都重复写一遍或者颠倒顺序试试。如果发现调整顺序后不再报错大概率就是顺序问题。MinGW 的链接器是单遍扫描它在解析某个.o文件时如果发现需要的符号尚未定义就只能往后找而库与库之间互相依赖时后面库被前面库的符号定义解决后前面的库就不会再被扫描于是会出现“先引用的库要放前面”的现象。避免这个问题的根本办法是把没有互相依赖的 FFmpeg 库按依赖关系排列-lavformat放最前-lavcodec次之-lavutil放最后。5.4 运行时崩溃的定位方法如果运行时崩溃但没有明显的日志信息可以用调试器来辅助定位。Qt Creator 加上 MinGW 工具链后F5 启动调试崩溃时查看调用栈call stack通常能直接看到是 FFmpeg 内部哪个库在什么场景下触发的。最常见的崩溃原因是SwsContext被重复释放或者AVFrame在被引用后又被av_frame_free释放了一次。建议用valgrind虽然 Windows 下支持有限或Dr. Memory辅助检查内存问题比肉眼效果好很多。6. 性能优化与界面渲染的实操心得编译可用只是第一步真正要做得流畅还需要在渲染路径上做一些优化。我这里集中讲几个我实际用过的优化点都是见效快、改动小的。6.1 避免多余拷贝QImage 的构造方式选择QImage的构造函数有几个重载。最简单粗暴的是每次从AVFrame的数据做一次内存拷贝生成独立的QImage。性能更好的做法是使用QImage的“不拷贝数据”构造方式让QImage直接引用rgbFrame内部的缓冲区从而省去一次 memcpyQImage img(rgbFrame-data[0], w, h, rgbFrame-linesize[0], QImage::Format_RGB888);但注意这种方式必须保证缓冲区的生命周期长于QImage。如果rgbFrame是局部变量且在函数返回时被释放而QImage被界面持有就会产生悬垂指针造成不可预期的崩溃。所以这种写法只适合在循环内同步使用——构造完QImage后立刻在循环内画到界面上不把它保存到成员变量里。如果你的逻辑需要把某一帧保存下来比如截图功能那时必须调用img.copy()做一次拷贝。6.2 刷新频率控制不要每个包都 repaint摄像头可能是 25 帧或 30 帧但 FFmpeg 解出来的帧率不一定均匀而且某些网络流会出现乱序、重复帧。如果解码循环是每读到一帧就刷新一次界面在某些模式下界面可能会出现明显的闪烁或卡顿。一个简单的方案是手动控制刷新率比如用QElapsedTimer做节流QElapsedTimer timer; timer.start(); const int frameIntervalMs 40; // 25 FPS 级别的刷新 while (av_read_frame(...) 0) { // 解码... if (timer.elapsed() frameIntervalMs) { ui-videoLabel-setPixmap(pixmap); timer.restart(); } }这个做法尤其在标清流720p 以下下有效因为解码速度远快于显示速度不加控制会导致界面刷新得太频繁视觉上反而产生闪烁。6.3 硬解码的可行性评估FFmpeg 在 Windows 下可以通过h264_qsvIntel Quick Sync、h264_cuvidNVIDIA GPU等硬件解码器减少 CPU 占用。但这里有个前提FFmpeg 的预编译包不一定包含这些解码器需要确认是否支持。另外硬解码输出的帧格式通常是 NV12 等而不是默认的 YUV420P需要额外转换。实际项目里如果只是显示一个或两个 RTSP 流CPU 软解完全够用。我这边在 i5-7500 上同时解码三路 1080pCPU 占用大约 40% 左右在工控机上还在可接受范围。除非你是要解码十几路流的大型平台否则先不折腾硬解把时间花在业务逻辑上更划算。6.4 界面卡顿的排查方法界面卡顿的原因通常是主线程做了耗时操作。RTSP 拉流、解码、格式转换这些逻辑如果在主线程里跑线程会被av_read_frame阻塞界面自然卡死。标准做法是把拉流解码放到独立线程主线程只负责接收QImage并显示。这个方案我用得最多稳定性和代码结构都比较清晰。7. 常见问题速查表与最后的实操建议7.1 问题排查总表问题可能原因检查顺序FFmpeg 库找不到库路径错误 / 下载的是 MSVC 包1. 确认.dll.a存在2. 检查.pro中-L路径3. 目录名不要带中文和空格运行缺 DLL依赖文件未拷贝1. 把 FFmpeg bin 下所有 DLL 拷到 exe 目录2. 把 MinGW 运行库 DLL 一并拷过去画面花屏或绿屏图像格式转换错误确认sws_scale的目标格式与QImage构造格式一致都是 RGB24拉流超时或卡死没设stimeout/ UDP 传输不稳建议显式设置rtsp_transporttcp并设置stimeout为 3000000 到 10000000重连无效没有释放旧上下文重新连接前必须完整avformat_close_input且新线程不要使用旧指针窗口关闭后进程仍在运行工作线程没退出重写closeEvent置m_stop true并wait()等待线程结束7.2 部署到其他电脑时的注意事项编译通过不代表部署顺畅。如果要把程序拷贝到没有开发环境的目标机器上运行除了 FFmpeg 的 DLL还需要带上 Qt 的发布工具。用 Qt 自带的windeployqt可以自动拷贝 Qt 依赖windeployqt RtspPlayer.exe它会自动分析可执行文件的依赖把需要的 Qt DLL、插件如 platforms/qwindows.dll都拷贝到目标目录。之后再手动把 FFmpeg 的 DLL 复制进去。如果没有 Qt 环境也可以把目标机器上安装对应的 Qt 运行库但我更推荐前者更干净。7.3 最后补充一个复用性技巧如果你以后还有别的 Qt 项目也要接 RTSP强烈建议把拉流和解码部分封装成一个独立的类比如RtspPlayer对外只暴露start(url)、stop()、以及一个frameReady(QImage frame)的信号。这样写的好处是代码可复用后续做录屏、截图、多路拼接都能基于这套接口快速扩。我在现在的项目里就是这样组织的把 FFmpeg 相关的细节全部藏在类内部界面上只做setPixmap一件事维护起来非常省事。这套 qt mingw32 windows ffmpeg rtsp 的方案从环境配置到代码落地踩过的坑和验证过的做法基本都写出来了。每个人实际遇到的报错可能会有差别但排查的路径是相通的——先确认工具链再确认库格式最后看运行依赖。抓住这三层大部分问题都能在一个小时内定位解决。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?