
简介这套librtmp源码包是专为需要在Linux环境下进行交叉编译的开发者准备的完整工程资源。librtmp是rtmpdump的核心组件提供RTMP协议底层实现该资源实测可在Linux主机上为ARM等目标架构构建库文件解决嵌入式实时流媒体应用的移植需求。压缩包共106个文件、约4.35MB以86个h头文件、5个c源文件及6个lib库文件为主同时包含Makefile、vcxproj工程文件和COPYING授权说明等结构清晰便于直接查看和修改编译配置。内容涵盖rtmp.c、amf.c、hashswf.c、parseurl.c、log.c等关键模块可帮助理解RTMP握手、消息解析、AMF编解码及URL处理等实现细节。目前已有1422人学习下载适合Linux开发者和嵌入式工程师参考尤其适用于需要定制或移植librtmp以接入RTMP直播服务的项目。1. 为什么要在 Linux 下交叉编译 librtmp一个推流设备的血泪起点做嵌入式直播推流的人迟早会遇到同一个坎设备端是 ARM 架构跑的是 Linux但你的开发机是 x86上面跑着 Ubuntu。直接在 ARM 板子上编 librtmp 也不是不行但交叉编译才是正路。librtmp 是 RTMP 协议实际上的事实标准客户端库几乎所有开源推流方案都绕不开它无论是做摄像头直播、无人机图传还是边缘计算盒子最终都要把视频流通过 RTMP 推到媒体服务器上。这篇文章就是把我自己踩过的交叉编译流程完整走一遍从工具链选型、依赖库处理、Makefile 参数到最终在目标板上跑起来每一步都写清楚参数和坑在哪给正在做嵌入式流媒体开发的人一份能直接照着干的参考。适合手里有具体推流任务、打算在 Linux 环境下把 librtmp 编到 ARM 平台的开发者。2. 交叉编译前的三个准备工具链、依赖库与配置参数2.1 为什么依赖库必须自己先交叉编译一遍librtmp 本身不是一个完全自包含的库它依赖 OpenSSL 提供加密和握手能力依赖 zlib 处理压缩。这两个库在开发机上通常都有现成的版本但那些是给 x86 架构编译的目标板上根本没法用。交叉编译的核心逻辑是你在一台 x86 机器上用针对 ARM 架构的编译器产出一份 ARM 机器能运行的库文件。很多人在这里会犯第一个错误觉得 librtmp 的 configure 脚本会自动处理依赖。实际上 librtmp 的 Makefile 设计得非常朴素它不会帮你自动定位 OpenSSL 和 zlib 的头文件与库文件位置全靠你在编译时通过参数告诉它。所以交叉编译的第一步不是碰 librtmp而是先把 OpenSSL 和 zlib 交叉编译好产出一套针对 ARM 的安装目录再把这个目录的路径传给 librtmp。我一般会在工作目录下建一个_install文件夹把所有交叉编译产物的头文件和静态库都统一放到里面这样后续编译 librtmp 时只需要把INC指向_install/include把XLDFLAGS指向_install/lib既干净又不容易漏路径。2.2 工具链选择与核心参数说明交叉编译工具链的选择取决于你的目标架构。我这边用的是 arm-linux-gnueabihf-gcc这对应的是 ARM 32 位硬浮点架构。如果你的板子是 ARM 64 位那就换成 aarch64-linux-gnu-gcc。选错工具链是最难排查的问题之一因为编译过程有时能过但跑起来直接报 Illegal instruction。先确认工具链能正常工作arm-linux-gnueabihf-gcc --version输出正常后顺手确认一下它默认的 sysroot 路径这决定了后续要不要手动指定额外的头文件路径。工具链确认没问题之后开始配置交叉编译环境变量。我通常会在编译前把下面这几个变量 export 出来export CCarm-linux-gnueabihf-gcc export ARarm-linux-gnueabihf-ar export RANLIBarm-linux-gnueabihf-ranlib export CROSS_COMPILEarm-linux-gnueabihf-CC是 C 编译器AR是静态库打包工具RANLIB是索引工具CROSS_COMPILE是 librtmp 的 Makefile 里用来拼工具链前缀的变量。这几个变量在后续编译 OpenSSL、zlib 和 librtmp 时全部都要用到提前设好可以避免每个包里重复写。2.3 configure 脚本与 Makefile 的取舍逻辑OpenSSL 和 zlib 都有 configure 脚本但 librtmp 没有。librtmp 的源码包自带一个 Makefile编译时直接传参数即可。这意味着你不需要也不可能对 librtmp 执行./configure它的所有配置项全部集中在 Makefile 的变量里。我在第一次操作的时候习惯性地去找 configure没找到还以为源码包不完整后来才意识到 librtmp 的设计就是让你直接改 Makefile 变量。这一点其实挺反直觉的但它反而简化了交叉编译的流程。你不需要担心 configure 检测到主机架构然后擅自启用某些不支持的特性所有决定都在你自己的掌控里。3. 实战三步完成 librtmp 交叉编译全流程3.1 第一步交叉编译 OpenSSLOpenSSL 是 librtmp 最核心的依赖RTMP 握手、RTMPS 加密都靠它。交叉编译 OpenSSL 时最关键的参数是Configure而不是config因为后者检测的是当前主机环境编出来的一定是 x86 架构。cd openssl-1.0.2u ./Configure linux-armv4 --prefix$PWD/../_install --cross-compile-prefixarm-linux-gnueabihf- shared no-asm make -j4 make installlinux-armv4指定了目标架构--prefix指定安装路径no-asm很重要它关闭了汇编优化。交叉编译时汇编优化经常会因为工具链版本不匹配而出错关掉它虽然损失一点性能但能保证编译顺利通过。shared表示编译动态库如果你打算做静态链接这一步可以去掉。这版本选择上我踩过一个坑OpenSSL 1.1.0 以上的编译参数和 1.0.x 差别很大。如果你拿到的是 1.1.x 版本Configure的参数要改成linux-armv4 -marcharmv7-a多了一个-march选项。建议先用 1.0.2u 熟悉整个链路跑通后再升级到 1.1.x。编译完成后去_install目录确认一下产物架构file _install/lib/libcrypto.so.1.0.0看到ARM字样就说明架构对了如果显示x86-64说明 Configure 那一步没生效。3.2 第二步交叉编译 zlibzlib 的交叉编译比 OpenSSL 简单得多它有一个非常朴素的 configure 脚本直接指定编译器就行cd zlib-1.2.11 ./configure --prefix$PWD/../_install make CCarm-linux-gnueabihf-gcc ARarm-linux-gnueabihf-ar rc make installzlib 的 configure 脚本不会像 OpenSSL 那样自动交叉编译你需要手动指定CC和AR。AR后面那个rc参数是 ar 工具的创建归档模式必须加上否则静态库打不出来。zlib 本身的代码量不大编译速度很快。它的作用是为 librtmp 提供解压能力RTMP 流里某些扩展头部或者 AMF 数据会经过压缩处理没有 zlib 可能在解析某些特定流时直接崩溃。这个库不是可选依赖必须编进系统里。确认 zlib 编译成功file _install/lib/libz.a静态库没有架构信息但你可以检查它的大小通常在几百 KB 左右。如果特别小大概率是编译期间出了什么怪问题。3.3 第三步librtmp 的 Makefile 参数配置这是整个交叉编译中最关键的一步也是参数最多的一步。librtmp 的 Makefile 支持通过命令行直接覆盖变量不需要改文件本身cd librtmp make CROSS_COMPILEarm-linux-gnueabihf- \ INC-I$PWD/../_install/include \ XLDFLAGS-L$PWD/../_install/lib -ldl -lpthread \ prefix$PWD/../_install \ SHAREDnoINC指定了额外的头文件搜索路径这里同时包含了 OpenSSL 和 zlib 的头文件因为它们都安装在_install/include下了。XLDFLAGS是链接选项除了-L指定库目录外-ldl和-lpthread是必须的。-ldl链接的是动态加载库OpenSSL 在很多地方会调用dlopen加载引擎模块-lpthread则是线程支持。少了这两个链接阶段报错会让你怀疑人生。SHAREDno表示编译静态库。这个是我在实践里总结出来的经验嵌入式设备上动态库的排查成本太高目标板上缺一个.so就得重新打包固件静态链接虽然会让最终程序的体积大几十 KB但省去了运行时依赖的麻烦。做嵌入式开发的少一个动态依赖就少一个更新固件的理由。编译完成后产物会出现在 librtmp 目录下ls -la librtmp.a看到librtmp.a就说明静态库编译成功了。如果你还需要动态库把SHAREDno去掉再编一次两种产物可以共存。4. 把编译好的 librtmp 集成进你的业务代码4.1 头文件路径与链接参数怎么配现在你已经有了针对 ARM 架构的librtmp.a、libcrypto.a和libz.a接下来要做的就是把它们链进你自己的推流程序。这一步如果是在自己的 Makefile 里操作链接参数有一个固定的顺序要求乱排会直接导致undefined reference。我一般这样写链接参数arm-linux-gnueabihf-gcc main.c -o rtmp_push \ -I./_install/include \ -L./_install/lib \ -lrtmp -lcrypto -lz -ldl -lpthread-lrtmp必须放在-lcrypto和-lz前面。GNU 链接器在处理静态库时是单向扫描的它会从-lrtmp的库文件里找没解析的符号然后继续在后面的库里找定义。如果你把-lcrypto放在-lrtmp前面链接器先扫描了 libcrypto发现里面没有未解析的符号就不管了等扫描到 liblibrtmp 时发现有符号引用了 libcrypto 里的函数但此时 libcrypto 已经没有再被扫描的机会了结果就是一堆undefined reference to SSL_*。这个顺序规则是链接器的工作机制决定的不是玄学。整理成一条经验就是被依赖的库放在依赖者的右边从右往左解析。4.2 静态链接与动态链接的选择在交叉编译的场景里我强烈建议用静态链接。理由很实际动态链接需要目标板子上有对应版本的librtmp.so、libcrypto.so和libz.so这三个库的版本只要有一个对不上程序启动就会报cannot open shared object file。而静态链接把所有代码都打包进了最终的可执行文件里目标板上只需要有基本的 C 运行库就行。不过静态链接也有它的问题最明显的就是体积。librtmp.a本身不大但libcrypto.a是个大块头静态链接后你的可执行文件可能会比动态链接大 1MB 以上。这对存储空间有限的嵌入式设备是个压力好在现在大多数板子的 flash 都在 16MB 以上1MB 的代价换来的稳定性是值得的。如果你确实要动态链接记得把编译好的librtmp.so一并拷贝到目标板的/usr/lib目录下然后执行ldconfig刷新动态链接器缓存。这两个动作缺一个程序在运行时都会找不到库。4.3 pkg-config 文件的修正librtmp 源码包里自带一个librtmp.pc.in模板安装后会生成pkgconfig/librtmp.pc但交叉编译时这个文件是错的因为它的路径直接指向了编译机器的目录。如果你习惯用 pkg-config 管理编译选项需要手动改正这个文件的内容prefix/home/build/arm_install exec_prefix${prefix} libdir${prefix}/lib includedir${prefix}/include Name: librtmp Description: RTMP implementation Version: 2.4 Libs: -L${libdir} -lrtmp -lz -lcrypto Cflags: -I${includedir}重点是把prefix改成你实际的安装路径并且Libs字段要手动加上-lz -lcrypto原版文件默认不包含这两个依赖。修改完复制到工具链的 sysroot 目录里后续用pkg-config --cflags --libs librtmp就能正常获取路径。5. 避坑我踩过的五个交叉编译翻车现场5.1 现象编译时报openssl/rsa.h: No such file or directory原因INC参数没有正确指向 OpenSSL 头文件所在的目录编译器找不到 RSA 相关的定义。解决检查INC是否确实指向了_install/include并且确认这个目录下存在openssl/rsa.h文件。很多时候是因为编译 OpenSSL 时--prefix没有生效头文件根本没安装过来重新执行make install就行。5.2 现象链接阶段报undefined reference to SSL_library_init原因链接库的顺序不对。这种情况几乎可以断定是把-lcrypto放在了-lrtmp前面导致 libcrypto 没有被正确扫描。解决把-lcrypto调整到-lrtmp的右端或者直接复制我的链接参数模板不要自己重组顺序。5.3 现象编译完成后在目标板上运行报cannot open shared object file: No such file原因你用了动态链接但目标板上缺少librtmp.so或者它的依赖库没有被拷贝过去。解决用静态链接或者在编译时加-static强制全部静态化。另外一个溜的办法是把readelf -d查看可执行文件的动态依赖列表逐条核对是否都在目标板上存在。5.4 现象configure 脚本检测的架构不对编出来的库是 x86 的原因OpenSSL 用了./config而不是./Configure导致它自动检测到了主机架构。解决强制使用./Configure linux-armv4并且在执行后检查Makefile里的CC变量是否确实带上了交叉编译前缀。我遇到过Makefile里显示的CC被自动改了回来检查一遍能少走很多弯路。5.5 现象程序能跑但卡在RTMP_Connect超时原因这是最迷惑人的一种情况编译没问题、链接没问题、架构也对但就是连不上服务器。我排查了很久才发现问题出在交叉编译 OpenSSL 时no-asm这个选项加得太随意SSL 握手过程中的某些计算路径在特定版本的 OpenSSL 里出现了分支错误。解决先用取消 SSL 的方式测试 RTMP 连接如果正常说明是 TLS 握手环节的问题。然后强制重新编译 OpenSSL 时加no-asm并且确认配置生效或者换一个 OpenSSL 版本再试。经验是librtmp 交叉编译失败了可以用strace看系统调用用tcpdump抓包看 RTMP 握手别在那里瞎猜。6. 验证与进阶从 file 命令到体积优化的一整套习惯6.1 用 file 和 readelf 验证产物架构拿到交叉编译产物后不验证就直接拷到目标板上等于在拒绝排错。我每次编译完都会跑三连命令file librtmp.a file rtmp_push readelf -d rtmp_push | grep NEEDEDfile确认可执行文件是 ARM 架构readelf -d查看动态依赖列表。如果readelf的输出里有libc.so.6以外的条目就说明这个可执行文件并不完全静态需要把这些库一并拷到目标板。6.2 体积优化裁剪 OpenSSL 的编译选项编译 OpenSSL 时no-asm选项除了规避汇编版本的坑还有一个好处是减小体积。ARM 汇编优化会加入很多特定架构的实现代码这些代码在你只跑 RTMP 握手时完全是多余的。配合no-shared和no-ssl2、no-ssl3这些选项编译出来的libcrypto.a能比默认配置小 30% 左右。6.3 从血泪经验里沉淀出的编译习惯从那以后我每次做 librtmp 交叉编译都强制走一遍同一套流程检查工具链版本、确定_install目录是干净的、按 OpenSSL、zlib、librtmp 的顺序依次编译、每个环节完成后立刻用file验证架构、最后固定用静态链接集成到业务代码。这套流程虽然看起来繁琐但每次都能在五分钟内跑完而且基本不会翻车。特别是静态链接的那一步让我再也没有为动态库缺失的问题重新烧过板子。希望这篇文章能帮你在 librtmp 交叉编译的路上少走几个来回一次就把推流跑通。本文还有配套的精品资源点击获取