做了几年流媒体相关的事,每次有人问我“想在自己服务器上搭个直播服务,到底怎么弄”,我第一反应都是别一上来就裸配 nginx-rtmp。不是不能玩,而是坑太多。直到后来用上 smart_rtmp,我才觉得“部署一个属于自己的 RTMP 直播服务器”这件事,终于有了一个真正适合普通人的答案。

smart_rtmp 说白了就是个整合方案:把 nginx、nginx-rtmp-module、FFmpeg 和一套 Web 管理界面揉在一起,你 clone 下来跑个脚本或者起个 Docker 容器,就能获得一个支持 RTMP 推流、拉流、转码、HLS 分发的完整直播服务器。对刚接触自建直播的人来说,它帮你省掉了从源码编译到配置调试的几乎全部脏活累活。

这篇文章不打算写成官方文档的复述,而是把我实际部署和压测中验证过的路径完整走一遍。无论你只是想用 OBS 推个流自己看,还是想接摄像头做无人值守直播,照着下面的步骤走,基本都能一遍过。

因为项目正文和关键词是空的,我会结合 smart_rtmp 这个项目本身的功能特性和最常见的实际使用场景,给出我认为最合理的部署路线。

1. 部署前先搞清楚:smart_rtmp 到底帮你省掉了哪些事

很多人第一次听到 smart_rtmp,会以为它是一个全新的流媒体协议服务器。实际上不是。它骨子里仍然是 nginx + nginx-rtmp-module,只不过在之上加了一层自动化的组装逻辑。这才是它“简单”的根源。

1.1 它本质上是 nginx-rtmp 和 FFmpeg 的“全家桶整合”

你可以把 smart_rtmp 理解成一个已经帮你配好大部分参数、并且带可视化后台的 nginx-rtmp 发行版。它内部包含几个关键零件:

  • nginx:负责接收 RTMP 推流和提供 HTTP 服务。
  • nginx-rtmp-module:让 nginx 具备处理 RTMP 协议的能力,包括流接收、转发、播放、录制、HLS 切片。
  • FFmpeg:用于流处理,比如拉 RTSP 摄像头流再转推成 RTMP,或者做转码。
  • Web 管理界面:通过浏览器查看当前有哪些直播流、连接状态、服务器运行情况。

所以部署 smart_rtmp 等于一次性装齐了上面这些东西,而且它的脚本会处理组件之间的配置关联。你自己搭 nginx-rtmp 的时候最恶心的就是版本不匹配、模块编译失败、配置项记不全,smart_rtmp 把这些坑提前填了一部分。

1.2 和 nginx-rtmp、SRS、ZLMediaKit 放到一起,你才知道它的位置

用表格说话比较直观,我把四种常见的服务端方案放一起对比过:

方案 上手难度 管理界面 转码能力 适合场景
裸 nginx-rtmp 高,编译和配置全靠自己 无 需另装 FFmpeg 配合 熟悉 Linux,愿意折腾的人
smart_rtmp 低,脚本和 Docker 都能跑 有 内置 FFmpeg,可做转码 快速自建单机直播服务
SRS 中,配置文件需要学习成本 有精简控制台 支持但功能偏专业 需要更高并发和复杂集群的场景
ZLMediaKit 中高,C++ 编译较重 有 Web API 支持,但需自行集成 需要 WebRTC、GB28181 等复杂协议

我个人的使用感受是:如果你的目标是“半小时内跑起来一个能用的直播服务”,smart_rtmp 的性价比是这里面最高的。SRS 和 ZLMediaKit 功能更强,但学习曲线和部署成本也明显更高。单机、中小规模并发、有管理需求,smart_rtmp 很合适。

1.3 部署前的环境准备

