恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
VS2017编译librtmp.lib完整指南:依赖配置、源码修改与避坑实践
首页
资讯中心
/
VS2017编译librtmp.lib完整指南:依赖配置、源码修改与避坑实践
VS2017编译librtmp.lib完整指南:依赖配置、源码修改与避坑实践
发布时间:2026/10/13 1:25:38
简介这份资源面向需要在 Windows 10 与 VS2017 环境下使用 RTMP 协议的 C/C 开发者提供可直接编译的 librtmp.lib 静态库工程解决自行编译时依赖库难找、配置繁琐的问题。压缩包共 238 个文件约 49.12MB以 163 个 h 头文件、28 个 dll 动态库、8 个 lib 库文件及 7 个 c 源文件为主另含 sln 解决方案、vcxproj 工程与编译日志等覆盖 librtmp、openssl-1.0.1c、zlib-1.2.8 及 vs2017 目录依赖关系完整。已有 637 人学习下载说明该编译方案在流媒体开发场景中具备一定参考价值。读者可直接打开 librtmp.sln 编译出目标库省去逐一下载与配置 OpenSSL、zlib 的步骤同时借助源码与头文件理解 RTMP 握手、AMF 编解码、URL 解析等模块的实现适合需要快速集成推流或拉流功能的初中级开发者对照使用。1. 为什么 2024 年还有人要在 VS2017 里啃 librtmp.lib如果你手上正好有一份「vs2017编译librtmp.lib库包含引用库和源代码可直接编译.zip」大概率不是为了做直播推流而是被某个老项目卡住了要么是维护一套工业相机的 RTMP 上传模块要么是给一套已经跑了七八年的 C 客户端补一个断线重连的推流能力。librtmp 这个库本身不新但它的价值在于「纯 C、无 C 运行时依赖、能静态编进 exe」这在 VS2017 这种 MSVC 工具链下反而比很多现代库好落地。问题在于网上能搜到的教程大多停留在 VS2013 甚至 VC6 时代直接照抄会在openssl头文件、ssize_t重定义、zlib链接顺序上连续翻车。这篇笔记就按「拿到压缩包之后怎么一步步编出能用的 librtmp.lib」来讲顺带把引用库怎么配、源码怎么改、参数怎么设讲透适合手上有源码但一编译就报错的人。2. 先搞清楚 librtmp 在 VS2017 下的依赖链2.1 librtmp 到底依赖哪几个库为什么缺一不可librtmp 的源码结构其实很朴素核心就是rtmp.c、amf.c、hashswf.c、log.c、parseurl.c这几个文件。但它不是自包含的编译前必须先把依赖关系理清楚否则你会看到一堆cannot open include file openssl/ssl.h或者unresolved external symbol _inflate。它真正依赖的是三个东西OpenSSL负责 RTMPSRTMP over TLS的握手和加解密。如果你只做rtmp://明文推流理论上可以裁掉但源码里rtmp.c有大量#ifdef CRYPTO分支直接删会牵连hashswf.c的握手逻辑不划算。常见做法是保留用 OpenSSL 1.0.2 或 1.1.1 的静态库。zlib处理 RTMP 的压缩块Set Chunk Size之后的压缩数据。rtmp.c里RTMP_SendPacket会调用compress没有 zlib 会直接链接失败。Win32 系统库ws2_32.libsocket、winmm.lib部分时间函数、crypt32.libOpenSSL 在 Windows 下会用到证书存储。这里有个容易忽略的点VS2017 默认的 MSVC 工具集是 v141而很多老教程给的 OpenSSL 预编译库是 v100 或 v120 工具集编的。混用不是一定崩但_MSC_VER不一致时openssl的applink.c会报LNK2019。所以第一步不是急着编译 librtmp而是先确认你手上的 OpenSSL 和 zlib 是不是 v141 编出来的。2.2 压缩包里「引用库」和「源代码」分别该放哪拿到那个 zip 之后先别双击 sln。我一般会先解压到一个没有中文、没有空格的路径比如D:\dev\librtmp_vs2017\。然后按下面的结构整理librtmp_vs2017/ ├── src/ # librtmp 源码 │ ├── rtmp.c │ ├── amf.c │ ├── hashswf.c │ ├── log.c │ ├── parseurl.c │ └── rtmp_sys.h ├── include/ # 对外头文件 │ ├── rtmp.h │ ├── amf.h │ └── log.h ├── deps/ │ ├── openssl/ │ │ ├── include/openssl/ │ │ └── lib/x64/ # libssl.lib libcrypto.lib │ └── zlib/ │ ├── include/ │ └── lib/x64/ # zlibstatic.lib └── build/ └── librtmp.vcxproj这个结构不是强迫症而是为了让 VS2017 的「附加包含目录」和「附加库目录」能写成相对路径。一旦你用了绝对路径换台机器或者换个盘符就全红。压缩包里如果已经带了.vcxproj先看它的「平台工具集」是不是 v141不是就右键项目 → 属性 → 常规 → 平台工具集改成 Visual Studio 2017 (v141)。提示如果压缩包里的引用库只有 Win32 版本而你要编 x64不要试图混用。直接去 OpenSSL 和 zlib 的官方发布页找对应架构的静态库或者自己用 VS2017 的 x64 本机工具命令提示符编一遍。3. 用 VS2017 从源码编出 librtmp.lib 的完整步骤3.1 新建静态库项目并导入源码不要直接用压缩包里的 sln除非你确认它没有硬编码路径。我习惯新建一个「静态库Windows」项目名字叫librtmp位置放在build/下。然后把src/里的.c文件全部「添加 → 现有项」进来include/里的.h不用加进项目但要在包含目录里指过去。关键一步librtmp 是 C 代码但 VS2017 新建的静态库项目默认会生成.cpp的编译规则。如果你直接把.c文件加进去MSVC 会按 C 编译这没问题。但如果你不小心把某个文件重命名成.cpprtmp.c里的ssize_t和struct timeval就会报重定义。所以保持.c后缀别手贱。项目属性里需要改这几处配置项值说明配置类型静态库 (.lib)不要选动态库C/C → 常规 → 附加包含目录..\..\include;..\..\deps\openssl\include;..\..\deps\zlib\include顺序不能反C/C → 预处理器 → 预处理器定义_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NO_CRYPTO可选见下文链接器 → 常规 → 附加库目录..\..\deps\openssl\lib\x64;..\..\deps\zlib\lib\x64按架构选链接器 → 输入 → 附加依赖项libssl.lib;libcrypto.lib;zlibstatic.lib;ws2_32.lib;winmm.lib;crypt32.lib顺序有讲究NO_CRYPTO这个宏要慎用。定义了它hashswf.c里的HMACsha256会走空实现RTMP 握手能过但如果你推流到某些要求swfVerification的服务器会直接被拒。我一般只在确认服务端不校验 SWF 时才开。3.2 改掉三个必改的源码兼容点即使你依赖库都配对了VS2017 下直接编 librtmp 还是会撞上三个经典错误。这不是压缩包的问题是 librtmp 源码年代太久。第一个ssize_t未定义。在rtmp_sys.h里Windows 分支没有定义ssize_t。解决办法是在rtmp_sys.h的#ifdef _WIN32块里加一行#ifdef _WIN32 #include winsock2.h #include ws2tcpip.h typedef int ssize_t; // MSVC 没有 ssize_t用 int 顶替 #endif注意typedef要放在#include windows.h之前否则winsock2.h和windows.h的顺序问题会让你看到redefinition of fd_set。第二个struct timeval重定义。如果你同时包含了winsock2.h和sys/time.hMSVC 会报timeval冲突。librtmp 的rtmp_sys.h里已经处理了但如果你自己写的测试工程也包含了sys/time.h就会撞。统一用winsock2.h里的定义别引sys/time.h。第三个snprintf和strsafe.h。VS2017 的stdio.h已经提供了snprintf但 librtmp 里有些地方用了_snprintf。如果你在预处理器里定义了snprintf_snprintf会报宏展开错误。正确做法是不要定义这个宏让 MSVC 用标准的snprintf。改完这三处右键项目 → 生成。如果一切顺利你会在build/x64/Debug/或Release/下看到librtmp.lib。Debug 版大概 1.2 MBRelease 版 300 KB 左右具体看你有没有开/GL。3.3 链接顺序和运行库选项怎么设才不报 LNK2019静态库本身不链接但你在测试工程里链接librtmp.lib时顺序错了就会报unresolved external symbol。MSVC 的链接器是从左到右解析符号的所以依赖库必须放在librtmp.lib后面librtmp.lib libssl.lib libcrypto.lib zlibstatic.lib ws2_32.lib winmm.lib crypt32.lib另一个大坑是运行库选项。librtmp 源码里用了malloc/free如果你编 librtmp 时用的是/MT多线程静态运行库而测试工程用的是/MD多线程 DLL 运行库链接时会报RuntimeLibrary不匹配。统一成/MT或/MD我一般用/MT因为静态库最终要嵌进 exe少一个 DLL 依赖少一份麻烦。注意OpenSSL 的预编译库通常是用/MD编的。如果你坚持/MT就得自己用 VS2017 的 x64 本机工具命令提示符重新编 OpenSSLperl Configure VC-WIN64A no-shared --prefix...然后nmake。这一步大概 20 分钟但能省掉后面一堆运行库冲突。4. 编译通过只是开始链接和调用时的避坑清单4.1 现象LNK2019 找不到_SSL_new但库目录明明配了原因OpenSSL 1.1.1 之后libssl.lib和libcrypto.lib的符号导出方式变了如果你用的是 1.0.2 的头文件配 1.1.1 的库或者反过来就会找不到符号。另一个可能是你配的是 Win32 的库目录但项目平台是 x64。解决先确认deps/openssl/include/openssl/opensslv.h里的OPENSSL_VERSION_NUMBER和库文件版本一致。然后检查项目属性 → 链接器 → 常规 → 附加库目录路径里是不是有x64。最后用dumpbin /symbols libssl.lib | findstr SSL_new确认符号确实在库里。4.2 现象运行时报RTMP_Connect1, handshake failed原因这不是编译问题是握手失败。常见于你用了NO_CRYPTO但服务端要求加密握手或者 zlib 压缩块处理出错。还有一种情况是rtmp_sys.h里的CRYPTO宏没开导致hashswf.c的HMACsha256返回空。解决先抓包看服务端返回的握手包。如果服务端是 nginx-rtmp默认不校验 SWFNO_CRYPTO可以过。如果是 SRS 或某些云厂商的 RTMP 入口必须开CRYPTO并链接 OpenSSL。检查rtmp.c里RTMP_Connect1的返回值-1是 socket 错误-2是握手失败。4.3 现象Debug 版能跑Release 版一推流就崩原因Release 版开了/O2优化librtmp 里有些地方依赖volatile或者未定义行为比如amf.c里的AMF_DecodeNumber对double的字节序处理。另一个可能是/GL全程序优化和静态库的/LTCG不匹配。解决先把 Release 的优化改成/Od试一下如果好了再逐级开/O1、/O2定位。我遇到过hashswf.c里HMACsha256在/O2下被优化掉中间变量导致哈希结果不对。临时办法是给那个函数加#pragma optimize(, off)。4.4 现象zlibstatic.lib链接后报_inflate_fast重复定义原因你的工程里可能同时链接了zlibstatic.lib和另一个带 zlib 的库比如 libpng 自带的。MSVC 不报冲突但链接器会随机选一个导致运行时解压出错。解决用dumpbin /symbols检查两个库的符号确保只链接一个。如果必须共存把其中一个的符号用/alternatename重定向但更简单的做法是统一用同一个 zlib 版本。4.5 现象编译时提示cannot open file libcrypto.lib但文件就在那原因路径里有中文或空格或者你在「附加依赖项」里写了绝对路径但盘符变了。VS2017 对中文路径的支持时好时坏尤其是lib文件。解决把整个工程挪到纯英文路径比如D:\dev\librtmp_vs2017\。然后在「附加库目录」里用相对路径不要用D:\...这种绝对路径。如果还不行在「附加依赖项」里直接写..\..\deps\openssl\lib\x64\libcrypto.lib绕过库目录搜索。5. 把 librtmp.lib 塞进实际工程一个最小可用的推流验证编出.lib只是第一步真正要验证它能不能用得写一个最小的推流程序。下面这段代码我用了很多次专门用来验证 librtmp 的编译结果是否完整。它不依赖任何 C 特性纯 C直接贴进 VS2017 的空项目就能跑。#include stdio.h #include string.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); // 推流地址换成你自己的 const char* url rtmp://127.0.0.1/live/test; if (!RTMP_SetupURL(rtmp, (char*)url)) { printf(RTMP_SetupURL failed\n); RTMP_Free(rtmp); return -1; } // 开启推流模式不设这个会变成播放 RTMP_EnableWrite(rtmp); // 超时设 5 秒避免卡死 rtmp-Link.timeout 5; 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, ready to send\n); // 这里可以调用 RTMP_SendPacket 发数据 // 验证完就关掉 RTMP_Close(rtmp); RTMP_Free(rtmp); return 0; }这段代码的逻辑很直白RTMP_Alloc分配句柄RTMP_Init初始化RTMP_SetupURL解析地址RTMP_EnableWrite切到推流模式然后RTMP_Connect和RTMP_ConnectStream完成握手和流建立。参数上唯一要改的是urltimeout可以根据网络情况调到 10 秒。如果你在RTMP_Connect就返回失败回去看第 4.2 节的握手排查。编译这个测试工程时记得把librtmp.lib和它的依赖库按第 3.3 节的顺序加进「附加依赖项」。运行前先确认本地有一个 RTMP 服务端在监听nginx-rtmp 或者 SRS 都行。如果连上了但推流几秒后断检查RTMP_SendPacket的返回值通常是 chunk size 没协商好。提示这个测试程序不要用Debug版去连生产环境Debug 版的 librtmp 带_DEBUG宏握手时的随机数生成会慢很多容易被服务端判定超时。6. 几个让 librtmp 在 VS2017 下更稳的进阶习惯编出.lib之后我一般还会做三件事算是血泪经验攒下来的。第一件是给librtmp.lib做一个Release和Debug的分离目录。很多人图省事只编一个版本结果 Debug 工程链接了 Release 库运行时报_ITERATOR_DEBUG_LEVEL不匹配。我的做法是在build/下建x64/Debug/和x64/Release/分别放对应的.lib然后在测试工程里用宏区分#ifdef _DEBUG #pragma comment(lib, ..\\build\\x64\\Debug\\librtmp.lib) #else #pragma comment(lib, ..\\build\\x64\\Release\\librtmp.lib) #endif第二件是给rtmp.c里的RTMP_Connect加一层重试。librtmp 原生不带重连网络抖动一次就断。我一般会在调用层包一个for循环重试 3 次每次间隔 2 秒超过就放弃。注意重试前必须RTMP_Close再RTMP_Free不能复用同一个句柄否则 socket 状态是脏的。第三件是记录RTMP_GetLastError的返回值。librtmp 的错误信息很粗但RTMP_GetLastError能给出RTMP_Connect失败的具体阶段。我习惯在每次失败时打一行日志格式是[librtmp] stage%d err%sstage 用rtmp-m_error或者自己埋点。这样线上出问题时至少知道是 DNS 解析、TCP 连接还是握手阶段挂的。最后一个习惯是关于源码管理的。那个 zip 里的源码不要直接改改之前先git init一下把原始版本提交一次。然后每改一个兼容点就提交一次注释写清楚为什么改。我见过太多人改完rtmp_sys.h之后忘了改了什么换台机器重新解压又得重来。源代码管理不是形式是后悔药。希望帮到你。本文还有配套的精品资源点击获取