SRS(Simple Realtime Server)是一款非常成熟的开源音视频流媒体服务器,早期大家习惯把它叫做“简单的实时服务器”,但实际上它在直播、低延迟通话、录播、SRT推流这些场景里表现相当能打。以往要跑一套流媒体服务,从源码编译到依赖处理再折腾几个钟头是常有的事,Docker 化之后流程被大幅压缩,我今天就完整记录一下用 Docker 部署 SRS 的过程,从镜像选择、容器配置到推拉流验证、常见坑位,一次性写清楚。
这篇内容适合正在选型流媒体服务、准备自建直播平台、或者在本地做音视频测试的同学。看完后不保证你能一步到位跑出商用级集群,但至少从零开始搭一个稳定的 SRS 单节点,验证 RTMP、HLS、WebRTC 这些核心协议链路是完全没有问题的。
1. 项目背景与整体思路
1.1 SRS 是什么,为什么要自建流媒体服务
SRS 全称 Simple Realtime Server,底层使用 C++ 编写,性能强悍,单机并发能力相当可观。它支持 RTMP、HLS、DASH、WebRTC、SRT、GB28181 等多种协议,无论你是做传统直播、低延迟互动,还是接入监控摄像头流,SRS 都能作为服务端核心来用。
很多人纠结“直接用云厂商的 CDN 直播服务不好吗”,这个取决于场景。云厂商的流媒体服务确实方便,但如果你只是内部测试、临时做一场活动直播、或者在做产品原型验证,按月付费的云直播产品往往显得冗余。自建 SRS 只要有一台普通服务器,就能跑起完整的直播链路,适合中小规模场景,也能为后续上云迁移保留标准协议的灵活性。
我最初用 SRS 是给一个在线教育产品做课堂直播的降级方案,当时的核心需求是支持 RTMP 推流、H5 页面能看、同时还要控制延迟不能太高。SRS 的 HTTP-FLV 和 HLS 完美符合,而且部署成本极低,后面慢慢用它做各种流媒体实验,发现它比很多商业产品的兼容性和灵活性都好。
1.2 为什么选 Docker 而不是直接编译安装
直接源码编译 SRS 不是不行,官方文档也给了明确流程,但问题出在依赖环境和版本管理上。SRS 涉及 openssl、ffmpeg、srt 等一堆库,服务器上如果同时有别的业务,很容易因为库版本冲突产生“站位错位”式的问题。编译一次加上下载依赖至少二十分钟,如果想切换版本又要重新来一轮,效率太低。
Docker 的好处是把运行时环境、配置文件、依赖库整体封装在镜像里,做到一次构建处处运行。升级回滚特别简单,换镜像标签就能完成。SRS 官方长期维护 Docker 镜像,跨版本升级成本几乎为零。对没有专职运维的团队来说,Docker 部署能显著降低维护压力和出故障的概率。
另外一个很重要的点是隔离性。流媒体服务对 TCP 连接数和网络带宽要求高,通过 Docker 的端口映射和资源限制可以控制容器占用,不至于某个异常流把整个服务器内存吃光。单容器崩溃也不会影响宿主机其他业务,这个在混合部署的场景里非常实用。
2. 环境准备与镜像获取
2.1 Docker 环境安装要点
先确认服务器上已经存在 Docker。使用docker -v检查版本,如果还没有安装,可以参考 Docker 官方脚本,在 Ubuntu/Debian 系系统里执行:
curl -fsSL https://get.docker.com | bash systemctl enable --now docker在 CentOS/RHEL 系可以改用 yum 安装,yum install -y yum-utils后配置官方仓库再装 docker-ce。Windows/macOS 用户建议直接安装 Docker Desktop,不过生产环境还是以 Linux 为主。
创建容器之前建议先确认内核参数开启 IPv4 转发,SRS 的 WebRTC 场景对网络栈依赖比较重:
sysctl -w net.ipv4.ip_forward=1 echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf注意:如果服务器本身有防火墙,提前放行 TCP 1935、1985、8080 以及 UDP 8000 端口。WebRTC 走的是 UDP 传输,只放 TCP 会导致连接一直建立不起来。
2.2 拉取 SRS 官方镜像
SRS 官方镜像发布在 Docker Hub 和阿里云镜像仓库,推荐优先使用阿里云镜像地址,在国内拉取速度快得多:
docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5这个5是主版本号,对应 SRS 5.x。如果网络环境特殊,使用 Docker Hub 也可以:
docker pull ossrs/srs:5拉取完成后执行docker images能看到镜像列表。官方镜像默认工作目录/usr/local/srs,里面包含 srs 主程序、配置文件模板和全套支持工具。观察容器内文件结构有助于理解 SRS 的行为方式,建议先用交互式命令进去逛一圈:
docker run -it --rm registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 bash ls /usr/local/srs/conf/这样做的目的是熟悉配置文件和目录布局。conf/下放着docker.conf、rtmp.conf、hls.conf、webrtc.conf等预置模板,直接拿模板做修改,比从空文件开始手写配置更稳妥。
3. SRS 容器部署实操
3.1 最简方式先跑起来
使用官方默认配置直接启动,验证 SRS 能正常工作。第一条命令只映射必要的端口,适合首次快速验证:
docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5各端口作用解释一下:
1935是 RTMP 协议默认端口,用于推流和拉流;1985是 SRS HTTP API 端口,提供流状态查询、在线统计等功能;8080用于 HTTP 服务,包含 HLS 播放地址访问和 SRS 控制台。
启动后访问http://服务器IP:8080/console/可以看到 SRS 内置的 Web 控制台。页面能显示当前流数、客户端数、CPU 占用等运行状态,这个控制台虽然在生产环境用处不大,但调试阶段相当好用,可以直观确认服务是否活着。
如果页面能打开,说明基础服务已正常。这时候只是用了最小化配置,离“能推能拉”还有一步。要支持完整的协议功能,需要引入更详细的配置文件。
3.2 自定义配置文件挂载
最小配置只能跑 RTMP 相关的简单功能,生产环境需要在配置文件里明确 HLS 开关、HTTP 回调、鉴权策略、SRT 支持等。SRS 的优势在于所有功能都是配置驱动的,改配置文件后重启容器即可。
在宿主机创建配置目录,准备持久化配置文件:
mkdir -p /opt/srs/conf /opt/srs/objs touch /opt/srs/conf/srs.conf chmod 755 /opt/srs/conf/srs.conf配置文件格式如下,兼容 SRS 5.x 的常见使用需求:
listen 1935; max_connections 1000; daemon off; srs_log_tank console; http_api { enabled on; listen 1985; } http_server { enabled on; listen 8080; dir ./objs/nginx/html; } rtc_server { enabled on; listen 8000; candidate $CANDIDATE; } vhost __defaultVhost__ { hls { enabled on; hls_path ./objs/nginx/html; hls_fragment 2; hls_window 12; } http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } srt { enabled on; srt_latency 300; } }需要注意,daemon off配合srs_log_tank console是关键,Docker 容器里如果以 daemon 方式运行,进程会脱离 PID 1 导致容器退出。日志打到 stdout 后可以通过docker logs srs实时查看,排查问题效率高。
candidate $CANDIDATE是 WebRTC 必须的配置项,稍后启动容器时要通过环境变量传入服务器的公网 IP 或内网 IP。WebRTC 协商过程需要告诉客户端“我应该连哪个 IP”,这个 IP 配不对,即使端口全开也无法通话。
3.3 启动带配置的 SRS 容器
确认配置文件无误后,开始启动正式容器:
docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ -p 10080:10080/udp \ -e CANDIDATE=你的服务器公网IP \ -v /opt/srs/conf/srs.conf:/usr/local/srs/conf/srs.conf:ro \ -v /opt/srs/objs:/usr/local/srs/objs \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 \ ./objs/srs -c conf/srs.conf映射 UDP 8000 端口给 WebRTC,映射 10080 给 SRT。-v /opt/srs/objs这个目录映射很关键,HLS 分片文件、DVR 录像、HTTP 服务目录全在这里,不挂载出来的话容器一删数据就全没了。
./objs/srs -c conf/srs.conf是覆盖默认启动命令,官方镜像的默认入口本身就会加载配置,但显式指定配置文件可以避免误用到容器内部的预置模板。
启动后使用docker logs srs观察日志,看到类似下面内容就代表启动成功:
SRS 5.0.xxx Copyright ... config: conf/srs.conf startup: ...3.4 配置持久化与后续维护
容器跑起来以后,日常维护主要围绕修改配置和数据备份展开。每次逻辑调整只需要在宿主机编辑/opt/srs/conf/srs.conf,然后重启容器:
docker restart srs重启操作很快,SRS 进程从加载配置到监听端口就绪一般只需要几秒。数据备份就更简单了,把/opt/srs/objs目录整体打包即可,HLS 切片、录像文件全部在里面。
这里谈一下为什么不推荐使用 Docker Desktop 跑生产环境的 SRS。Docker Desktop 在 Windows/macOS 上底层依赖虚拟化技术,网络模型和 Linux 原生环境差异明显,特别是 UDP 端口映射和 NAT 穿透行为不稳定,做本地开发测试问题不大,但压测和生产建议还是用 Linux 服务器,可以少踩很多怪坑。
4. 推拉流验证与协议实战
4.1 RTMP 直播推拉流全流程
SRS 部署完成后,第一个标准动作是用 RTMP 做推拉流验证。使用 ffmpeg 推送本地视频文件或者摄像头流:
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://服务器IP/live/test如果没有现成的视频,可以用 SRS 自带的 FFmpeg 工具生成测试视频源,或者简单用手机摄像头推流。SRS 默认应用名是live,test是自定义流名称,后续拉流时保持同一路径即可。RTMP 拉流用以下命令:
ffplay rtmp://服务器IP/live/test也可以使用 VLC 播放器打开网络串流,输入同样的 RTMP 地址。此时去 SRS 控制台http://服务器IP:8080/console/里面能够看到活跃流列表,里面记录着推流时间、码率、帧率、客户端数量。这组命令看似简单,却是验证整套链路是否通畅的黄金路径。
实际操作中会遇到一个情况:推流端的-re参数如果漏了,ffmpeg 会以极限速度把文件瞬间推完,直播画面一眨眼就结束了。第一次做测试时我也踩过这个坑,原因是-re强制 ffmpeg 按原始帧率读取文件,模拟实时流,不加就会以最快速度推流。
4.2 基于 HLS 的播放验证
HLS 的验证重点在 HTTP 服务是否正常响应。推流后等待 2-3 秒,SRS 的 HLS 模块会把直播流转为 TS 分片文件,播放地址通常是:
http://服务器IP:8080/live/test.m3u8在浏览器里访问这个地址,或者用 VLC 打开 m3u8 链接,能看到画面就说明 HLS 链路正常。m3u8 索引文件里记录了分片组成的序列,每个分片包含约 2 秒的视频数据,具体分片时长由hls_fragment和hls_window控制。hls_fragment 2表示每 2 秒生成一个 TS 文件,hls_window 12表示索引里只保留最近 12 秒的分片。
HLS 延迟基本在 6-10 秒之间,这是因为播放器需要先缓冲几个分片才能保证播放连续。如果对延迟要求高,HTTP-FLV 才是更优解。SRS 配置里已经开了http_remux,可以直接用 FLV 地址播放:
http://服务器IP:8080/live/test.flvFLV 播放的延迟通常在 1-3 秒,很多在线课堂、低延迟直播场景都用这个模式。支持 FLV 的播放器非常多,小程序、Web 端、移动端都有成熟 SDK 可用。
4.3 WebRTC 低延迟验证
WebRTC 的验证相对复杂一些,但对低延迟互动场景必不可少。SRS 5.x 对 WebRTC 协议支持已经很成熟,推拉流都是标准接口。在浏览器里打开 SRS 提供的 WebRTC 测试页面:
http://服务器IP:8080/players/rtc_player.html如果使用虚拟摄像头或桌面共享推流,也可以使用 SRS 的 WebRTC 推流页面。重点考验的是之前配置的candidate $CANDIDATE是否设置正确。这个参数决定了 SDP 协商时向客户端公布的 IP 地址。
我在用云服务器测试 WebRTC 时遇到过一种典型问题:服务器有公网 IP 也有内网 IP,没有显式设置 candidate 时,SRS 可能把内网 IP 写入 SDP,浏览器拿它去连接,结果一直卡在“连接中”状态。解决办法很直接,在启动命令的环境变量里把CANDIDATE设为该服务器的公网 IP,或者内网测试环境就设内网 IP。也可以通过配置文件硬编码:
rtc_server { enabled on; listen 8000; candidate 你的IP; }DNS-DERP 之类的生产级中继方案属于进阶话题,单机测试阶段设置 candidate 足够用。WebRTC 跑通后,延迟基本能做到 500ms 以内,是当前公共互联网上体验最好的低延迟方案之一。
4.4 SRT 弱网传输验证
SRT 协议主要用于弱网环境下的稳定传输,SRS 5.x 内置了 SRT 支持。rtmp 推流之外,可以用 ffmpeg 以 SRT 方式推流:
ffmpeg -re -i test.mp4 -c copy -f mpegts 'srt://服务器IP:10080?streamid=#!::r=live/test,m=publish'拉流时把m=publish改成m=request即可。SRT 的优点是自带重传机制,在网络抖动时可以保持视频流稳定,很多广电级传输场景都在使用。SRS 的 SRT 支持在实际测试中表现不错,配置不算复杂,但要求客户端使用支持 SRT 的 ffmpeg 或专用推流端。
5. 常见问题排查与生产优化
5.1 端口冲突与拉流失败
最常发生的问题是端口被占用,尤其是 1935 端口,如果服务器之前跑过其他流媒体服务,很容易出现“RTMP 推流失败”的情况。排查命令:
netstat -tlnp | grep 1935 ss -lunp | grep 8000如果有其他进程占用,杀掉冲突进程或修改 SRS 配置的监听端口都可以。拉流失败另一个常见原因是从公网拉流时防火墙没有放行对应端口,这个前面环境准备时提过,需要系统防火墙和安全组两端都检查一遍。
经验教训:使用云服务器时,安全组策略和系统防火墙是两个独立维度,只放行安全组而系统防火墙默认 deny 的情况下,外网依然连不进去。
5.2 HTTP API 统计与流状态排查
SRS 的 HTTP 服务提供了多种 API 接口。查询当前活跃流数量和客户端信息:
curl http://服务器IP:1985/api/v1/streams/返回的是 JSON 结构,里面包含每个流的 ID、名字、来源 IP、推流时间、视频编码、音频编码、码率等详细信息。这个接口在定位“为什么流黑屏”“为什么播放卡顿”时非常有用,可以判断推流端到底有没有成功推上来,以及编码参数是否异常。
还有几个常用接口:
/api/v1/clients/查看当前所有客户端连接信息;/api/v1/raw/streams/可获取更底层的流状态;/api/v1/record查询 DVR 录制信息。
用这些 API 可以封装出简单的流监控脚本,定时探测流是否在线,断了就告警。我在维护 SRS 期间就是靠这些接口做了个轻量级看板,配合告警规则能及时感知异常流。
5.3 控制台进不去和鉴权问题
浏览器访问控制台提示 404 或者无法加载,多数情况是 HTTP 服务根目录配置不对。配置文件里的dir ./objs/nginx/html路径需要和宿主机挂载的目录对应。如果镜像内该路径下不存在console目录,就需要在配置中明确指定。
生产环境中 SRS 控制台和 API 不应直接暴露在公网,建议用反向代理配合鉴权。简单做法是在 Nginx 里给/console/和/api/加 basic auth,或者限制来源 IP。SRS 自身也支持 HTTP 回调鉴权,推流时向鉴权服务发请求,鉴权失败拒绝推流。回调配置在 vhost 下:
http_hooks { on_publish http://你的鉴权服务/api/auth_publish; }这层设计能有效防止陌生人往你的流媒体服务器推流,对外提供服务时必须考虑。
5.4 容器内存和 CPU 资源控制
流媒体服务对资源消耗十分敏感,尤其是码率高的流。Docker 直接启动时不加限制会占满宿主机资源,建议根据业务预估给容器加上资源配额:
docker run -d --name srs \ --memory=1g \ --cpus=1.5 \ ... \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 \ ./objs/srs -c conf/srs.confSRS 本身性能很好,单核处理多路标清流没有压力,但高码率流和大量并发客户端会有明显 CPU 消耗。加资源限制的另一个好处是防止异常流量把容器 CPU 打满拖垮宿主机上的其他服务。
5.5 日志切割与长期运维
SRS 把日志打到 stdout 后,全部交给 Docker 的 logging driver 管理。生产环境建议配置json-file日志轮转:
docker run -d --name srs \ --log-opt max-size=50m \ --log-opt max-file=5 \ ... \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5max-size=50m表示每个日志文件最大 50MB,max-file=5表示保留 5 个历史文件。如果不加这个配置,长时间运行后/var/lib/docker/containers/目录会被日志撑爆,清理起来很头疼。
5.6 版本升级与回滚策略
Docker 部署升级流程极其简单。先拉取新镜像:
docker pull registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5然后删除旧容器重新运行。配置文件和数据目录都在宿主机上,容器删除重建不影响业务数据。升级前最好先备份当前配置文件和 objs 目录,以防万一需要回滚:
cp -r /opt/srs/conf /opt/srs/conf.bak.$(date +%Y%m%d) cp -r /opt/srs/objs /opt/srs/objs.bak.$(date +%Y%m%d)SRS 5.x 各小版本之间配置兼容性比较好,但大版本之间有一定差异,如果跨大版本升级,需要仔细阅读官方迁移文档。
6. 进阶玩法与扩展场景
6.1 FFmpeg 转码集成
SRS 本身是一个流媒体服务器,不包含转码能力。接入不同编码源的流时,需要配合 FFmpeg 做转码。例如 RTMP 推流编码是 H.264+AAC,移动端播放基本够用,但如果要兼容老旧设备或者统一码率,就需要转码。
常见的做法是在宿主机部署 FFmpeg,把源流转成不同清晰度的目标流后再推给 SRS。也可以用 FFmpeg 做截图、水印、多画面合成等处理,这些都不需要 SRS 参与,属于流媒体链路的前处理或后处理环节。
6.2 负载均衡与集群部署
单节点 SRS 最多能支撑的并发量受限于服务器本身的 CPU、带宽和内存。有更高的承载需求时,可以用 SRS 的 Origin 和 Edge 模式做集群。Origin 作为源站接收推流,Edge 节点负责对外分发。
SRS 的原生集群配置比很多商业流媒体服务简单得多,基本逻辑是 Edge 回源自 Origin 拉流,Origin 只需要正常配置推流域名和拉流域名解析,Edge 上开启回源配置即可。这个模式能横向扩展播放能力,而推流能力和存储能力仍然集中在 Origin。
我见过不少团队用云厂商的负载均衡器配合多台 SRS Edge 节点搭建分发网络,在区域间有多点部署需求时非常有效。对于单数据中心几千路并发以内的场景,单机 SRS 加合理调优通常足以应对,不必一开始就上集群。
6.3 录制回放与 DVR
SRS 支持将直播流录制为 MP4 文件。配置里开启 DVR 模块后,推流期间会自动生成录像文件,结束后可直接用于点播回放:
vhost __defaultVhost__ { dvr { enabled on; dvr_path ./objs/nginx/html/[app]/[stream].[timestamp].mp4; dvr_plan session; } }dvr_plan session表示每次推流会话生成一个 MP4 文件,配合 HTTP 目录可以直接提供回看地址。录制文件同样存储在/opt/srs/objs目录下,通过挂载目录可以方便地迁移和备份。
6.4 鉴权与防盗链配置
对外提供流媒体服务时,防盗链是必修课。SRS 支持 referer 防盗链和 token 鉴权。referer 方法适合防止网页端盗播,token 方法则更适合 App 场景。
token 鉴权通常在推流环节用 HTTP 回调实现,播放环节用 referer 或者自定义头。SRS 也支持内置的on_connect、on_play等回调,可以在播放前请求业务服务校验权限。相比完全开放的服务,加一层鉴权能大幅减少被别人盗用带宽的可能。
6.5 与 WebRTC 通话、直播结合
SRS 在 5.x 版本把 WebRTC 作为一等公民支持,可以实现直播与实时通话的混合场景。例如观众通过 WebRTC 上麦连麦,服务端将多路流合流转成直播流,再分发给所有观众。这种场景常见于在线课堂、连麦直播、视频面试等。
SRS 提供的 SFU 能力虽然不如专业集成的音视频通信云方便,但对于已经具备一定音视频经验的研发团队,完全可以基于 SRS 搭建一套可控的私有低延迟互动系统。整体成本比云厂商的实时音视频服务低很多,只是需要自己处理客户端 SDK 和信令服务。
我在实际使用中发现,SRS 最核心的竞争力不只是功能多,而是配置改动后的行为可预测性很强,几乎每个模块都有详细的日志输出,出了任何问题都能顺着日志找到根因。排查问题思路基本是三步:确认网络通不通、确认配置对不对、确认日志有没有报错。把这条路走通,SRS 的日常维护不会占用太多精力。
最后再分享一个小技巧:在测试 WebRTC 或排查推拉流问题时,尽量使用 SRS 自带的控制台页面和示例播放器,它们能省去你自行判断播放器兼容性的时间。遇到问题不要急着改配置,先看日志里的错误关键字,按模块去定位,比自己瞎猜快得多。这套基于 Docker 的部署方式我已经稳定运行很长时间,希望这篇记录能帮你在流媒体服务搭建上少走弯路。