☰
开源视频流服务器横评:SRS、MediaMTX、ZLMediaKit与Nginx-RTMP选型指南
2026/10/9 12:39:50 网站建设 项目流程

做视频流相关服务,选一个合适的“视频流服务器”是避不开的第一步。这个领域里“免费+开源”的选项不少,但真正称得上“目前主流”的其实就那么几个。如果你也跟我一样,要做直播、要做摄像头拉流转发、或者要给网页做低延迟播放,这篇文章可以帮你把SRS、MediaMTX、ZLMediaKit和Nginx-RTMP这几个方案从头到尾盘一遍。我会结合自己的实际部署经验,先说选型思路,再给能直接抄的部署步骤,最后把那些文档里没写的坑讲清楚。

1. 视频流服务器的定位:先搞清你面对的是什么问题

1.1 流媒体服务器的核心职责

视频流服务器不是一个“播放器”,也不是单纯的转码工具。它的核心职责是接收、处理、分发视频流。一个完整的流媒体服务链路通常有三件套:输入协议(RTSP、RTMP、SRT等),中间处理(转封装、录制、鉴权、协议转换),输出协议(HLS、HTTP-FLV、WebRTC等)。

我见过不少新手直接把推流地址写给播放器,问为什么手机浏览器打不开。原因很简单:摄像头大多用RTSP输出,而浏览器根本不认识RTSP。中间缺的就是一个视频流服务器,把RTSP拉进来,再转成浏览器能播放的HLS或HTTP-FLV分发给前端。

如果只是单点、单终端、几分钟的传输,那不需要服务器,用WebRTC点对点或者直接UDP推流就够了。但一旦涉及多人同时观看、多终端适配、断线重连、安全管控、录制回放这类需求,就必须引入一个标准流媒体服务。它相当于整个视频链路的“中枢”,把各种协议之间的关系捋顺,也把设备的兼容性问题吃下来。

1.2 免费开源的边界到底在哪

市面上标榜免费开源的视频流服务器不少,但真正能用于生产、持续维护、社区不冷清的其实就几个:SRS、MediaMTX、ZLMediaKit、Nginx-RTMP。它们都是MIT或BSD类宽松协议,商用没有法律风险。

需要澄清一个边界:FFmpeg不是流媒体服务器,它是转码和推流工具,经常配合服务器使用,但本身不承担长期分发的职责。GStreamer是多媒体框架,适合做底层开发,但没有现成的服务端管理能力。Janus是WebRTC网关,更多用于音视频会议,不是通用直播分发。所以下面我只围绕这四个真正意义上的“视频流服务器”展开。

还要提醒一点:有些商业产品也叫开源,但其实核心模块是闭源的,比如某些“开源版”只是做了个壳,或者限制了并发路数。选择前一定要去官方仓库看最近的提交记录和Issues处理速度。一个三年不更新的开源项目,免费倒是免费,但用起来就是给自己埋雷。

2. 四个主流开源服务器横评:SRS、MediaMTX、ZLMediaKit与Nginx-RTMP

2.1 整体对比一览

先放一张我自己整理的对比表,方便你按需求快速定位:

项目开发语言核心协议部署形态维护活跃度最擅长的场景
SRSC++RTMP、HLS、HTTP-FLV、WebRTC、SRTDocker/source编译非常高,社区活跃直播推流、互动直播、跨地域分发
MediaMTXGoRTSP、RTMP、HLS、WebRTC(插件)单二进制/镜像高摄像头接入、多协议互转、轻量边缘服务
ZLMediaKitC++RTSP、RTMP、HLS、HTTP-FLV、GB28181二进制/源码编译高安防监控、国标GB28181、大规模流媒体中间件
Nginx-RTMPCRTMP、HLSNginx模块低,基本停更老项目维护、小型试验、HLS点播

这个表格里的“维护活跃度”是我看GitHub近一年提交频率得到的结论。Nginx-RTMP属于老牌但基本停更的状态,如果只是学习可以用,生产上新项目不建议。

2.2 SRS:直播场景里的主力