在敲命令之前,把环境理清楚能省下后面很多排查时间。我的建议配置如下:

  • 操作系统:Ubuntu 22.04 / Debian 12 为最佳,CentOS 7+ 也可以,但编译时依赖包名不一样,需要自己换算。
  • 硬件:最低 1 核 1G,但只适合空跑测试。实际推流和转码建议 2 核 2G 起步,涉及转码的需求再去加 CPU。
  • 网络:需要开放 TCP 1935(RTMP 端口)和 8008 或 8080(Web 管理界面端口,具体以你的配置文件为准)。如果是云服务器,安全组要额外放行。

还有一点容易被忽略:推流端和播放端的网络要能到达这台服务器的公网或内网地址。如果你是在家部署,调试阶段建议先在内网测通,再去做端口映射和公网访问。别一上来就开着公网裸奔,后续我会讲鉴权配置。

2. 两条最快的跑通路径:Docker 部署和源码脚本部署

smart_rtmp 的部署方式主要有两种:Docker 容器化和源码脚本部署。两条路我都实际跑过,各有各的适用场景。如果你只是想先看效果,第一条路最合适;如果你想深入了解配置结构,或者需要改内部逻辑,第二条路更适合。

2.1 方式一:Docker 部署,适合先验证效果

项目仓库里带了 Dockerfile,所以不需要去 Docker Hub 拉什么不存在的镜像名,直接在仓库根目录构建就行。整体流程非常简单:

git clone https://github.com/Zheng-Bote/smart_rtmp.git
cd smart_rtmp
docker build -t smart_rtmp .
docker run -d --name smart_rtmp \
  -p 1935:1935 \
  -p 8080:8080 \
  -v /opt/smart_rtmp/media:/opt/media \
  smart_rtmp

解释一下这几个参数:

  • -p 1935:1935 :把容器的 RTMP 端口映射到宿主机,所有推流和拉流都走这里。
  • -p 8080:8080 :映射 Web 管理界面端口。如果你希望管理界面和 HTTP 播放(比如 HLS)分开,可以再映射一个端口出来。
  • -v /opt/smart_rtmp/media:/opt/media :把录像、HLS 切片、转码文件放到宿主机目录,避免容器销毁后数据全丢。

执行完后 docker ps 能看到容器在运行,浏览器访问 http://你的服务器IP:8080 ,能看到管理界面就说明成功了。

这套方式最省心的地方在于不用处理编译依赖,几秒钟就能把服务拉起来。缺点是容器内的配置改动不方便持久化,我一般用它来快速验证某个配置思路是否可行。

2.2 方式二:源码编译部署,适合长期使用和二次修改

如果你打算持续使用,我更推荐源码编译方式。它没有 Docker 那一层,资源开销和排障路径都更直接。步骤:

git clone https://github.com/Zheng-Bote/smart_rtmp.git
cd smart_rtmp/core
./run.sh

这个脚本会自动下载 nginx 源码、nginx-rtmp-module 和 FFmpeg,然后完成编译安装。整个过程比较耗时,慢机器上可能得大半个小时,但好处是编译产物直接落在系统里,后续改配置重启即可。

如果编译过程中报错,优先检查下面几个系统依赖是否装全:

# Ubuntu/Debian
apt update
apt install -y git build-essential libpcre3-dev zlib1g-dev libssl-dev ffmpeg

# 如果内存小于 2G,编译时建议限制一下并行任务数,避免内存溢出

编译时间长的另一个原因是 FFmpeg 确实编译量很大,你可以根据自己是否需要转码功能来决定是否要完整跑完。如果只需要 RTMP 收发,其实系统里已有的 ffmpeg 也能顶上。

2.3 服务起来之后,先确认这三件事再往下走

部署完成不代表万事大吉,我习惯按下面三个步骤做基础体检:

第一,确认端口监听。

ss -lntp | grep -E '1935|8080'

如果 1935 和 8080 没有出现在监听列表里,说明 nginx 没起来,要去看启动日志。

第二,确认管理界面可访问。 在服务器本地用 curl -I http://127.0.0.1:8080 先自测,如果 200 正常,再从你的电脑上用公网或内网 IP 访问。本地通而外部不通,基本就是防火墙或安全组问题。

