Docker 部署 SRS 流媒体服务器:从直播到 WebRTC 的完整实践指南
做流媒体开发这几年,我折腾过的流媒体服务器不止一套:Nginx-RTMP、MediaMTX、Janus、SRS……但平时最常用、也最愿意推荐给别人的还是 SRS。原因很简单,它用一套服务把直播、点播、低延迟连麦这些音视频场景全包了,而且配合 Docker 部署,几乎是我见过把上手成本压得最低的方案之一。这篇文章就把我实际部署 SRS 的过程、踩过的坑,以及几个生产环境里真正用得上的配置,一次性写清楚。无论你是想给家庭监控接一个流媒体中心,还是要在公司内部搭一套直播系统,或者只是个人想玩一下音视频,这套“Docker + SRS”的组合都值得你花半小时试一遍。
很多人第一次接触流媒体服务器,第一反应是“这东西是不是很重”?实际上 SRS 是一个 C++ 写的单进程服务,官方镜像只有几十 MB,跑起来内存占用往往不到 100MB。用 Docker 一发搞定之后,你会发现真正花时间的不是部署,而是后面理解协议和调参——那才是音视频项目的核心乐趣所在。好了,先从选型思路讲起。
1. 为什么是 SRS + Docker,而不是 Nginx-RTMP 或裸机编译
1.1 SRS 的核心能力图谱
SRS(Simple Realtime Server)是一个开源的实时流媒体服务器,简单理解就是:你把一路视频流推给它,它负责把这份流按需转成各种格式,再分发给无数个观众。它支持的协议非常全,我一列你就知道这意味着什么:
| 协议 | 典型用途 | SRS 支持情况 |
|---|---|---|
| RTMP | 传统直播推流/拉流 | 原生支持 |
| HTTP-FLV | 网页低延迟直播 | 内置 HTTP Server 直接输出 |
| HLS | 点播、大并发、兼容性最好 | 转封装后输出 .m3u8 |
| WebRTC | 连麦、低延迟互动 | 内置 RTC Server |
| SRT | 弱网环境下的推流 | 支持 |
| GB28181 | 安防摄像头国标接入 | 5.0+ 内置 SIP 服务 |
正是这种“一个进程全协议栈”的设计,让它特别适合做音视频网关。举例来说,海康摄像头走 GB28181 把流推给 SRS,SRS 能同时输出 HLS 给网页播放器、输出 RTMP 给老平台、再用 WebRTC 给低延迟看板,一套服务就把端到端的链路打通了。如果你以前用过 Nginx-RTMP,就会发现 SRS 相当于把“协议转换”这件事做到了开箱即用,不用再额外拼装其他模块。
1.2 为什么用 Docker 而不是裸机编译
SRS 本身是 C++ 项目,裸机部署也没那么难,但通常需要先装编译工具链、拉源码、跑 configure 和 make。我最早一次在生产服务器上编译 SRS,因为机器上 GCC 版本太老,折腾了一下午才搞定。Docker 方案直接把这些问题抹平了:官方镜像 ossrs/srs:5 开箱即用,容器里的编译环境、运行依赖全是现成的,宿主机上只要有一个能跑 Docker 的环境就够了。
更重要的是升级和回滚。裸机部署想升级版本,得先停服务、备份二进制、再编译新的,一旦出问题要回退就更麻烦。Docker 只需要拉一个新 tag、换一个镜像重启容器,出问题就用旧镜像秒级回滚。再加上同一台机器可以同时跑好几个 SRS 实例做隔离测试,开发环境、预发环境互不干扰,这对“一个人维护多套服务”的场景特别友好。说句实话,我后来把公司的内网直播服务也从裸机迁到了 Docker,运维成本肉眼可见地降了下来。
1.3 这套方案适合谁,能顶住什么规模
我见过不少人对 SRS 有误解,以为它是玩具。其实 SRS 在开源流媒体服务器里属于相当能打的一个,单机撑几百路的并发观看完全没问题,具体能跑多少取决于流的码率、机器 CPU 和网络带宽。个人项目、中小型直播平台、企业内部的培训直播、门店监控上云,都是它的典型应用范围。如果你只是临时测试,Docker 一条命令就能跑起来;如果后续要上生产,再用 Docker Compose 做精细化配置也不迟。
另外,SRS 的文档相当完整,中文文档对开发者非常友好,这一点在国内开源项目里尤其难得。我处理过很多项目,遇到问题查 issues 往往能直接找到答案,这也是我敢在日常项目里长期用它,而不是换成其他方案的原因之一。
2. 部署前准备:环境检查、目录规划与镜像加速
2.1 先确认宿主机环境
动手之前,先确认你机器上的 Docker 是能用的。Linux 上直接执行
docker --version
,Windows 和 macOS 用户则先装好 Docker Desktop。Windows 用户特别注意一点:Docker Desktop 需要开启 WSL2 或者 Hyper-V,如果一启动就报 “virtualization support not detected” 之类的错误,多半是 BIOS 里虚拟化没打开,或者 Windows 功能里的“适用于 Linux 的 Windows 子系统”没启用。这个问题和 SRS 本身无关,但卡住的人特别多,所以先排查一遍最省时间。
确认安装完成后,建议再执行
docker info
看下基本信息。如果输出正常,说明 Docker 守护进程在跑。Linux 服务器上如果出现权限问题,可以把当前用户加进 docker 组:
sudo usermod -aG docker $USER
newgrp docker
这一步做完之后,当前会话就能免 sudo 执行 docker 命令了。然后顺手检查一下磁盘空间,SRS 镜像不大,但后续录制文件、HLS 切片都是写在磁盘上的,空间不够会很尴尬。
2.2 镜像拉取慢的解决方案
SRS 的官方镜像在国内网络下有时会拉得很慢,这是很多新手第一道坎。解决办法是给 Docker 配置镜像加速器。修改
/etc/docker/daemon.json
(Windows 上路径和 Linux 不同,可以在 Docker Desktop 的设置里改),加入 registry-mirrors:
{
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
修改完重启 Docker:
sudo systemctl restart docker
注意:镜像加速地址不一定长期可用,如果发现拉取还是慢,可以换成其他能用的镜像源地址。判断标准很简单——
docker pull ossrs/srs:5能快速跑到几百 MB/s 就对了。
我自己实测,配置好加速之后,拉 SRS 镜像基本就是几秒钟的事,整体体验会好很多。
2.3 端口规划与防火墙放行
SRS 要用的端口不算少,但每一个都有明确的用途。先看一张规划表:
| 端口 | 协议 | 用途 |
|---|---|---|
| 1935 | TCP | RTMP 推流/拉流 |
| 1985 | TCP | HTTP API,管理接口 |
| 8080 | TCP | HTTP-FLV、HLS、控制台页面 |
| 8000 | UDP | WebRTC 媒体传输 |
| 1989 | TCP | SRT 协议(可选) |
| 5060 | TCP/UDP | GB28181 SIP(可选) |
如果是云服务器,光在系统层面放行还不够,还得去云控制台的安全组里加规则。很多人在本地测试一切正常,一上云就推流失败,十有八九是安全组端口没放行。系统防火墙这边,Ubuntu 用 ufw,CentOS 用 firewalld,示例是 ufw:
sudo ufw allow 1935/tcp
sudo ufw allow 1985/tcp
sudo ufw allow 8080/tcp
sudo ufw allow 8000/udp
sudo ufw reload
不记得自己有没有放行的时候,最直接的办法是用
telnet IP 端口
或者
nc -vz IP 端口
测试连通性,一秒就能判断问题出在服务本身还是网络层。
2.4 目录结构设计
容器是临时文件系统,容器一删,里面的配置、日志、录制文件全没了。所以生产环境一定要做目录挂载。我习惯在宿主机建这样一个目录结构:
~/srs/
├── conf/
│ └── srs.conf
├── data/
│ └── www/ # HLS 切片、录制文件、点播文件
└── logs/ # 运行日志
这个结构的好处是,配置、产物、日志三者分离,之后备份和排查问题都非常方便。
data/www
目录对应容器里的 HTTP 根目录,SRS 生成的 HLS 切片和录制文件都会落在里面;
logs
目录用于之后排查,容器 stdout 日志也可以重定向到文件里。
3. 上手实操:三种部署方式从简单到规范
3.1 用 docker run 三十秒跑起 SRS
如果你是第一次接触 SRS,我强烈建议先用一条最简单的命令把它拉起来,感受一下“原来流媒体服务器这么轻”:
docker run --rm -p 1935:1935 -p 1985:1985 -p 8080:8080 -p 8000:8000/udp -t ossrs/srs:5
这条命令拆开看:
-p
做了四个端口映射,分别是 RTMP、HTTP API、HTTP 服务和 WebRTC;
-t
是为了让 SRS 能输出彩色日志;
--rm
表示容器停止后自动删除,适合临时测试。执行后你会看到一堆日志滚动,最后出现类似
RTMP stream server listening on :1935
的字样,就说明服务起来了。
这时候打开浏览器访问
http://localhost:8080/
,你会看到 SRS 的默认引导页。再访问
http://localhost:8080/console/
,能进入内置控制台。同时可以验证一下 API 是否正常:
curl http://localhost:1985/api/v1/versions
返回 JSON 里带了版本号,说明 SRS 的核心服务都正常了。
3.2 验证服务:控制台、WebRTC 与流地址检查
服务起来之后,很多人不知道下一步该干什么。我的建议是先用 SRS 自带的“播放器”页面测试。控制台里有一个在线播放器,输入一条流地址就能直接播放。这比你自己写前端播放器快得多,也方便判断“服务有问题”还是“播放器代码有问题”。
此时还没有推流,控制台里看不到任何流,这是正常的。验证拉流地址是否可达,可以用 curl 请求一个不存在的流,比如访问
http://localhost:8080/live/test.flv
,返回 404 其实也代表服务在正常响应。真正要测直播效果,还得先推一路流上去。
3.3 进阶版:docker compose 部署与持久化
等你在 docker run 里玩明白了,就该上 docker compose 了。这个方案能让你把端口、目录、重启策略固化在一个文件里,以后任何一台机器都能快速复现。先准备一个
docker-compose.yml
:
services:
srs:
image: ossrs/srs:5
container_name: srs
restart: always
ports:
- "1935:1935"
- "1985:1985"
- "8080:8080"
- "8000:8000/udp"
volumes:
- ./conf/srs.conf:/usr/local/srs/conf/srs.conf
- ./data/www:/usr/local/srs/objs/nginx/html
- ./logs:/usr/local/srs/objs
这里的
restart: always
是关键,它保证 Docker 重启或机器重启后 SRS 能自动拉起,省去“人肉盯服务”的烦恼。启动命令也很简单:
docker compose up -d
-d
表示后台运行,想看日志就执行
docker logs -f srs
。以后要升级镜像,改一下 tag,再
docker compose up -d
就行;想回滚,把 tag 改回去再执行一次同样的命令。
3.4 推流测试:FFmpeg 打一路视频流
没有摄像头也没有采集卡时,最方便的推流工具是 FFmpeg。找一台装了 FFmpeg 的机器,用一条命令把本地视频文件循环推给 SRS:
ffmpeg -re -stream_loop -1 -i local.mp4 -c copy -f flv rtmp://localhost:1935/live/livestream
我来解释一下各参数:
-re
按原速读取文件,模拟真实推流;
-stream_loop -1
无限循环;
-c copy
不重新编码,直接复制流,CPU 占用非常低;
-f flv
指定输出封装格式;最后的地址就是 SRS 的 RTMP 入口。推流之后,浏览器打开
http://localhost:8080/console/
,在 streams 列表里就能看到
live/livestream
这条流。
如果用摄像头推流,Linux 下可以用 v4l2:
ffmpeg -f v4l2 -i /dev/video0 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/live/camera
提示:推流地址里的
live是 app 名,livestream是流名,这两个字段可以灵活定义,后面播放地址、录制路径都会用到它们来区分业务。
3.5 三种拉流协议对比:如何选地址
SRS 同一路流可以输出多个协议,拉流地址怎么选,取决于你的播放端场景。我把最常用的三种放一起对比:
| 拉流协议 | 地址示例 | 延迟水平 | 适合场景 |
|---|---|---|---|
| HTTP-FLV | http://host:8080/live/livestream.flv | 1~3秒 | 网页直播、微信小程序直播 |
| HLS | http://host:8080/live/livestream.m3u8 | 5~15秒 | 点播、跨平台兼容播放 |
| WebRTC | webrtc://host:8080/live/livestream | <500ms | 连麦、会议、互动直播 |
我个人的习惯是:网页端用 HTTP-FLV,兼顾延迟和兼容性;需要兼容 iOS Safari 等没有 FLV 原生支持的场景时,用 HLS;做一对一或小范围互动时,直接上 WebRTC。RTMP 则主要用于推流端,因为如今浏览器已经基本不支持 RTMP 播放了,但推流端生态里 RTMP 依然是最通用的。
4. 配置拆解:录制、低延迟与鉴权三大实战场景
4.1 直播录制:DVR 配置
直播录制的需求非常普遍,比如企业培训要留存回放,门店监控要留证据。SRS 的 DVR 模块可以自动把直播流落盘。在自定义配置文件的 vhost 里加一段:
vhost __defaultVhost__ {
dvr {
enabled on;
dvr_path ./objs/nginx/html/record/[app]/[stream]/[2006]/[01]/[02]/[15]/[04]/[05].[flv];
dvr_plan session;
}
}
DVR 模块支持按推流会话切文件(session),也支持按固定时长切文件(duration)。录制成 FLV 是默认行为,兼容性最好;如果你需要 mp4,可以在录完之后用 FFmpeg 做一次转封装,或者用 SRS 的转封装功能再处理。这里有个容易被忽略的点:
dvr_path
里面的日期占位符是按 UTC 计算还是本地时间,SRS 有对应的配置项,国内使用记得确认时区,否则录出来的文件名时间对不上。
4.2 低延迟直播:gop_cache 与协议优化
直播延迟是音视频项目里绕不开的话题。SRS 默认配置偏向兼容和稳定,延迟大概在 3~5 秒;如果要做互动型直播,就得手动做低延迟优化。关键在于关闭 GOP 缓存、调小播放缓冲、开启 TCP_NODELAY:
vhost __defaultVhost__ {
tcp_nodelay on;
play {
gop_cache off;
play_buffer 50;
}
}
gop_cache off
的效果是,新观众进来时不会等到下一个关键帧才出画面,从而降低“起播即卡”的感知延迟。但代价是起播时可能没有关键帧参考,部分播放器会出现短暂花屏。所以如果只是做大规模直播、不追求极低延迟,反而建议保持 gop_cache 开启,让新观众能快速看到画面。延迟这件事,永远是业务场景优先,不是参数越激进越好。
低延迟不是 SRS 单方面能决定的,推流端的设置同样关键。用 OBS 推流时,关键帧间隔(GOP)建议设成 2 秒以内,否则播放端为了等关键帧,延迟会肉眼可见地增大。整条链路是“推流端编码参数 → SRS 服务器转发 → 播放端解码缓冲”一起决定最终延迟的,只调服务器不如把三段一起调。
4.3 鉴权与防盗链:HTTP 回调验证
生产环境里的流媒体服务基本都要做鉴权,否则任何人都能把视频推到你的服务器上,或者任意拉走你的直播流。SRS 最常见的鉴权方式是 HTTP 回调:推流或播放时,SRS 向你的业务后端发一个请求,由后端决定允许还是拒绝。
vhost __defaultVhost__ {
http_hooks {
enabled on;
on_publish http://127.0.0.1:3000/auth;
on_play http://127.0.0.1:3000/auth;
}
}
后端接口收到请求后,检查参数里的 app、stream、签名等字段,返回 HTTP 200 就放行,返回非 200 就拒绝。这个方案的优点是灵活,你可以接自己的账号体系、时间戳签名、甚至风控系统,比简单的防盗链密钥要可靠得多。实现后端接口时注意一个问题:回调必须在超时时间内返回结果,如果后端超时,SRS 默认会拒绝流,所以鉴权接口一定要稳,最好做本地缓存。
4.4 点播与回放目录管理
SRS 不只是直播服务器,也能直接当静态文件服务器用。前面
data/www
挂载的目录就是 HTTP 根目录,你把 MP4 文件放进去,就能用 HTTP 地址直接点播:
http://host:8080/vod/xxx.mp4
这个能力很适合做“直播回放”:直播按 DVR 录成文件后,脚本自动把录像文件移动到
data/www/record/
目录,前端就能直接通过 HTTP 地址播放回放,完全不需要再部署一套点播服务。如果你对 HLS 点播更熟悉,也可以把直播存成 HLS 切片再生成 m3u8 播放列表,SRS 在直播场景下会自动维护这一点,但回放场景建议用现成的 MP4,省心不少。
5. 常见故障排查与避坑实录
5.1 容器起来了但推流失败
这个问题的排查路径非常固定:先确认端口。
docker ps
看容器状态和端口映射;再用
telnet 127.0.0.1 1935
测本地端口通不通;最后看云服务器安全组有没有放行 1935。很多时候问题就出在安全组,而不是 SRS 本身。
排除了端口,再看推流地址。RTMP 地址格式是
rtmp://host:1935/app/stream
,很多新手会把 HTTP-FLV 地址和 RTMP 地址混用,导致推流一直连不上。最后可以看日志:
docker logs -f srs
,日志里会清楚打印推流请求和报错原因。掌握这三步,九成推流问题都能定位。
5.2 WebRTC 一直连不上
WebRTC 是坑最多的地方,因为它既依赖 TCP 又依赖 UDP,而且对网络环境相当敏感。本地 localhost 测试能通,放到公网就连不上,这种现象十有八九是 candidate 配置问题。SRS 的 RTC 模块需要知道自己的公网 IP,否则返回给浏览器的连接地址是内网 IP,观众自然连不上。
rtc_server {
enabled on;
listen 8000;
candidate your-public-ip;
}
这里直接写死公网 IP 是最省事的方案。另外,浏览器在 HTTPS 页面下才能稳定使用 WebRTC,如果你的页面是 HTTP,localhost 可以跑,但在非本机环境下浏览器会限制 WebRTC 能力。所以公网部署时,前端页面尽量放在 HTTPS 后面,再通过反向代理转发到 SRS。
5.3 录制文件为空或没有权限
DVR 录制文件为空,最常见的原因是容器内的进程没有目录写权限。用 docker compose 挂载目录时,宿主机目录的所有者和容器内进程用户不一致,就会导致写入失败。解决办法很简单:启动前先给目录一个宽松一点的权限,或者在配置里单独指定录制目录的路径,确保它在挂载范围内。
另一个隐蔽坑是配置文件没生效。如果你改了宿主机上的
conf/srs.conf
,但容器里还是旧配置,先检查挂载路径是否正确。可以进容器确认:
docker exec -it srs cat /usr/local/srs/conf/srs.conf
,看内容是不是你改的那份,如果不是,多半是 compose 文件路径写错了。
5.4 容器重启后配置丢失
docker run 临时测试跑出来的容器,一删就没,这是很多新手的血泪教训。解决思路很朴素:所有需要持久化的东西全挂载出来。配置、日志、录制文件,一个都不能少。搭配
restart: always
之后,即使机器重启,SRS 也会自动恢复,基本可以做到无人值守。
如果你已经踩过坑,容器被删了但数据目录是挂载的,那没问题;最怕的是当初没挂载目录,一删容器所有录像和日志都跟着没了。所以我的经验是:哪怕只是临时测试,也尽量用 compose 加挂载,别贪图 docker run 一条命令的省事。
5.5 并发上来后卡顿与 CPU 飙高
SRS 本身是 C++ 高性能服务,单机并发处理能力很强,但瓶颈往往在带宽和推流端编码。观众端卡顿,先去检查公网带宽是否打满,而不是怀疑服务器性能。一路 1080p 直播大概需要 4~8 Mbps,100 路观看就是 400~800 Mbps,普通家用带宽根本扛不住。
如果并发确实上来了,可以考虑 SRS 的集群模式:一台源站负责接收推流,多台边缘节点分发拉流,中间用流分发协议同步。SRS 原生支持 Origin/Edge 集群,配置思路也不复杂,但那是另一个话题了。单机部署时,我更建议压一压推流端的码率,合理设置关键帧间隔,很多时候卡顿问题就缓解了大半。
6. 进阶玩法与周边生态组合
6.1 内置控制台与 HTTP API 的进阶用法
SRS 自带的 Web 控制台能看流列表、在线人数,但它真正强大的地方是 HTTP API。你可以把拉流数、推流状态这些数据接到自己的监控系统里:
curl http://localhost:1985/api/v1/streams/
返回的 JSON 会列出所有在线流,包括每个流的推流时间、视频编码、音频编码等信息。做自动巡检、异常告警都很方便。比如定时脚本检查某条关键流是否在线,不在线就发钉钉/企微通知,这个在很多直播运维场景里非常实用。
6.2 与 FFmpeg、MediaMTX 等其他工具组合
SRS 的定位是流媒体分发核心,但整个音视频链路里,它通常不是唯一组件。推流端可能用 OBS,转码可能用 FFmpeg,协议网关可能用 MediaMTX,SRS 则负责把流稳定地分发给大量观众。
我常用的一套组合是:摄像头 → MediaMTX 拉 RTSP → 转成 RTMP 推给 SRS → SRS 输出 HLS 给前端播放。这里 MediaMTX 只做协议转换,SRS 只做分发,各司其职,出问题也好排查。FFmpeg 则用在需要裁剪、加水印、转码的场景,比如定时任务把录制的视频裁成片段,或者把视频转成低码率版本供移动端播放。
6.3 公网部署的几个隐藏注意点
本地玩明白了,想部署到公网服务器,有几个点很容易被忽略。
第一,安全组放行端口要一次性配全,特别是 UDP 8000,很多云平台默认不放行 UDP 端口。第二,如果用了 WebRTC,
candidate
一定要配成公网 IP,这是公网 WebRTC 最常见的坑。第三,控制台页面最好加一层访问控制,毕竟它能查看和管理所有流,裸奔在公网上不安全。我一般用 Nginx 做反向代理,给控制台和 API 加上 Basic Auth 或者 IP 白名单。第四,日志要做轮转,SRS 长时间运行日志文件会越来越大,用 Docker 自带的 log rotation 或者挂载目录后配合 logrotate 都可以。
还有一个细节:Docker 镜像更新前,先看看官方 changelog,SRS 的配置项在不同大版本之间偶尔会有调整,贸然升级可能导致旧配置无法解析,容器起不来。升级前备份 conf 目录是最基本的纪律。
这套 SRS + Docker 的组合我实际用了快三年,踩过最大的坑就是公网部署时忘了配置 WebRTC 的 candidate,导致内网能连、公网永远黑屏。后来我把部署模板固化成 compose 文件,任何新服务器基本都能在十分钟内跑通。如果你打算长期用,我建议从一开始就把配置和录制定位到宿主机目录,别贪图 docker run 一条命令的省事。还有一个小技巧:推流测试时不要只用一个播放器,不同协议的拉流各开一个窗口同时验证,能帮你更快定位是推流问题还是分发链路的问题。这套东西的边界远不止“搭起来能跑”,协议转换、集群分发、AI 音视频分析都可以在它上面继续延伸,等你把基础玩熟了,自然就知道下一步该往哪儿走了。
更多推荐
所有评论(0)