SRS全称Simple Realtime Server,是国人团队开源的流媒体服务器,也是四个人里面功能最全的。它原生支持RTMP推流,转发到HLS、HTTP-FLV,而且内置了WebRTC播放能力,延迟可以压到几百毫秒以内。

我用SRS做直播推流转发的体验是:配置极简,主配置文件一个srs.conf就够,理解起来不费劲。它最厉害的一点是单进程就能同时处理RTMP拉流、HLS切片、HTTP-FLV分发,不需要像Nginx-RTMP那样全靠外部模块拼凑。生产环境里还能配置成源站/边缘集群,适合做CDN级别的分发架构。

SRS的另一个优势是文档全,官方Wiki把每个配置项都讲得很清楚,包括API接口、回调鉴权、录制切片、转码插件。遇到问题基本能在官方文档里找到答案,这是免费开源项目里很难得的。

2.3 MediaMTX:轻量转发的瑞士军刀

MediaMTX(前身叫rtsp-simple-server)是用Go写的,体积极小,一个二进制文件搞定,特别适合嵌入式设备或者需要快速搭建的临时服务。

它的核心能力是“协议转换器”:可以把一个RTSP摄像头流同时输出成RTSP、RTMP、HLS、WebRTC,也能反过来,把RTMP推流转成RTSP给其他设备看。这种多协议互转能力在接入不同厂商设备时非常有用。我遇到过一些老旧摄像头不支持RTMP,但输出RTSP很正常,用MediaMTX拉RTSP再转成RTMP,下游的云平台就能直接收流了。

MediaMTX的配置是YAML格式,简单直观。它对弱网也做了很多处理:断流自动重连、RTSP的keepalive、UDP/TCP模式切换,这些都内置了,不需要自己造轮子。唯一需要注意的是它定位是“轻量”,没有SRS那么完善的回调和集群能力,超过一定并发后会比较吃力。

2.4 ZLMediaKit:安防领域的隐形王者

ZLMediaKit是C++开发的高性能流媒体服务器,在安防监控圈子里用得非常多。它最大的特色是支持GB/T 28181国标协议,这是国内摄像头平台接入的硬需求,SRS和MediaMTX都不直接支持。

我是在做一个安防项目时接触到它的:几十路摄像头通过GB28181注册到平台,平台再统一输出RTSP/HLS给Web端查看。ZLMediaKit对这种场景的优化很到位,支持RTP TCP/UDP被动收流,也支持按需拉流,省了很大的带宽压力。

另外它提供了一套完整的REST API和Hook回调机制,可以编写业务逻辑对接自己的后台系统,比如订阅流事件、控制录像、获取拉流地址等。如果你做的是监控平台、视频中台、或者需要对接大量国标设备,ZLMediaKit基本是绕不开的选择。

2.5 Nginx-RTMP:老古董但仍有市场

Nginx-RTMP是Nginx的一个第三方模块,很多人通过它开启RTMP推流和HLS直播。这个方案2015年左右非常流行,因为当时浏览器里的Flash还能用,RTMP是绝对主流。

但Nginx-RTMP的维护已经基本停滞,很多年没有大更新。它本身不提供HTTP-FLV输出,也没有WebRTC支持,想实现现代播放体验还得自己搭一层转发。不过它有一个不可忽视的优势:如果你已经有一个Nginx服务,在这个服务器上加个模块就能实现流媒体能力,不用额外起进程,对系统资源极其友好。

如果你只是临时跑一个测试环境、验证一下推流逻辑,Nginx-RTMP还是够用的。但新项目我不推荐,你会在后续扩展WebRTC、跨域配置、回调鉴权这些功能时感受到强烈痛苦。

3. 协议二十分钟速览:先选协议再选服务器

3.1 RTSP与RTMP的核心区别

视频流服务器的“协议”是绕不开的话题。很多问题看似服务器选得不对,实际是协议没选对。

RTSP全称Real Time Streaming Protocol,主要用来控制流媒体会话,媒体数据走RTP通道。它本身不关心流的内容是直播还是点播,只负责“播放/暂停/快进”这类控制命令。RTSP的默认传输有UDP和TCP两种,摄像头厂商基本都支持RTSP,但它有个痛点:浏览器原生不支持,直接通过Web播放需要转封装。