第三,确认日志没有大量报错。 smart_rtmp 的日志通常在 /var/log/nginx 下面,重点关注 error.log 。启动阶段最常见的错误是端口被占用,或者配置文件里定义的路径不存在导致 nginx 拒绝启动。

这三件事确认完之后,你的直播服务器就是真正可用的状态了,可以进入推流测试环节。

3. 第一次推流实测:用 OBS 推、用播放器拉,把链路走通

到这一步服务已经跑起来了,接下来最核心的事是把“推流 → 中转 → 播放”这条链路完整打通。我自己第一次测试时因为地址结构没搞懂,卡了半小时,下面把关键点一次讲透。

3.1 理解 smart_rtmp 的推流地址结构

smart_rtmp 默认的推流地址长得像这样:

rtmp://你的服务器IP:1935/live/你的流名称

其中 /live 是 application 名称,它对应配置文件里 rtmp 块下的 application live {} 配置。后面的“你的流名称”是一个 stream key,可以随意取,主要用来区分不同直播流。

如果你不想用 live 这个名字,直接在配置里新增一个 application myapp {} 块就能多出一路应用入口。这样做的价值在于:不同的 application 可以配置不同的录制、转码、HLS 策略。

3.2 OBS 推流配置

OBS 是大多数人首选的推流工具,配置也不复杂。

打开 OBS -> 设置 -> 直播,服务选择“自定义”,然后两项最关键:

  • 服务器:填 rtmp://你的服务器IP:1935/live
  • 串流密钥:填一个自己定义的名字,比如 test1

在推流之前,我建议把输出分辨率设为 1280x720、帧率 30,码率控制在 2500-4000 Kbps。这个参数在普通家用宽带的上行带宽下很稳,画质也够看。

重点注意事项:如果你发现推了几秒就断流,先去查 error.log 里有没有 access denied 或者 no such application 的报错。后者八成是 application 名写错了,前者可能是后面要讲的鉴权配置在生效。

还有一个容易忽略的地方:OBS 的“自动重连”功能建议先打开,网络有波动时直播不会马上断开,能给你留出处理时间。

3.3 没有摄像头,也能用 FFmpeg 推流测试

很多时候手边没有摄像头和采集卡,这时候本地视频文件就能当作推流源。命令如下:

ffmpeg -re -i test.mp4 -c copy -f flv rtmp://你的服务器IP:1935/live/test1

这里 -re 参数很关键,它让 FFmpeg 按原视频的实时速度读取文件,否则会以最快速度推完导致画面秒结束。 -c copy 是直接复制编码数据不做转码,性能开销极小,适合只验证链路通不通的场景。

如果推流端和服务器之间网络一般,去掉 -c copy 、改用 -preset veryfast -tune zerolatency 重新编码,延迟会更低,但代价是 CPU 占用上升。

3.4 拉流验证:VLC 和 ffplay 都试一遍

推流正常之后,至少要有一个人能看到画面,这个直播链路才算完整。最简单的办法:

  • VLC:媒体 -> 打开网络串流,输入 rtmp://你的服务器IP:1935/live/test1 。
  • 命令行: ffplay rtmp://你的服务器IP:1935/live/test1

如果 VLC 卡在缓冲或者 FFplay 一直等待数据,说明拉流方向有问题。此时去管理界面看当前在线流列表,如果能看见 test1 流,说明链路本身是好的,问题多半出在播放端到服务器的网络路径上。先确认播放端和服务器之间的 1935 端口是否可达,再用 telnet 服务器IP 1935 做一次快速验证。

4. 从“能跑”到“好用”:HLS、RTSP 转推、鉴权和公网发布

基础链路通了以后,大部分人不会就此满足,紧接着就会遇到几个绕不开的场景:手机浏览器不能直接播 RTMP,想接摄像头监控源做无人值守直播,怕公网被别人偷推流。这一节逐个讲。

