树莓派4B搭建Nginx-RTMP推流服务器:直播分发与录制回放实战

发布时间:2026/10/14 18:45:12
树莓派4B搭建Nginx-RTMP推流服务器:直播分发与录制回放实战 1. 为什么要在树莓派上折腾RTMP这套东西手里有块树莓派4B大多数人第一反应是拿它做下载机、做家庭网关、或者跑个轻量级服务。但如果你手头恰好有摄像头、有麦克风又想让多个设备同时看到画面那推流这件事就绕不开了。我最初的需求很朴素家里有台老摄像机想让它采集的画面能同时被客厅电视、卧室平板和手机看到而且最好能顺手把声音录下来存档。商业方案要么按月收费要么画质被压得惨不忍睹于是我把目光投向了树莓派加Nginx-RTMP这套组合。RTMP的全称是Real-Time Messaging Protocol直译过来就是实时消息传输协议。它最早是给Flash播放器传音视频用的虽然Flash本身已经退出历史舞台但RTMP作为推流协议却活得好好的原因很简单延迟低、兼容性好、服务端实现成熟。Nginx本身是个高性能的Web服务器加上RTMP模块之后它就变成了一个能接收推流、分发直播、同时把流写成文件的服务端。树莓派4B的硬件配置——四核Cortex-A72、最高8GB内存、千兆网口——跑这套东西绰绰有余功耗还低7x24小时开着也不心疼电费。这套方案能解决什么问题第一把采集端和播放端解耦。摄像头只管往树莓派推流至于谁在看、用什么看树莓派不关心。第二一份流可以同时做两件事一边分发给多个观众一边录成文件存到硬盘上。第三成本极低树莓派加一张SD卡加一个摄像头总投入可能还不到某些商业方案一个月的订阅费。适合谁来参考如果你懂一点Linux基础命令能照着教程敲命令那就能跟着做下来。完全没接触过命令行的朋友建议先补一下cd、ls、nano这几个命令的用法不然中途容易卡住。我实际搭这套环境的时候前前后后折腾了大概三个晚上踩的坑主要集中在编译参数、权限配置和录制文件的格式选择上。下面我把整个流程拆开从系统准备到最终跑通每一步都说明白为什么这么做以及我踩过哪些坑。2. 树莓派4B上的系统准备与依赖梳理2.1 系统版本的选择与基础配置树莓派4B支持32位和64位系统我强烈建议用64位的Raspberry Pi OS。原因很直接64位系统能充分利用4B的ARM Cortex-A72架构内存寻址不受4GB限制编译Nginx的时候速度也快不少。我最初用的是32位系统编译Nginx-RTMP模块花了将近四十分钟换成64位之后缩短到二十分钟左右。系统烧录用官方的Raspberry Pi Imager就行烧录时记得在高级选项里提前配置好WiFi和SSH省得接显示器键盘。系统起来之后第一件事是更新软件源并升级已有包。这一步不能省因为Nginx-RTMP的编译依赖一些开发库老版本的库文件可能导致编译失败。命令是sudo apt update sudo apt full-upgrade -y执行完重启一次。重启后检查一下内核版本和架构用uname -a看一眼确认是aarch64就对了。接下来要调整几个系统参数。树莓派默认的交换空间只有100MB编译过程中容易内存不足导致进程被杀死。我把它调到2GB编辑/etc/dphys-swapfile把CONF_SWAPSIZE改成2048然后执行sudo dphys-swapfile setup sudo dphys-swapfile swapon。另外如果你打算长时间录制建议把文件系统扩展到整张SD卡用raspi-config里的Expand Filesystem选项操作即可。2.2 编译Nginx-RTMP所需的依赖清单Nginx-RTMP模块不是独立运行的它需要作为Nginx的一个模块编译进去。这意味着我们不能直接用apt install nginx装现成的Nginx必须自己下载源码编译。编译之前需要安装一堆开发库我列一下完整的依赖清单build-essential提供gcc、make等编译工具libpcre3-devNginx处理正则表达式需要libssl-dev支持HTTPS和加密推流zlib1g-dev支持gzip压缩libxml2-dev和libxslt1-dev如果你需要XSLT模块git用来拉取RTMP模块源码这些库用一条命令就能装完sudo apt install build-essential libpcre3-dev libssl-dev zlib1g-dev libxml2-dev libxslt1-dev git -y。装完之后建议用dpkg -l | grep检查一下关键库的版本确保没有遗漏。注意如果你之前用apt装过Nginx建议先卸载干净否则编译安装后可能出现版本冲突。卸载命令是sudo apt purge nginx nginx-common nginx-full -y sudo apt autoremove -y。2.3 源码下载与目录规划我习惯把源码放在/usr/local/src下面方便管理。先创建目录并进入sudo mkdir -p /usr/local/src cd /usr/local/src。然后下载Nginx源码我选的是1.24.0稳定版这个版本和RTMP模块的兼容性经过验证比较稳。下载命令是sudo wget https://nginx.org/download/nginx-1.24.0.tar.gz解压用sudo tar -zxvf nginx-1.24.0.tar.gz。RTMP模块从代码托管平台拉取命令是sudo git clone https://github.com/arut/nginx-rtmp-module.git。这个模块的维护者一直在更新但主干分支偶尔会有小问题我建议切到一个稳定的标签版本。进入模块目录后用git tag看一下有哪些版本我选的是v1.2.2执行git checkout v1.2.2切换过去。目录结构规划好之后后面编译的时候指定路径就清晰了。我一般把Nginx安装到/usr/local/nginx日志放在/var/log/nginx录制文件放在/mnt/record。这些路径在编译配置和后续的配置文件中都要保持一致不然会出现找不到文件或者权限拒绝的问题。3. 编译安装Nginx与RTMP模块的完整过程3.1 configure参数的选择逻辑进入Nginx源码目录后执行./configure来生成编译配置。这一步的参数决定了哪些模块会被编译进去以及安装路径在哪里。我用的参数如下sudo ./configure \ --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_flv_module \ --with-http_mp4_module \ --add-module../nginx-rtmp-module \ --with-cc-opt-O3 \ --with-ld-opt-Wl,-rpath,/usr/local/lib逐个解释一下为什么这么选。--prefix指定安装目录方便后面统一管理。--with-http_ssl_module开启HTTPS支持虽然RTMP本身不加密但如果你后面想用HTTP-FLV或者HLS播放HTTPS就派上用场了。--with-http_flv_module和--with-http_mp4_module是为了支持FLV和MP4文件的伪流播放录制完的文件可以直接通过HTTP拖进度条播放。--add-module指向RTMP模块的源码路径注意路径是相对于当前目录的我这里是../nginx-rtmp-module。--with-cc-opt-O3是让编译器用最高级别的优化树莓派的CPU性能有限优化一下能提升推流时的处理效率。--with-ld-opt指定运行时库的搜索路径避免编译出来的二进制找不到动态库。configure执行完之后它会输出一个摘要告诉你哪些模块会被编译。仔细检查一下RTMP模块是否在列表里如果没有说明路径写错了需要重新执行。3.2 编译与安装中的性能调优编译用make -j4利用树莓派4B的四核并行编译。这个过程大概需要十五到二十分钟取决于SD卡的速度和交换空间的使用情况。如果中途出现virtual memory exhausted之类的错误说明内存不够要么加大交换空间要么用make -j2降低并行度。编译完成后执行sudo make installNginx会被安装到/usr/local/nginx。安装完之后用/usr/local/nginx/sbin/nginx -V查看编译参数确认RTMP模块已经包含在内。如果输出里有--add-module../nginx-rtmp-module就说明成功了。接下来配置系统服务让Nginx能开机自启。创建/etc/systemd/system/nginx.service文件内容如下[Unit] Descriptionnginx with rtmp Afternetwork.target [Service] Typeforking ExecStart/usr/local/nginx/sbin/nginx ExecReload/usr/local/nginx/sbin/nginx -s reload ExecStop/usr/local/nginx/sbin/nginx -s quit PrivateTmptrue [Install] WantedBymulti-user.target保存后执行sudo systemctl daemon-reload sudo systemctl enable nginx。这样每次树莓派启动Nginx就会自动运行。3.3 验证RTMP模块是否生效在正式配置推流之前先验证一下RTMP模块是否真的加载了。执行/usr/local/nginx/sbin/nginx -V 21 | grep rtmp如果输出里有nginx-rtmp-module就说明模块已经编译进去了。然后启动Nginxsudo systemctl start nginx用sudo systemctl status nginx查看状态确认是active (running)。这时候用浏览器访问树莓派的IP地址应该能看到Nginx的默认欢迎页面。如果看不到检查一下防火墙设置树莓派默认没有开启ufw但如果你之前装过需要放行80端口sudo ufw allow 80/tcp。提示RTMP默认使用1935端口推流之前记得在防火墙里放行这个端口。如果只在局域网内使用可以跳过防火墙配置但如果你打算从外网推流端口映射和安全策略需要另外考虑。4. RTMP服务端配置从推流接收到录制落盘4.1 nginx.conf中RTMP块的完整写法Nginx的主配置文件在/usr/local/nginx/conf/nginx.conf。RTMP的配置需要写在http块之外和http块平级。我先把完整的RTMP配置块贴出来然后逐段解释rtmp { server { listen 1935; chunk_size 4096; max_message 1M; application live { live on; record off; allow play all; allow publish all; } application record { live on; record all; record_path /mnt/record; record_suffix -%Y%m%d-%H%M%S.flv; record_unique on; allow play all; allow publish all; } } }listen 1935是RTMP的标准端口chunk_size 4096表示数据块大小为4KB这个值在局域网内比较合适太大增加延迟太小增加开销。max_message 1M限制单条消息最大1MB防止异常数据撑爆内存。application live定义了一个名为live的应用live on表示开启直播模式record off表示不录制。allow play all和allow publish all分别允许任何人播放和推流局域网内用没问题但如果暴露在公网建议改成指定IP段。application record是专门用来录制的应用record all表示录制所有流record_path指定录制文件的存放目录record_suffix定义文件名后缀格式这里用了时间戳record_unique on确保每次推流生成独立的文件不会覆盖。4.2 录制路径的权限与存储规划录制目录/mnt/record需要提前创建并赋予Nginx进程写入权限。Nginx默认以nobody用户运行所以执行sudo mkdir -p /mnt/record sudo chown nobody:nogroup /mnt/record sudo chmod 755 /mnt/record。如果你把录制目录放在外接硬盘上记得先挂载硬盘并设置开机自动挂载否则重启后录制会失败。存储规划方面FLV格式的录制文件大小大约每小时1GB到2GB取决于码率。树莓派4B的USB接口是USB 3.0接一块移动硬盘能轻松应对长时间录制。我建议至少准备64GB的存储空间并且定期清理旧文件。可以写一个简单的定时任务每天凌晨删除七天前的录制文件0 3 * * * find /mnt/record -name *.flv -mtime 7 -delete把这个加到crontab -e里就行。注意-mtime 7表示修改时间超过7天-delete直接删除不经过回收站。4.3 推流地址的构成与鉴权思路推流地址的格式是rtmp://树莓派IP:1935/应用名/流名。比如rtmp://192.168.1.100:1935/live/camera1其中live是应用名camera1是流名可以随便取但推流端和播放端必须一致。如果你不想让任何人都能推流可以在application块里加推流鉴权。Nginx-RTMP模块支持on_publish回调当有推流请求时Nginx会向一个HTTP接口发送请求接口返回2xx状态码才允许推流。配置写法是on_publish http://127.0.0.1:8080/auth;然后在树莓派上跑一个简单的HTTP服务来验证密钥。这个方案适合对安全有要求的场景但会增加一点延迟。局域网内使用的话allow publish all就够了。播放地址和推流地址一样用VLC或者ffplay就能直接播放。VLC的操作是打开网络串流输入rtmp://192.168.1.100:1935/live/camera1点播放就能看到画面。ffplay的命令是ffplay rtmp://192.168.1.100:1935/live/camera1延迟大概在1到3秒之间。5. 推流端的配置与实测效果5.1 用ffmpeg从摄像头采集并推流树莓派上接USB摄像头的话用ffmpeg推流是最直接的方式。先确认摄像头被识别ls /dev/video*通常会出现/dev/video0。然后用v4l2-ctl查看支持的格式v4l2-ctl --device/dev/video0 --list-formats-ext记下支持的分辨率和帧率。推流命令如下ffmpeg -f v4l2 -input_format h264 -video_size 1280x720 -framerate 30 -i /dev/video0 \ -f alsa -i hw:1,0 \ -c:v copy -c:a aac -b:a 128k \ -f flv rtmp://192.168.1.100:1935/live/camera1-input_format h264表示摄像头直接输出H264编码这样-c:v copy就能直接复制视频流不用重新编码极大降低CPU占用。音频用ALSA采集hw:1,0是声卡设备号用arecord -l可以查看。如果摄像头不支持H264输出那就只能软编码把-c:v copy换成-c:v libx264 -preset ultrafast -tune zerolatency但树莓派4B软编码720p30fps大概会占用60%以上的CPU。5.2 用OBS从另一台电脑推流如果你手头有电脑用OBS推流更方便可以灵活切换场景、加字幕、混音。OBS的设置里服务选“自定义”服务器填rtmp://192.168.1.100:1935/live串流密钥填camera1。输出模式选高级编码器选硬件编码比如NVENC或者QuickSync码率设2000到4000 Kbps关键帧间隔设2秒。OBS推流的好处是可以在推流端做画面合成比如画中画、文字叠加、多摄像头切换。但缺点是电脑必须一直开着功耗比树莓派高得多。我的做法是平时用树莓派直接推流需要做复杂制作的时候才开电脑用OBS。5.3 实测延迟、CPU占用与画质表现我在局域网内实测的结果ffmpeg直接复制H264流720p30fps码率2Mbps树莓派4B的CPU占用在15%到20%之间内存占用不到200MB。播放端用VLC延迟大约1.5秒用ffplay延迟大约1秒。录制文件用record应用生成每个文件大约每分钟30MB画质和推流端一致没有二次压缩。如果开启软编码CPU占用会飙升到70%以上而且画面偶尔会卡顿。所以强烈建议用支持H264硬编码的摄像头或者用树莓派的硬件编码器。树莓派4B的VideoCore VI支持H264硬件编码但需要通过raspivid或者libcamera来调用ffmpeg直接调用硬件编码器需要额外配置稍微麻烦一些。注意录制FLV文件的时候如果推流中断最后一个文件可能没有正确写入索引导致无法播放。解决办法是用ffmpeg -i input.flv -c copy output.mp4重新封装一下或者直接用MP4格式录制。Nginx-RTMP模块支持record_suffix .mp4但MP4录制在中断时更容易损坏FLV反而更健壮。我的做法是录FLV需要的时候再转MP4。6. 录制文件的后续处理与回放方案6.1 FLV转MP4的批量处理脚本FLV文件虽然健壮但兼容性不如MP4很多播放器不支持直接拖进度条。我写了一个简单的脚本每天凌晨把前一天的FLV文件转成MP4#!/bin/bash RECORD_DIR/mnt/record for file in $RECORD_DIR/*.flv; do if [ -f $file ]; then output${file%.flv}.mp4 ffmpeg -i $file -c copy -movflags faststart $output -y if [ $? -eq 0 ]; then rm $file fi fi done-c copy表示不重新编码直接复制流速度极快。-movflags faststart把MP4的索引移到文件开头方便网络播放。转换成功后删除原FLV文件节省空间。把这个脚本保存为/usr/local/bin/convert_flv.sh加执行权限然后加到crontab里每天凌晨4点执行。6.2 通过HTTP回放录制内容Nginx本身就能提供HTTP文件服务把录制目录映射到HTTP路径下就能用浏览器直接播放MP4文件。在http块里加一个locationlocation /record/ { alias /mnt/record/; autoindex on; autoindex_exact_size off; autoindex_localtime on; }重启Nginx后访问http://192.168.1.100/record/就能看到文件列表点MP4文件就能在线播放。autoindex on开启目录列表autoindex_localtime on让文件时间显示为本地时间方便查找。如果你想让播放更流畅可以加mp4模块的伪流支持。在http块里确保有mp4;指令然后访问MP4文件时加?start0参数就能拖进度条。不过现代浏览器对MP4的HTTP Range请求支持很好不加参数也能拖。6.3 存储空间监控与自动清理策略长时间录制最怕硬盘写满导致Nginx崩溃。我加了一个监控脚本当磁盘使用率超过85%时自动删除最旧的录制文件#!/bin/bash THRESHOLD85 RECORD_DIR/mnt/record USAGE$(df $RECORD_DIR | tail -1 | awk {print $5} | sed s/%//) if [ $USAGE -gt $THRESHOLD ]; then find $RECORD_DIR -name *.mp4 -type f -printf %T %p\n | sort | head -n 10 | awk {print $2} | xargs rm -f fi这个脚本每小时跑一次每次删除最旧的10个MP4文件。-printf %T %p\n输出文件的修改时间和路径sort按时间排序head -n 10取最旧的10个xargs rm -f批量删除。加到crontab里0 * * * * /usr/local/bin/cleanup_record.sh。7. 踩过的坑与排查思路复盘7.1 编译时报错“SSL modules require the OpenSSL library”这个错误出现的原因是libssl-dev没有安装或者安装的版本和Nginx要求的版本不匹配。解决办法是先确认libssl-dev已经安装dpkg -l | grep libssl-dev。如果没有执行sudo apt install libssl-dev -y。如果已经安装但还是报错可能是pkg-config找不到OpenSSL的路径执行export PKG_CONFIG_PATH/usr/lib/aarch64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH然后重新configure。我遇到过一次比较诡异的情况系统里同时存在OpenSSL 1.1和3.0两个版本Nginx默认找了1.1但RTMP模块需要3.0的符号。解决办法是在configure时显式指定OpenSSL路径--with-openssl/usr/include/openssl。不过这种情况比较少见大多数时候装好libssl-dev就能解决。7.2 推流成功但播放端黑屏推流端显示推流成功但播放端一直黑屏这种问题最让人头疼。排查思路是从推流端到服务端再到播放端逐段确认。首先在树莓派上用ffplay rtmp://127.0.0.1:1935/live/camera1本地播放如果本地能播说明服务端没问题问题出在网络或者播放端。如果本地也黑屏说明推流数据有问题。常见原因有几个推流端的编码格式和RTMP不兼容比如用了H265编码RTMP默认只支持H264。解决办法是在ffmpeg里强制指定-c:v libx264。另一个原因是时间戳问题ffmpeg推流时如果时间戳不连续播放端会卡住。加-fflags genpts让ffmpeg重新生成时间戳。还有一个原因是防火墙拦截了1935端口用sudo netstat -tlnp | grep 1935确认Nginx在监听。7.3 录制文件无法播放或时长异常录制出来的FLV文件用播放器打开显示时长是0或者直接报错无法播放。这种情况通常是推流中断导致的FLV的元数据没有正确写入。解决办法是用ffmpeg修复ffmpeg -i broken.flv -c copy fixed.flv。如果修复不了试试ffmpeg -i broken.flv -c copy -flvflags no_duration_filesize fixed.flv这个参数强制ffmpeg忽略文件里的时长信息重新生成。预防措施是在Nginx配置里加record_interval 30m每30分钟自动切分文件这样即使某个文件损坏也只丢失30分钟的内容。另外record_unique on确保每次推流生成新文件不会追加到旧文件上导致结构混乱。7.4 树莓派发热降频导致推流卡顿树莓派4B在高负载下发热明显如果没有散热片或者风扇CPU温度超过80度就会降频推流画面开始卡顿。用vcgencmd measure_temp查看温度如果经常超过75度建议加一个散热风扇。我用的是一块铝制散热片加一个5V小风扇温度稳定在55度左右。软件层面也可以优化把Nginx的worker进程数设为2而不是4减少CPU竞争关闭不必要的Nginx模块减小内存占用推流端用硬件编码而不是软编码。这些措施综合下来树莓派4B可以稳定推流720p30fps连续运行一周不重启。8. 几个提升稳定性的小配置8.1 开启Nginx的访问日志与错误日志默认情况下Nginx的RTMP模块不记录推流和播放的详细日志。在rtmp块里加access_log和error_log可以方便排查问题rtmp { access_log /var/log/nginx/rtmp_access.log; error_log /var/log/nginx/rtmp_error.log info; server { ... } }access_log记录每次推流和播放的IP、时间、流名error_log记录错误信息。日志文件会逐渐增大建议加logrotate规则每天切割一次保留7天。8.2 限制同时推流的客户端数量如果不加限制多个客户端同时往同一个流名推流会导致画面混乱。在application块里加max_connections可以限制并发连接数application live { live on; max_connections 10; ... }max_connections 10表示最多10个客户端同时连接超过的会被拒绝。这个值根据你的实际需求调整局域网内一般5到10就够了。8.3 用systemd管理Nginx的自动重启Nginx偶尔会因为内存不足或者其他原因崩溃用systemd的Restart选项可以让它自动重启[Service] Restarton-failure RestartSec5sRestarton-failure表示非正常退出时自动重启RestartSec5s表示重启前等待5秒。这样即使Nginx崩溃5秒后就能恢复服务不用手动干预。我在实际使用中发现树莓派4B跑这套方案最关键的其实是散热和存储。散热不好CPU降频推流必卡存储满了Nginx写不进去直接崩溃。把这两个问题解决好剩下的就是配置细节了。另外如果你打算长期录制建议用外接硬盘而不是SD卡SD卡的写入寿命有限频繁录制容易坏卡。我第一张SD卡就是这么报废的换了移动硬盘之后稳定运行了半年多。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询