VS2017编译librtmp.lib实战:资源包与避坑指南

发布时间:2026/10/13 8:51:47
VS2017编译librtmp.lib实战:资源包与避坑指南
简介本资源面向需要在 Windows 10 与 Visual Studio 2017 环境下使用 librtmp 的开发者提供一套可直接编译的 librtmp.lib 静态库工程解决自行编译时依赖库难找、配置繁琐的问题。压缩包共 238 个文件约 49.12MB包含 163 个 h 头文件、28 个 dll 动态库、8 个 lib 库文件以及 7 个 c 源文件并附带 openssl-1.0.1c、zlib-1.2.8 等依赖源码与预编译产物以及 librtmp.sln 解决方案和 vcxproj 工程文件目录按 lib、librtmp、openssl、zlib、vs2017 分层组织结构清晰。已有 637 人学习下载。读者可直接打开解决方案完成编译省去依赖库收集与工程配置环节同时借助源码与头文件理解 RTMP 协议实现、AMF 编解码、URL 解析及哈希校验等模块适合流媒体开发、直播推流调试及二次开发场景参考。1. 为什么我还在用 VS2017 编译 librtmp.lib一份能直接落地的资源包如果你在 Windows 上做过 RTMP 推流、直播客户端或者音视频采集大概率绕不开 librtmp 这个库。它本身是 RTMPDump 项目的一部分负责处理 RTMP 协议握手、chunk 分块、AMF 编码这些脏活累活让上层业务不用从零啃协议。但问题在于librtmp 官方源码默认走的是 Linux 那套 Makefile 流程放到 Windows 上要么用 MinGW 凑合要么就得自己手写 VS 工程文件而后者往往才是真正的血泪经验开始的地方。这份资源包解决的就是这个痛点它提供了完整的 VS2017 解决方案文件、预配置好的引用库依赖以及可直接编译的源代码。你不需要再去折腾 OpenSSL 的版本匹配、zlib 的链接顺序、或者 Windows SDK 的包含路径。拿到手之后用 VS2017 打开 sln改一下 OpenSSL 的路径点生成就能得到 librtmp.lib 和对应的头文件。适合谁适合那些需要在 Windows 原生环境下集成 RTMP 功能、又不想被编译环境卡住的中高级 C/C 开发者。新手如果只是想跑个 demo建议先看后面的避坑章节因为 OpenSSL 的坑几乎每个人都会踩一遍。2. 拆开这个包目录结构、依赖关系与 VS2017 工程配置2.1 资源包里到底有什么下载完解压之后你会看到类似这样的目录布局不同打包方式可能略有差异但核心文件不会少librtmp-vs2017/ ├── librtmp/ │ ├── amf.c │ ├── hashswf.c │ ├── log.c │ ├── parseurl.c │ ├── rtmp.c │ ├── rtmp.h │ ├── rtmp_sys.h │ ├── handshake.h │ └── ... ├── VS2017/ │ ├── librtmp.sln │ ├── librtmp.vcxproj │ └── librtmp.vcxproj.filters ├── openssl/ (可选有些包会附带预编译的 OpenSSL) │ ├── include/ │ └── lib/ └── README.md核心是librtmp目录下的 C 源文件和VS2017目录下的工程文件。librtmp 本身依赖两个外部库OpenSSL 和 zlib。OpenSSL 负责 RTMP 握手阶段的 SHA256 和 HMAC 计算以及 RTMPE 加密zlib 负责压缩块的处理。如果你的场景不需要 RTMPE 加密理论上可以裁掉 OpenSSL但那样会失去很多服务器兼容性常见做法还是老老实实把 OpenSSL 编进去。2.2 为什么选 VS2017 而不是更高版本VS2017 的 MSVC 工具集是 v141这个版本对 C99 的支持已经比较完整同时又不至于像 VS2019/2022 那样在默认配置上引入一些新的安全检查选项比如/sdl和/guard:cf这些选项在编译 librtmp 这种老派 C 代码时反而容易报一堆警告甚至错误。另一个现实原因是很多音视频项目的历史代码库就是基于 v141 工具集维护的升级工具集意味着要重新验证所有依赖库的 ABI 兼容性成本太高。所以如果你手头的项目锁定了 VS2017这份资源包就是最省事的路径。2.3 工程配置的关键参数打开librtmp.sln之后先别急着点生成。右键librtmp项目 → 属性重点检查这几个地方配置项推荐值说明配置类型静态库 (.lib)默认就是不用改平台工具集Visual Studio 2017 (v141)如果你装的是更高版本 VS需要手动选 v141C/C → 常规 → 附加包含目录$(SolutionDir)..\openssl\include指向 OpenSSL 头文件链接器 → 常规 → 附加库目录$(SolutionDir)..\openssl\lib指向 OpenSSL 的 lib 文件C/C → 预处理器 → 预处理器定义_CRT_SECURE_NO_WARNINGS屏蔽老式 CRT 函数的警告C/C → 代码生成 → 运行库多线程 (/MT) 或 多线程 DLL (/MD)必须和你的主项目一致否则链接会报错这里特别说一下运行库的选择。librtmp 编译成静态库时运行库选项不会直接影响 .lib 文件本身但会影响你最终链接时的符号解析。如果你的主项目用的是 /MD而 librtmp 编译时用了 /MT链接阶段就会出现LNK2038不匹配的错误。我一般会先确认主项目的设置然后让 librtmp 保持一致。2.4 编译前的依赖准备如果你拿到的包里没有附带 OpenSSL那就需要自己准备一份。常见做法是去下载 OpenSSL 1.0.2 或 1.1.1 的 Windows 预编译版本注意位数要和你的目标平台一致x86 对 x86x64 对 x64。下载后把 include 和 lib 目录放到资源包根目录下和librtmp文件夹平级。zlib 的情况类似但很多 OpenSSL 的 Windows 包会自带 zlib 的静态库所以可以先检查一下openssl/lib下面有没有zlib.lib或zlibstatic.lib。如果没有单独下一个 zlib 源码用 VS2017 编一下也很简单新建一个静态库工程把*.c加进去直接编译就行。提示OpenSSL 1.1.x 和 1.0.x 的头文件路径略有不同1.1.x 的 include 目录下直接是openssl/文件夹而 1.0.x 可能多一层。配置附加包含目录时确保#include openssl/ssl.h能被正确找到。3. 从源码到 librtmp.lib编译步骤、链接顺序与符号导出3.1 逐步编译流程假设你已经把 OpenSSL 和 zlib 准备好了目录结构也调整到位了接下来按这个顺序操作第一步用 VS2017 打开VS2017/librtmp.sln。如果提示“重定向项目”选择“取消”不要升级工具集否则 v141 的配置会被覆盖。第二步在解决方案资源管理器里右键librtmp项目选择“属性”按照上一节的表格逐项核对。重点确认附加包含目录和附加库目录的路径是真实存在的。第三步切换到“生成事件” → “预生成事件”如果你看到有拷贝 OpenSSL DLL 的命令可以删掉因为静态库不需要 DLL。但如果是编译动态库版本那就保留。第四步选择配置为Release平台为x64或Win32取决于你的目标。右键项目 → “仅生成”。如果一切顺利你会在VS2017/x64/Release/下面看到librtmp.lib。第五步验证符号。打开“开始菜单” → “VS2017 开发人员命令提示符”cd 到 lib 所在目录执行dumpbin /symbols librtmp.lib | findstr RTMP_Init RTMP_Connect RTMP_SendPacket如果能看到这些符号被导出或者至少存在说明编译成功。静态库不需要__declspec(dllexport)所以符号默认是外部链接的dumpbin 能查到就够用。3.2 链接顺序为什么重要在 VS 里链接静态库时顺序其实不像 GCC 那么敏感因为 MSVC 的链接器会多次扫描库文件。但有一个例外如果 librtmp 依赖 OpenSSL而 OpenSSL 又依赖ws2_32.lib和crypt32.lib那么你在主项目的链接器输入里必须把这些系统库也加上。常见做法是在主项目的“链接器 → 输入 → 附加依赖项”里写librtmp.lib libssl.lib libcrypto.lib ws2_32.lib crypt32.lib zlib.lib顺序上librtmp.lib放最前面后面跟它依赖的库。如果你遇到LNK2019无法解析的外部符号九成是某个依赖库没加或者路径不对。3.3 一个最小可用的推流验证代码编译出 lib 之后别急着集成到大项目里。先写一个最小的测试程序确认库能正常初始化和连接。下面这段代码只做一件事初始化 librtmp、设置推流地址、尝试连接。#include stdio.h #include stdlib.h #include rtmp.h int main(int argc, char* argv[]) { RTMP* rtmp RTMP_Alloc(); if (!rtmp) { printf(RTMP_Alloc failed\n); return -1; } RTMP_Init(rtmp); // 设置推流地址格式如 rtmp://live.example.com/app/streamkey if (!RTMP_SetupURL(rtmp, rtmp://127.0.0.1/live/test)) { printf(RTMP_SetupURL failed\n); RTMP_Free(rtmp); return -1; } // 启用写入模式这一步不能漏 RTMP_EnableWrite(rtmp); if (!RTMP_Connect(rtmp, NULL)) { printf(RTMP_Connect failed\n); RTMP_Free(rtmp); return -1; } if (!RTMP_ConnectStream(rtmp, 0)) { printf(RTMP_ConnectStream failed\n); RTMP_Close(rtmp); RTMP_Free(rtmp); return -1; } printf(Connected to RTMP server successfully\n); RTMP_Close(rtmp); RTMP_Free(rtmp); return 0; }这段代码的逻辑很直白RTMP_Alloc分配句柄RTMP_Init初始化默认值RTMP_SetupURL解析地址RTMP_EnableWrite告诉库这是推流而不是拉流然后RTMP_Connect建立 TCP 连接并完成握手最后RTMP_ConnectStream创建流通道。参数方面RTMP_SetupURL的第二个参数必须是完整的 RTMP URL不能省略端口默认 1935 可以省略。RTMP_Connect的第二个参数是可选的结构体一般传 NULL 就行。编译这个测试程序时记得把librtmp.lib、libssl.lib、libcrypto.lib、ws2_32.lib、crypt32.lib、zlib.lib都加到附加依赖项里。如果连接本地服务器失败先检查服务器是否在监听 1935 端口再检查防火墙。3.4 静态库和动态库的选择边界这份资源包默认生成的是静态库.lib。静态库的好处是部署简单不需要额外带 DLL坏处是如果多个模块都链接了 librtmp最终可执行文件里会有多份副本体积膨胀。如果你的项目是单一 exe静态库完全够用。如果是插件架构或者多个 DLL 共享 librtmp那就需要改成动态库。改法是在项目属性里把“配置类型”改成“动态库 (.dll)”然后在rtmp.h里给需要导出的函数加上__declspec(dllexport)。不过 librtmp 的头文件并没有预置导出宏手动加的话工作量不小常见做法是写一个.def模块定义文件把要导出的函数名列进去。4. 避坑指南OpenSSL 版本、运行库不匹配与常见链接错误4.1 现象编译时报openssl/ssl.h找不到原因附加包含目录的路径写错了或者 OpenSSL 的目录结构和预期不一致。OpenSSL 1.1.1 的 Windows 包解压后通常是OpenSSL-Win64/include/openssl/ssl.h而你的附加包含目录应该指向OpenSSL-Win64/include而不是OpenSSL-Win64/include/openssl。解决在项目属性里把附加包含目录改成$(SolutionDir)..\openssl\include然后在代码里用#include openssl/ssl.h。如果还是找不到在“C/C → 常规 → 显示包含目录”里看一下实际搜索路径确认没有多余的层级。4.2 现象链接时报LNK2038: 检测到“RuntimeLibrary”的不匹配项原因librtmp 编译时用的运行库和主项目不一致。比如 librtmp 用了/MT主项目用了/MD链接器就会拒绝合并。解决统一运行库选项。打开 librtmp 项目属性 → C/C → 代码生成 → 运行库改成和主项目一样的值。如果不确定主项目用的是什么在 VS 里右键主项目 → 属性 → C/C → 代码生成 → 运行库看一眼即可。改完之后重新编译 librtmp再重新链接主项目。4.3 现象RTMP_Connect返回失败但网络是通的原因RTMP 握手阶段需要计算 HMAC 和 SHA256这些依赖 OpenSSL 的加密函数。如果 OpenSSL 的 lib 文件链接了但版本不对比如用了 3.x 的头文件配 1.1.x 的 lib握手就会静默失败。解决确保 OpenSSL 的头文件和 lib 文件来自同一个版本。我一般会在代码里加一行printf(OpenSSL version: %s\n, OpenSSL_version(OPENSSL_VERSION));来确认运行时加载的版本。另外librtmp 对 OpenSSL 1.1.1 的兼容性最好3.x 版本因为 API 变动较大可能需要打补丁才能编译通过。4.4 现象编译成功但推流几秒后断开原因librtmp 默认的 chunk size 和超时参数可能不适合你的网络环境。特别是在跨运营商或者高延迟场景下默认的 30 秒超时可能不够。解决在RTMP_Connect之前设置超时参数rtmp-Link.timeout 60; // 单位秒 rtmp-m_outChunkSize 4096; // 增大 chunk size 减少分包timeout控制 socket 读写超时m_outChunkSize控制发送分块大小。这两个参数没有银弹需要根据实际网络质量调整。我一般会先用默认值跑如果频繁断开再逐步加大。4.5 现象x64 平台编译报fatal error C1189: #error: This file requires _WIN32_WINNT to be #defined原因librtmp 的某些源文件依赖 Windows SDK 的版本宏VS2017 默认可能没有定义_WIN32_WINNT。解决在项目属性 → C/C → 预处理器 → 预处理器定义里加上_WIN32_WINNT0x0601对应 Windows 7或0x0A00对应 Windows 10。一般设成0x0601兼容性最好。5. 进阶技巧用 dumpbin 验证符号、裁剪不需要的模块与版本管理5.1 用 dumpbin 做编译后验证编译出librtmp.lib只是第一步你还需要确认它真的包含了所有需要的符号。除了前面提到的dumpbin /symbols还有一个更实用的命令dumpbin /headers librtmp.lib | findstr machine这条命令会输出 lib 文件的目标架构。如果是 x64你会看到machine (x64)如果是 x86会看到machine (x86)。这个检查很有必要因为如果你不小心用 Win32 配置编译了 lib却试图在 x64 项目里链接链接器会直接报错而且错误信息不一定直观。另一个技巧是用dumpbin /exports查看动态库的导出表但静态库没有导出表所以这个命令对 .lib 不适用。对于静态库/symbols是主要手段。5.2 裁剪不需要的模块librtmp 的源码里有一些模块在特定场景下是可以裁掉的。比如hashswf.c负责 SWF 验证如果你推流的服务器不需要 SWF 校验可以把这个文件从工程里移除。log.c提供日志输出如果不需要调试信息也可以去掉。但要注意rtmp.c里可能引用了这些模块的函数移除之前先全局搜索一下符号引用。裁剪的好处是减小 lib 体积但坏处是以后如果需要这些功能得重新加回来。我一般会保留完整源码只在最终链接时让链接器自动丢弃未引用的函数MSVC 默认就会做这个优化。所以除非有明确的体积要求否则不建议手动裁剪源文件。5.3 版本管理与团队协作如果你是在团队里使用这份资源包建议把librtmp的源码和 VS 工程文件一起纳入版本控制Git 或 SVN。但 OpenSSL 和 zlib 的二进制文件不要提交因为体积大且平台相关。常见做法是写一个setup.bat脚本让每个开发者自己下载 OpenSSL 并放到指定目录。脚本内容大致如下echo off if not exist openssl ( echo Please download OpenSSL 1.1.1 Win64 and extract to openssl/ exit /b 1 ) if not exist zlib ( echo Please download zlib and extract to zlib/ exit /b 1 ) echo Dependencies ready.这个脚本不复杂但能避免“在我机器上能编译”的经典问题。另外在 README 里写清楚 VS2017 的版本号比如 15.9.x和 Windows SDK 的版本因为不同小版本的 MSVC 在警告级别上可能有差异。5.4 一个我踩过的坑别在 Debug 模式下发布早期我为了调试方便直接用 Debug 配置编译了 librtmp.lib然后链接到 Release 版的主项目里。结果程序运行起来性能极差推流延迟高得离谱。后来才发现 Debug 版的 librtmp 带了大量断言和调试检查而且运行库是/MDd和 Release 主项目的/MD不匹配链接器虽然没报错但运行时行为完全不对。从那以后我每次编译静态库都强制走一遍 Release 配置并且在链接前用dumpbin /directives确认运行库版本。这个习惯帮我省了很多莫名其妙的调试时间。希望这份笔记能帮你顺利把 librtmp.lib 编出来少走点弯路。本文还有配套的精品资源点击获取