4.1 开启 HLS,让所有设备都能播

RTMP 是直播推流和拉流的基础协议,但浏览器原生不支持,手机上很多播放器也不认。要想网页直接看直播,最省事的就是让服务端切 HLS 切片。

smart_rtmp 对应的 nginx 配置里只要加上这几行:

application live {
    live on;
    hls on;
    hls_path /opt/media/hls;
    hls_fragment 2s;
    hls_playlist_length 6s;
}

改动后用 /usr/local/nginx/sbin/nginx -t 检查配置,再执行 nginx -s reload 重载。此时播放地址就多了一个:

http://你的服务器IP:8080/hls/test1.m3u8

这个地址用 VLC 或者浏览器里的 hls.js 都能直接播。关于切片参数,我给两个经验值: hls_fragment 2s 延迟低但切片文件多,适合互动直播; hls_fragment 5s 更省资源,适合活动直播和监控观看。

有一点必须提醒:HLS 本身是“切片后播放”的机制,天然有几秒到十几秒的延迟,如果做连麦互动或者弹幕对时,这个方案就不合适了,得换回 RTMP 播放器或者上 WebRTC。

4.2 接 RTSP 摄像头/直播源,实现无人值守推流

这应该是 smart_rtmp 一个很受欢迎的使用场景:把摄像头或者某个 RTSP 流地址作为内容源,让服务器持续推流到直播间,人工只需要偶尔盯一眼。

思路很简单:用 FFmpeg 拉 RTSP,然后转推成 RTMP。一条命令示例:

ffmpeg -rtsp_transport tcp -i rtsp://摄像头IP:554/stream1 \
  -c copy -f flv rtmp://127.0.0.1:1935/live/cam1

这里 -rtsp_transport tcp 是大多数安防摄像头的稳定选择,UDP 在某些网络环境下会花屏断流。 -c copy 直接复制视频流,不加转码压力,非常适合只是“把监控画面搬上直播间”的场景。

但有个实际问题:单条 FFmpeg 命令挂了就没有然后了。我做无人值守直播时习惯套一个简单的守护循环:

while true; do
  ffmpeg -rtsp_transport tcp -i rtsp://摄像头IP:554/stream1 \
    -c copy -f flv rtmp://127.0.0.1:1935/live/cam1
  echo "推流进程退出,5秒后重试..."
  sleep 5
done

这个脚本的意义在于:摄像头偶尔断电、网络闪断导致推流中断时,它能自动重连重推,实现真正意义上的无人值守。你要做的只是把这个脚本放到 nohup 或者 systemd 服务里常驻运行。

4.3 加一道鉴权,防止别人偷推流

你的直播服务器一旦暴露在公网,就一定会被各种端口扫描器扫到。如果推流路径没有鉴权,任何人都能往你的服务器推流,不仅占带宽,还可能推一些不该出现的内容。所以公网环境下必须处理鉴权问题。

smart_rtmp 基于的 nginx-rtmp 模块支持 on_publish 回调,简单来说:当有人推流时,nginx 会向你的后端接口发起一次 HTTP 请求,校验通过才允许继续推流。

一个最基础的思路是这样的:

在 nginx 配置里加:

application live {
    live on;
    on_publish http://127.0.0.1:8080/auth;
}

后台用一个简单接口来判断推流时带的 sn 参数是否合法。FFmpeg 推流时可以通过 rtmp://ip/live/test1?token=xxx 携带 token,OBS 可以在串流密钥里拼上问号参数。校验逻辑不用复杂,能拦住无效推流即可。

即便不想写后端接口,我也建议至少通过防火墙或安全组把 1935 端口限制在可信来源 IP 范围内。这是最朴素、也最有效的保护手段。

4.4 公网发布时的几点务实建议