RTMP则是Adobe提出的RTMP协议族的代表,基于TCP传输,设计目标就是“推流+直播”。它天然适合推流上行,把音视频数据从编码器传到服务器。RTMP最初依赖Flash播放器,Flash退市后直接播放已经不行了,但推流侧仍然是主流,抖音、快手这种平台的推流端协议底层也和RTMP有渊源。

3.2 为什么HLS延迟大但兼容性好

HLS(HTTP Live Streaming)的思路是把连续流切片成一段一段的小文件(.ts),再生成一个.m3u8索引文件。播放器先下载索引,再逐段拉取切片播放。好处是完完全全基于HTTP,所有服务器、CDN、浏览器、播放器都认识,配合也很好。

但切片过程会引入缓冲:至少要先攒够一个切片的时长,播放器还要再缓存几个切片防止卡顿,所以常见直播的HLS延迟在5到15秒,有些保守的实现甚至到20秒以上。如果你只是做演唱会直播或电视转播,这个延迟可以接受;但如果是连麦互动、远程操控类业务,HLS基本没法用。

3.3 HTTP-FLV与WebRTC构成低延迟双雄

HTTP-FLV就是把RTMP里的媒体数据用HTTP协议传输,播放器端通过flv.js这样的库把流解包出来。它在体验上保留RTMP的低延迟(1到3秒),又解决了浏览器不能直接播放RTMP的问题,是目前Web直播场景最常用的播放协议。

WebRTC则是另一套思路:浏览器间或浏览器与服务器间通过UDP点对点或转发传输媒体,延迟可以控制在几百毫秒以内,是视频会议的技术基础。让服务器支持WebRTC推流和播放,需要额外的信令服务和UDP端口管理,SRS和MediaMTX都有这种能力,但配置复杂度陡增。

我的建议是:如果是直播内容分发,优先HTTP-FLV或HLS;如果对延迟要求极高,直接上WebRTC;如果只是内部摄像头对接,RTSP就够了。先想清楚你的“终端”是什么,再回来看服务器特性,就不会被协议问题困住。

4. 从零部署一套SRS直播服务(含推流拉流验证)

4.1 为什么拿SRS做部署示范

四个项目里,SRS是文档最全面、上手最平滑的,而且Docker镜像一条命令就能跑起来,适合用来做演示和验证。多协议互转、WebRTC播放都能在默认配置里体验,对新手来说容错率很高。下面这套流程我实测过多次,直接抄作业没问题。

4.2 Docker启动与基础配置

先用Docker启动一个SRS 5.x版本的容器,映射关键端口:

docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ ossrs/srs:5

这里几个端口各司其职:

  • 1935:RTMP推流/拉流端口
  • 1985:SRS的HTTP API端口,用来查询状态和回调
  • 8080:HTTP服务端口,比如HTTP-FLV流和网页播放器页面
  • 8000/udp:WebRTC的UDP端口

启动后可以检查一下API是否正常:

curl http://localhost:1985/api/v1/versions

正常会返回带版本号的JSON。然后浏览器访问http://localhost:8080,能看到SRS默认的演示播放器页面。

如果只是临时测试,默认配置就够了。但建议你在/usr/local/srs/conf/srs.conf里打开http_api、http_server相关配置,确认http_remux支持HTTP-FLV输出。默认的Docker镜像已经开启了这些,不需要额外改。

4.3 推流与拉流验证

准备一个本地mp4文件,用FFmpeg推流到SRS:

ffmpeg -re -stream_loop -1 -i test.mp4 \ -vcodec copy -acodec copy \ -f flv rtmp://127.0.0.1:1935/live/test

这里的-re是让FFmpeg按真实时间速率读取文件,模拟直播现场;-stream_loop -1表示循环推流,方便反复测试。

推流成功后,开另一个终端拉流。先用RTMP直接拉:

ffplay rtmp://127.0.0.1:1935/live/test

如果实验机器没有桌面,可以用FFmpeg转存落地来验证流是否正常:

ffmpeg -i rtmp://127.0.0.1:1935/live/test -c copy out.mp4

更推荐验证HTTP-FLV拉流,因为浏览器方案通常用它:

ffplay http://127.0.0.1:8080/live/test.flv

打开浏览器访问http://127.0.0.1:8080/players/srs_player.html?autostart=true,填入http://127.0.0.1:8080/live/test.flv,就能直接看到直播画面。这个播放器页面是SRS自带的,调试时非常方便。

4.4 更多协议输出与验证

SRS默认还支持HLS输出。推流成功后,过几秒会在/usr/local/srs/objs/nginx/html/live/test.m3u8生成切片文件,直接访问:

curl http://127.0.0.1:8080/live/test.m3u8

能看到返回的m3u8列表。WebRTC播放则需要额外的信令配置,SRS默认也带了,访问播放器页面时选择WebRTC模式即可。但我第一次测WebRTC踩过坑:必须在能访问到公网地址的机器上测试,否则会拿到内网IP导致握手失败。开发环境可以先用HTTP-FLV兜底,生产再上WebRTC。

5. 实战中的坑与排查:端口、同源策略、鉴权和断流重启

5.1 端口与网络边界:最容易被忽略

很多人本地跑通了服务,换到服务器或局域网就不行。第一个要查的就是防火墙和云安全组。SRS默认监听多个端口,云服务器需要放行1935、1985、8080、8000/udp,其中8000/udp是WebRTC必需,如果遗漏,浏览器播放会一直处于“连接中”,但RTMP和HTTP-FLV却正常。

排查时我会先用netstat或ss确认端口确实在监听:

ss -lntup | grep -E '1935|1985|8080|8000'

然后从外部用nc -vz <服务器IP> 8080逐端口测试。如果云控制台的安全组和你服务器里的iptables混在一起,容易出现内外配置不一致,这种情况我会直接先清掉本机iptables规则,再逐条添加,避免被已有的默认策略误伤。

5.2 HTTP-FLV跨域(CORS)问题的修复

浏览器里用flv.js播放http://其他域名:8080/live/test.flv时,经常报CORS错误,画面黑屏但FFplay能正常播放。原因是HTTP-FLV的跨域请求被服务器默认策略拦截了。

SRS的解决办法是修改http_server配置,加上跨域响应头:

http_server { crossdomain on; }

改完重启SRS。MediaMTX则不需要特殊配置,它对跨域默认比较宽松。ZLMediaKit也可以通过配置文件里[http]的allow_cross_domains选项控制。

这种坑很容易误导人,因为本地用FFplay根本试不出来,必须用浏览器控制台看网络请求。所以我现在只要涉及Web播放,第一步就在浏览器F12里看请求头,而不是猜是哪边的问题。

5.3 推流鉴权:用回调拦截陌生推流

免费开源服务器默认都不设防,知道IP和端口的人都可以推流上来占资源。生产环境必须做鉴权。

SRS的方式是在rtmp_server里配置callbacks,推流时请求你的业务接口:

vhost __defaultVhost__ { rtmp { enabled on; } http_hooks { enabled on; on_publish http://127.0.0.1:8081/auth/publish; on_unpublish http://127.0.0.1:8081/auth/unpublish; } }

你的回调接口接收到SRS发来的请求后,根据stream、app、param等字段决定返回0(允许推流)还是非0(拒绝推流)。我习惯在推流地址上加签名参数:rtmp://host/live/test?token=xxx,回调时校验token。

MediaMTX的鉴权逻辑更简单,在YAML配置里直接声明用户名密码:

auth: method: internal internalUsers: - user: admin pass: secret

ZLMediaKit则是通过REST API配置流的鉴权,适合和大型后台系统集成。

5.4 RTSP源不稳定时的保活思路

用摄像头RTSP源的时候,最烦的就是摄像头偶尔断流。SRS、MediaMTX对输入源断线后的处理策略不同:MediaMTX会自动重连RTSP源,而SRS如果没有额外配置,上游断开后下游会直接掐断。

我的做法是:输入端单独放一层MediaMTX或ZLMediaKit,用来拉取摄像头RTSP并转成RTMP输出,然后再让SRS或你的业务流系统从RTMP拉流。这样源断掉后,中间的转发层会按自己的重连策略恢复,下游不用反复重建连接。对摄像头这类设备来说,它们普遍支持TCP方式的RTSP,记得把传输模式从UDP改为TCP,会稳定很多。

5.5 资源占用与日志轮转

看过一个生产事故:SRS跑了几个月,日志文件涨到几十GB,磁盘被写满,流服务全部卡死。开源服务器默认不会自动切日志,需要你自己配置日志轮转或定时清理。

SRS里可以设置日志路径并用log_tank控制输出到文件和屏幕,然后配合logrotate做排转。MediaMTX是Go写的,日志量相对小,但我也会用系统日志做限制。还有一个隐蔽问题:如果长时间开启HLS录制,切片文件会不断累积,记得配置dvr里的文件保留策略,或者写个定时任务删除过期切片。

6. 不同业务场景的选型与扩展建议

6.1 家庭监控:MediaMTX + 内网穿透

如果你家里有摄像头,想在手机上随时看,我建议选MediaMTX。先用一个低功耗设备(树莓派或旧路由)跑MediaMTX,把摄像头的RTSP流接入,再通过Docker镜像或指纹二进制部署到边缘,转发成RTSP或HLS输出。对于外网访问,配合内网穿透工具,把HLS地址暴露出去就够用了。这个方案的优势是:内存占用小、断线自动重连、配置可读性强。

6.2 中小型直播:SRS是稳妥的起点

要做推拉流直播,比如直播课程、活动直播,SRS是最稳的选择。它内置HTTP-FLV和HLS,默认页面都提供了,前端接入成本低。需要录制回放时,SRS的DVR模块直接开启即可。如果是业务初期,一台2核4G的云服务器跑SRS,承载几百路并发观看基本没问题。

需要注意一个性能边界:SRS默认处理的是“分发”,不是“转码”。如果推流端视频码率过高,或者客户端带宽不够,级联画面就会卡。这时候应该在推流端或源站前做一次FFmpeg转码,把码率压下来,而不是让服务器硬扛。

6.3 安防集中平台:ZLMediaKit + GB28181

如果你的项目需要接入大量国标摄像头,或者要做“一机一档”这类安防平台,那必须上ZLMediaKit。它支持GB28181的注册、心跳、媒体流管理,统一把设备端的PS流转成RTSP/HLS/HTTP-FLV输出。ZLMediaKit的REST API可以让我把“流上线事件”推给业务后台,实现自动告警,这是其他几个项目不太好直接实现的功能。

6.4 边缘嵌入式:轻量方案与裁剪

对路由器、开发板这类场景,我建议评估MediaMTX的单二进制优势,它的静态编译版本可以在x86、ARM等架构上跑,一条命令启动,适合放在边缘节点。SRS也有ARM版本,但整体体积和依赖比MediaMTX重。边缘设备算力有限,尽量只做协议转换和短时间缓存,不要做转码和切片。

6.5 关于集群和上云的建议

如果你已经过了单机阶段,需要扩容,优先考虑SRS的源站/边缘集群方案。SRS有Edge模式,可以配置边缘节点从源站拉流,实现就近分发。另外也可以把HLS切片直接写到OSS/NAS上,通过CDN分发,减少服务器压力;但直播低延迟场景还是优先HTTP-FLV源站分发,CDN公司一般不免费支持HTTP-FLV,需要确认商用成本。

我自己折腾视频流服务器的顺序是:先用Nginx-RTMP搭了个测试,遇到HLS延迟之后换MediaMTX,后来又因为WebRTC需求换成SRS,再到安防项目专门上了ZLMediaKit。说白了,没有哪一个是绝对完美的,只有谁更适合当时的业务。如果你现在还纠结怎么选,我的建议是先明确你手里的流是RTSP还是RTMP、终端是浏览器还是播放器、延迟要求是几秒还是几百毫秒,然后再选服务器。选定了就用默认配置跑通,之后慢慢补鉴权和录制,这样踩坑的成本最低。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询