
简介这份VS2017编译的librtmp.lib库资源包面向在Windows 10环境下需要集成RTMP推流、拉流功能的C/C开发者。压缩包包含已编译好的librtmp.lib静态库、配套引用库目录以及可直接打开编译的VS2017解决方案librtmp.sln无需自行配置OpenSSL与zlib依赖即可一键生成目标库文件。压缩包共238个文件以h头文件、dll动态库、lib静态库、c源码及vs2017工程配置文件为主整体约49.12MB。目录结构覆盖lib、librtmp、openssl-1.0.1c、zlib-1.2.8等模块划分清晰方便按需引用或二次修改。资源已有635人浏览学习适合需要快速获得librtmp编译产物、避开复杂编译环境搭建的开发者。包内附带编译生成的构建日志与记录可作为排错参考帮助理解librtmp在VS2017下的完整编译链路。 写这篇东西的起因是我自己当年从各种渠道找编译好的librtmp.lib踩了一下午的链接错误。后来静下心把依赖库和源码放在一起配好工程一次性编译通过才意识到这玩意其实没那么玄乎。今天把这个“vs2017编译librtmp.lib库包含引用库和源代码可直接编译”的完整思路和实操过程整理出来给做直播推流、拉流、RTMP协议解析的朋友做个参考。librtmp是 RTMPDump 项目的核心 C 库负责 RTMP 协议的握手、AMF 编解码、流媒体数据收发。它没有官方维护的 Windows 预编译产物所以想在 Windows 上用librtmp.lib最常见的方式就是自己把源码和依赖库放在一起编一遍。本文涉及的 ZIP 包其实就是干这个事里面有 librtmp 的 C 源码、OpenSSL、zlib、pthread 这几个第三方依赖库的引用文件以及一个配置好的 Visual Studio 2017 解决方案打开就能编译。这个包适合三类人一类是项目里必须静态链接 librtmp不能带一堆 DLL 的一类是要跟踪 RTMP 层内部逻辑必须拿到完整调试符号的还有一类就是纯粹不想在配置 OpenSSL 和 zlib 上浪费时间想直接拿到.lib文件跑通 demo 的。下面从背景、依赖、编译流程、坑位排查、落地使用五个部分展开尽量把每个“为什么”都交代清楚。1. 为什么要自己编译 librtmp.lib1.1 librtmp 在技术栈里的位置先理清一个概念librtmp不是微软提供的系统库它来自开源项目 RTMPDump。整个 RTMPDump 项目分两部分命令行工具rtmpdump 可执行文件和核心库librtmp。我们做 Windows 开发时需要的是把核心库编译成.lib文件然后让自己的播放器或推流程序去链接。RTMP 协议本身工作在 TCP 之上默认端口 1935。握手过程是 C/S 双方各发 1536 字节的随机数据然后交换确认流媒体数据被切成一个个 chunk每个 chunk 有基本头、消息头、扩展时间戳这些字段。这些逻辑在rtmp.c、amf.c、parseurl.c里都有对应实现。第三方库只要调用RTMP_Init、RTMP_SetupURL、RTMP_Connect、RTMP_Write这一组 API就能完成推流或拉流。既然官方没有给你编译好的 Windows 库那摆在面前的路只有两条要么自己编要么用别人编好的。用别人编好的风险在于你不知道他用的 OpenSSL 版本、编译器版本、运行时库配置是否和你项目匹配。最常见的结果就是链接器报一堆 LNK2038 或 LNK2019到时候排查起来比自己编译还痛苦。1.2 什么场景下必须用静态库这里说的librtmp.lib是静态库。静态库和动态库DLL的核心区别是链接时把库代码复制进你的 exe运行时不依赖额外的 DLL 文件。我实际遇到过的几个场景对外发布绿色软件客户机器上很可能没有 VC 运行库也不方便安装。全静态链接后程序复制过去就能跑省去一堆环境问题。调试 RTMP 协议细节做 CDN 调度或者自研推流器时需要断点跟到librtmp内部看消息流程。用静态库编译出来的 Debug 版本符号都在自己手里随时能看。定制协议行为有些厂商的 RTMP 实现会在握手后多传几个自定义字段。直接用别人的库没法改自己编译就能在rtmp.c里加代码。顺带说一句librtmp的代码里有一个RTMP_DEBUG宏开启后会把每个 chunk 的收发日志打到 stderr。自己编译时想开就开想关就关这属于“带源码”的天然优势。2. 编译前的依赖关系和版本匹配2.1 librtmp 到底依赖哪些第三方库先明确一件事librtmp不是一个完全自包含的库。它依赖 OpenSSL 和 zlib在 Windows 上还需要处理线程抽象层。各依赖的作用OpenSSL提供 HMAC-SHA256、SHA256、RC4 等加密算法。RTMPERTMP 加密扩展和 RTMPSRTMP over TLS都要用到。打开rtmp.c能看到不少#include openssl/hmac.h之类代码这部分在链接期必须解析到符号。zlib提供 AMF 数据压缩。虽然主流 RTMP 场景很少开压缩但Makefile默认会编 zlib 支持所以把依赖加上能避免链接报错。pthreadlibrtmp内部用 POSIX 线程接口做锁。Windows 原生没有 pthread需要借助pthread.h的实现。常见方案是引入 mingw 的 winpthreads 或者 DCE 的 pthreads-win32。这个依赖比较隐蔽如果只看了rtmp.c里的 OpenSSL 调用很容易漏。下载引用的第三方库时版本越接近项目作者测试过的越好。某些 OpenSSL 版本把 HMAC 相关 API 的公开方式改了1.1.0 开始很多结构体变成不透明类型导致旧版librtmp源码编译报错。ZIP 包里之所以要放“引用库”而不是让你自己去下载就是为了锁定这些版本关系避免这类问题。2.2 为什么非要用 VS2017首先librtmp的源码很老它不挑编译器但挑 CRT 库的配置。VS2015、VS2017、VS2019、VS2022 生成的静态库默认使用的 C/C 运行时库版本和 UCRT 版本不同。VS2017 工程文件的平台工具集是v141如果你用 VS2019 打开则会提示做工具集升级升级后能不能编过要看你代码里有没有踩到编译器的行为变更。其次VS2017 是很多做流媒体开发的团队还在用的稳定版本。这个版本的 C 编译器对旧 C 代码的兼容性比较好librtmp这种上世纪风格的 C 代码大量隐式类型转换、没有严格原型警告在 VS2017 下几乎不报错到更新版本可能就变成 error 或 warning-as-error。所以如果你手上没有 VS2017建议装一个安装时勾选“使用 C 的桌面开发”把 MSVC v141 工具集和 Windows SDK 选上。安装完成务必把“Windows 10 SDK”和“VC 2017 工具集”两项都确认一下因为编译 OpenSSL 时需要nmake和rc.exe这些都由 VS 的“VC 工具集”提供。这里补充一条经验编译时VS2017 安装路径和工程路径都别带中文和空格。某些版本的工具链特别是 Perl 脚本参与的 OpenSSL 构建在中文路径下会出现莫名其妙的文件找不到错误省事起见最好统一用纯英文目录。2.3 引用库的目录结构怎么设计ZIP 包内的引用库通常按这种结构组织librtmp_deps/ ├── openssl/ │ ├── include/ # 头文件 │ │ ├── openssl/ │ │ └── ... │ ├── lib/ │ │ ├── libeay32.lib │ │ └── ssleay32.lib │ └── bin/ # 如果引用的是 DLL 版 OpenSSL ├── zlib/ │ ├── include/ │ │ ├── zlib.h │ │ └── zconf.h │ └── lib/ │ └── zlibstat.lib ├── pthread/ │ ├── include/ │ │ └── pthread.h │ └── lib/ │ └── pthreadVC2.lib └── README.txt # 说明文件include目录放头文件lib目录放.lib这是 C/C 工程的常见惯例。VS 工程里只需要把这两个目录配置到“附加包含目录”和“附加库目录”即可。要注意的是OpenSSL 和 zlib 也分 Debug/Release、x86/x64 版本。包内如果放了多份就对应好配置管理器别在图省事时全部选同一个。有一个判断依赖库是否匹配的经验打开openssl/lib目录看文件名是libeay32.lib还是libcrypto.lib。前者是 OpenSSL 1.0.x 的老命名后者是 OpenSSL 1.1.0 及之后的新命名。两种命名对应两代 API和librtmp源码的兼容性差别很大。如果编不过优先去查 OpenSSL 的版本。3. 从打开工程到编译通过的全过程3.1 解压后先看 README再打开解决方案拿到这个包含引用库和源代码的 ZIP 包之后第一步不是急着双击.sln而是先解压并看README.txt。通常作者会写明包内包含哪些源码、依赖库对应什么版本、支持 Debug 还是 Release、需要额外安装什么东西。这些信息能帮你避免折腾半天后才发现版本不对的问题。如果包内已经存在librtmp.sln直接双击打开即可。现在假设你有 VS2017能正常打开。打开后先做两件检查在“解决方案资源管理器”里看项目名称确认存在librtmp项目生成目标是librtmp.lib。在“配置管理器”里看当前活动解决方案配置通常默认是 Debug Win32。如果你实际需要 x64就新建或切换到 x64 配置。如果只有librtmp.vcxproj而没有.sln也不要紧在 VS2017 里选择“文件 → 新建 → 从现有代码创建项目”把源码目录指过去再手动配置项目属性。3.2 项目属性的关键配置项无论包内的工程有没有预配置你都需要确认以下属性设置配置项建议值说明平台工具集Visual Studio 2017 (v141)保持和 VS2017 一致Windows SDK 版本10.0.xxxxx.0看你安装了哪个版本只要能编译即可配置类型静态库(.lib)目标产物是librtmp.lib字符集未设置多字节librtmp 源码基本用 char 字符串预处理器_CRT_SECURE_NO_WARNINGS;WIN32;USE_OPENSSL;NO_CRYPTO看情况NO_CRYPTO如果定义了就跳过 OpenSSL但也会失去 RTMPE/RTMPS 支持一般不要轻易用C/C → 代码生成 → 运行库Release 用/MTDebug 用/MTd这一步最容易出错后面会细讲C/C → 附加包含目录指向openssl/include、zlib/include、pthread/include缺了就找不到头文件链接器 → 常规 → 附加库目录指向openssl/lib、zlib/lib、pthread/lib缺了就找不到 .lib链接器 → 输入 → 附加依赖项libeay32.lib;zlibstat.lib;pthreadVC2.lib按实际命名.lib文件名要和你包内一致预处理器里需要重点解释两个_CRT_SECURE_NO_WARNINGSRTMPDump 源码大量使用sprintf、strcpy这类函数VS2017 默认会报警告 C4996加上这个宏才能整洁地编译通过。USE_OPENSSLlibrtmp的rtmp.c里通过这个宏决定是否启用 OpenSSL 相关代码。如果包内启用了 OpenSSL却忘了定义这个宏可能导致头文件和源文件的编译配置不一致运行时行为异常。3.3 如果包内的工程没配好自己建立工程怎么操作不少网上的 ZIP 包只给了源码和依赖库但工程文件是坏的或者缺失。这时要手动创建工程不算难关键是别漏文件新建一个“空项目”Visual C → Windows 桌面 → 空项目命名librtmp_build。把librtmp目录下的 C 源码文件全部加入工程至少包括amf.c、hashswf.c、log.c、parseurl.c、rtmp.c。头文件rtmp.h、log.h、amf.h、bytes.h、http.h也要在目录里。添加 OpenSSL、zlib、pthread 的包含目录和库目录操作路径见上节表格。编译并查看输出。一个值得注意的细节hashswf.c在处理 SWF 文件哈希时也要用到 OpenSSL 的加密函数。如果把hashswf.c从工程里拿掉某些依赖RTMP_HashSWF符号的调用会链接失败。所以如果直接复制了别人的工程却因为报错把某个源文件移除了后续很可能在链接器阶段暴露问题。另一个容易被忽略的文件是bytes.h。这个头文件定义了小端字节序转换的宏librtmp在组装消息头时大量使用它。它不像rtmp.h那样被人熟知但缺失时编译会报一堆“找不到标识符”的错误。3.4 编译后的产物验证编译成功后在输出目录Debug 或 Release 目录下能看到librtmp.lib。体积通常在几百 KB 到 1MB 之间取决于是否包含调试符号和优化级别。只看到.lib文件还不够最好顺手写个小测试工程验证它真的能用。下面是最小的验证代码它不做实际的服务器连接只验证头文件和库文件能正确链接#include stdio.h extern C { #include rtmp.h } int main() { RTMP* rtmp RTMP_Alloc(); if (!rtmp) { printf(RTMP_Alloc failed\n); return -1; } RTMP_Init(rtmp); printf(RTMP_Init ok, sizeof(RTMP)%d\n, (int)sizeof(RTMP)); RTMP_Free(rtmp); return 0; }注意两点C 工程引入rtmp.h时必须包在extern C里否则 C 名字修饰会让链接器找不到符号RTMP_Alloc和RTMP_Free是配对的用来申请和释放RTMP结构体直接malloc这类的操作不适用于它内部维护的资源。4. 实际踩过的坑与排查技巧4.1 常见编译/链接错误速查表这里整理我实际遇到过的报错信息按第二条“错误现象”右侧的“原因”去排查效率最高错误现象直接原因解决办法error C1083: Cannot open include file: openssl/hmac.h附加包含目录没配好检查工程属性里的 VC 目录或 C/C 附加包含目录确保指向openssl/includeerror LNK2019: unresolved external symbol _HMAC_CTX_initOpenSSL 版本不匹配1.1.0 及以上改成了HMAC_CTX_new换 OpenSSL 1.0.2 系列或改用新版 API 的 librtmp 源码error LNK2038: mismatch detected for _ITERATOR_DEBUG_LEVEL: value 0 doesnt match value 2Debug 与 Release 混链或运行库配置不一致把主程序和所有 lib 的 Debug/Release 配置对齐/MTd和/MDd不要混用error LNK2019: unresolved external symbol _deflateInit_启用了 zlib 但没链接 zlib 库在附加依赖项里加上zlibstat.lib或对应 zlib 库error C2011: timespec : struct type redefinitionpthread.h 与系统头文件冲突更新 pthread 版本或在包含 pthread.h 之前先包含 windows.herror C4996: strcpy: This function or variable may be unsafe缺少_CRT_SECURE_NO_WARNINGS预处理器定义里加_CRT_SECURE_NO_WARNINGSfatal error LNK1104: cannot open file libcrypto.lib找不到 OpenSSL 库文件检查 OpenSSL lib 目录下的文件名1.1.0 后是libcrypto.lib出现链接错误时先看第一个错误别被后面几十条刷屏吓到。VS 的链接器经常因为一个符号找不到而连带报出大量“同样文件里的其他符号未解析”实际上源头往往只有一个。4.2 运行时库配置的深水区/MT 还是 /MD这个坑是最隐蔽的因为它在编译期不报错在运行期才炸。librtmp.lib作为一个静态库它内部使用哪个 C 运行时库决定了你在主程序里链接它的兼容性。VS2017 的 C 运行库有四种配置/MT链接静态的 libcmt.lib不依赖 VC 运行库 DLL。/MTdDebug 版静态运行库。/MD链接动态的 msvcrt 版本运行时需要 vcruntime140.dll。/MDdDebug 版动态运行库。规则很简单lib 和你最终的 exe/dll 的运行时库配置必须一致。如果你编译librtmp.lib用/MT但主程序用/MD那么单看链接过程可能没问题运行到分配内存或释放字符串时会由于堆管理方式不同而崩溃错误信息经常是HEAP CORRUPTION DETECTED。建议做法是你的主程序最终用哪种就用哪种编librtmp.lib并且 Debug 和 Release 分别建配置各编各的。不要图省事只编一个 Release 版本然后 Debug 调试时链接编译进 RTMP_DEBUG 的代码那个排查过程非常痛苦。4.3 多线程场景下的 pthread 链接隐患librtmp内部维护了一个 socket 接收缓冲区并对读写操作加了锁这部分在 Windows 上依赖 pthread 库。链接时如果没把 pthread 库加进附加依赖项链接器会报unresolved external symbol _pthread_mutex_lock之类的错误。但有一种更隐蔽的情况你的项目里已经有一个旧版 pthread 头文件它与librtmp源码里引用的 pthread 函数对不上导致编译期全部通过运行时pthread_mutex_lock进入死锁。我实际遇到过项目用的 pthread 是 2005 年的老版本链接也正常但只要多个线程同时调用RTMP_Write程序就卡住不动。后来把 pthread 库更新到 2.10.0 版本并重新编译librtmp.lib问题才消失。如果你发现自己编的librtmp.lib在多线程推流时随机卡死第一时间查 pthread 版本。5. 编译通过之后怎么用才稳妥5.1 引用 librtmp.lib 的项目需要哪些配置假设你现在已经拿到librtmp.lib要集成到自己的入口程序比如main.cpp或某静态库工程中需要把rtmp.h、amf.h、log.h等头文件路径加进“附加包含目录”。把librtmp.lib所在目录加进“附加库目录”。在“链接器 → 输入 → 附加依赖项”里填入librtmp.lib如果你编译时连了 OpenSSL zlib pthread则这些.lib也要一并填入。这一条很多人会漏只写 librtmp.lib结果报出一堆 OpenSSL 相关符号找不到。如果主程序是 C头文件引用处记得用extern C包裹。实际代码里初始化顺序也有讲究。librtmp没有显式的全局初始化函数但它内部用了静态变量所以调用RTMP_Alloc之前确保你的程序没有在main之前或之后立即卸载这个库。在多线程推流场景下建议在程序启动时先创建一个主线程调用一次RTMP_Init让相关初始化动作在单线程环境下完成再启动工作线程。5.2 如果换 VS 版本要不要重新编译很多朋友有一个误区既然都是.libVS2017 编出来的VS2019 打开主程序应该能直接链接。实际不是这样因为librtmp.lib内部引用了 CRT 符号而不同 VS 版本的 CRT 符号集略有差别。静态库的 COFF 格式虽然没有变但某些代码生成特性如安全函数替换会按编译器版本决定。所以换了 VS 版本后正确做法是把librtmp工程也用新版本编译器重编一遍同时保持依赖库版本不变。如果依赖库是老版本可能还需要同步升级。从长期可维护性看如果更新 VS 版本尽量把整个依赖链 OpenSSL、zlib、pthread 一起升级重编别只用旧库硬抗。5.3 由这个库还能扩展出去什么方向拿到librtmp.lib只是第一步。基于librtmp可以做不少二次开发在rtmp.c的RTMP_SendPacket里加数据统计逻辑统计每秒钟发送的字节数和帧数用于推流质量监控。用RTMP_ReadPacket做拉流分析把每个消息类型、时间戳、消息长度打印出来辅助排查推流端和播放端的时间戳不同步问题。结合自己的加密模块在 RTMP 握手完成后对消息体做额外的应用层加密实现私有信令保护。从实操角度我个人踩过几次坑之后总结出一个习惯不管从哪个渠道拿到的librtmp工程包解压之后先看一眼三个东西——OpenSSL 目录里的库文件名、工程属性里的运行库配置、源码里RTMP_Init函数的实现位置。确认这三点之后再编译基本能一次过。再说一个容易被忽略的小细节librtmp编译时默认会尝试读取rtmpdump项目里的dh.h和dhgroups.h这两个文件定义了握手时的 Diffie-Hellman 参数。如果你的包里没有这两个文件编译可能没问题某些版本会禁用完整握手但连接某些对端服务器时会握手失败。我的建议很简单要么确认包内包含这两个头文件要么在动手编译前先确认源码里是否引用了dh.h没有就直接补上别等连接阶段才排查。做流媒体底层库的编译调试确实琐碎但一旦把这条链路打通后面做播放器、推流器、协议分析工具都会顺畅很多。希望这篇整理能帮你少走点弯路顺利产出自己可控的librtmp.lib。本文还有配套的精品资源点击获取