如果把服务器开放到公网,有几点建议是从实际备案过的教训里总结出来的:

  • 带宽要按观看人数算。一路 2Mbps 的流,10 个人同时看就是 20Mbps 下行带宽。云服务器带宽买小了,观众会全员卡在缓冲。
  • 域名和证书提前规划。RTMP 地址裸 IP 可用,但 HTTP 播放和未来上 HTTPS 时,没有域名会非常被动。
  • 监控连接数和流量。smart_rtmp 的管理界面能看到在线连接情况,建议定期看一眼,异常连接暴涨时第一时间处理。

5. 我自己踩过的坑和对应的排查链路

部署 smart_rtmp 一路下来没少踩坑,挑几个最有代表性的记录一下,希望你不用再走一遍弯路。

5.1 端口通了但管理界面打不开

有一次我部署完, ss -lntp 显示 8080 明明在监听,服务器本地 curl 也 200,但从我电脑上访问就是转圈。排查了半天,最后发现是云服务器安全组只放行了 1935,没放行 8080。

排查这类问题有一个固定链路:先 curl -I http://127.0.0.1:8080 验证服务本身正常,再 telnet 服务器IP 8080 验证网络路径是否通。如果本地通、外部不通,99% 是安全组或防火墙规则的问题,和 smart_rtmp 本身没关系。

5.2 推流延迟越抬越高,画面开始卡顿

直播过程里如果发现延迟从 2 秒一路涨到 10 秒以上,屏幕越来越卡,多数不是服务端挂掉,而是推流端码率和链路带宽不匹配,导致服务端缓冲队列越积越长。

解决方向有三个:降低推流码率、关闭 OBS 里的动态码率、检查上行带宽是否被占满。我当时遇到的是家里宽带在上传大文件,把上行带宽挤没了,停了上传任务症状立刻消失。

5.3 源码编译跑到半路 OOM

低配服务器上编译 smart_rtmp,尤其是编译 FFmpeg 的时候,很容易因为内存不足直接报错退出。比较快的处理办法是加 swap:

fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

然后重新跑 run.sh 。另外编译时可以手动调整 make 的并行度,默认并行任务太多会瞬间吃满内存,改成 make -j2 或者更保守的 make -j1 ,能极大降低 OOM 概率。

5.4 HLS 播放一直 404

HLS 地址能访问 m3u8 文件,但里面的 ts 切片全部 404,这个场景我也遇到过,原因是 hls_path 配置的目录权限不对。nginx 的工作进程没有写权限,切片文件没生成出来,播放自然失败。

检查方法很直观:看 hls_path 目录里有没有 .ts 文件。没有的话, chown -R nginx:nginx /opt/media/hls 或者改成 chmod -R 755 ,把目录写权限给到位就解决了。

6. 最后说点实际使用中的个人体会

我把 smart_rtmp 从玩票到真正实际使用之后,最大的感受是:它的定位非常精准,就是让你用最小的成本把直播服务器跑起来。你要是硬拿它和 SRS、ZLMediaKit 比并发比协议,确实比不过;但你要是想 30 分钟内搭好一台能推能拉、还能带管理界面的直播服务,找不出比它更省事的方案。

部署顺序上我的建议是:第一次用 Docker 方式跑通全流程,确认链路没问题之后,如果需要长期使用,再切换到源码编译方式。因为源码部署改配置、看日志、接第三方工具都更顺手,而且可以更好地把握内部逻辑。

每次改配置之前先备份原文件,这是我从无数次改崩配置里学到的教训。smart_rtmp 的配置结构不难,但错一个小地方 nginx 就可能起不来,回退到上一份可用配置是最高效的恢复手段。

如果你后续想拿 smart_rtmp 做更商业化的直播分发,不要在单机上死磕并发。它更适合作为源站,上游接 OBS 或者摄像头,下游再分发到 CDN 或者更高并发的流媒体集群。想明白自己的规模边界,就不会在选型上走偏。

Logo

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。

更多推荐