基于Docker快速部署SRS流媒体服务器:从推流到WebRTC播放的完整实践
最近帮一位朋友折腾直播推流,他家里老人过生日,想搞一个私人的实时音视频直播,一大家子人远程看。他没接触过流媒体这块,又想快速跑起来,我想都没想就推荐了 SRS——没错,就是那个开源的流媒体服务器,全称 Simple Realtime Server。再配合 Docker 一把梭部署,前后不到二十分钟,一套能推能拉、支持 RTMP、HTTP-FLV、HLS、WebRTC 的实时音视频流媒体平台就上线了。这篇文章就是当时部署过程的完整记录,包括方案选型、镜像选择、端口规划、实际踩坑和一些进阶玩法,希望能给想自建流媒体服务的朋友一条明路。
我身边不少朋友一听“流媒体服务器”就觉得是个大家伙,其实今天这套东西,只要你装好了 Docker,跟着下面的步骤走,基本不会卡住。它适合什么人参考呢?第一类是想给家里或公司搭一个私密直播系统的人;第二类是做 Web 或移动端开发,想快速在本地起一套流媒体服务做联调测试的;第三类是初步接触音视频协议,想研究 RTMP、HLS、WebRTC 之间区别的学习者。我尽量把原理和操作放一起讲,保证你看完不是只会复制命令,还能搞明白为什么这么做。
1. 为什么是 SRS + Docker:方案选型的思考
很多人一上来就问“我该用哪个流媒体服务器”,这个问题的答案其实完全取决于场景。如果只是给家里路由器上的小主机配个看摄像头画面的服务,那轻量方案可能就够;但要搞一套正经的直播系统,SRS 在协议支持、社区活跃度、文档完善程度这几个维度上,确实是最省心的选择。尤其是配上 Docker,整个环境的搭建复杂度被压到极低。
1.1 SRS 是什么,能干什么
简单说,SRS 是一个用 C++ 写的高性能流媒体服务器,GitHub 上 star 很多,国内不少直播产品里都有它的影子。它最大的特点就是“什么协议都往嘴里塞,什么协议都能往外吐”:你可以用 RTMP 推流,用 HTTP-FLV 或 HLS 拉流,用 WebRTC 做低延迟直播,也能接入 SRT 处理弱网环境下的传输问题。同时它内置了 HTTP API、回调鉴权、转码、录播、集群这些企业级功能,很多本来需要你再写一套业务逻辑的事情,它自己就干了。
我最开始接触它的时候,其实是想找一个能同时满足“低延迟”和“浏览器直接播放”的方案。用过 Nginx-RTMP 的都知道,它做 RTMP 和 HLS 没问题,但 WebRTC 支持基本是空白,要自己找补一堆第三方组件。SRS 则是把这几条链路都打通了,尤其从 SRS 4.0 开始,WebRTC 的成熟度明显提升,5.0 又在 RTC 和 SRT 上做了大量优化。所以如果你要在 2025 年这个节点选一个开源流媒体服务器,不想折腾组合方案,SRS 基本是默认选项。
1.2 同类型方案对比,为什么选 SRS
这里我把市面上几个常见的可见方案放在一起比一比,纯基于我用下来的感受:
| 方案 | 协议支持 | 维护状态 | Docker 化程度 | 上手难度 |
|---|---|---|---|---|
| SRS | RTMP / HLS / HTTP-FLV / WebRTC / SRT | 活跃,社区大 | 官方镜像维护完善 | 低 |
| MediaMTX | RTSP / RTMP / HLS / WebRTC 等 | 活跃 | 官方镜像 | 中,偏轻量 |
| Nginx-RTMP | RTMP / HLS | 维护少,功能停滞 | 需自己封装 | 中 |
| ZLMediaKit | RTSP / RTMP / HLS / WebRTC 等 | 活跃 | 有第三方镜像 | 较高,文档偏工程化 |
这里面 MediaMTX 我也用过,轻量、配置简单,很适合快速把一路 RTSP 摄像头流转成 RTMP 或 HLS,但它更像一个“协议转换器”,在业务逻辑的丰富度上不如 SRS。ZLMediaKit 是很多视频监控项目的底子,功能很强,但你需要更多的 C++ 背景知识,微信群里也是各说各话,新人容易找不到门。Nginx-RTMP 呢,最大的问题就是太久没大更新,很多协议标准和浏览器兼容性问题,你得自己去填坑。
所以我的结论很直接:如果做的是“直播分发平台”这类需要长期维护、可能加鉴权/转码/集群的业务,直接选 SRS,少走弯路。
1.3 Docker 部署的优势与局限
再说为什么一定要用 Docker 而不是直接编译安装。SRS 本身是 C++ 项目,从源码编译虽然不算难,但要装一堆依赖,而且不同操作系统的差异会让你多花不少时间。Docker 最大的价值不是让你“少打几条命令”,而是把整个运行环境固化成一个镜像,你在这台机器上怎么跑,换一台机器还是这么跑,不存在“在我电脑上是好的”这种尴尬。
另外 SRS 的官方镜像和 GitHub 上的版本发布是同步的,每次升级只需要拉一个新镜像、换一下配置,启动新容器,老容器一停,回滚也特别容易。对我来说,这正是 Docker 最迷人的地方:应用的升级和回滚变成了一次“替换容器”的操作,而不是在服务器上动一堆系统文件。
当然,Docker 也不是没有代价。容器默认走 NAT 网络,对流媒体这种对网络性能敏感的场景,会有一定的转发损耗,但实测下来,在家庭内网或中小型服务器上这种损耗微乎其微。另一个要注意的是,容器是“无状态”的,如果你没做好目录挂载,容器一删数据就全没了——后面我会专门讲怎么避免这个坑。
2. 部署前准备:版本选择、端口与目录规划
真正动手之前,我建议你把三件事想清楚:用哪个镜像 tag、开哪些端口、怎么挂目录。别看这三件事不起眼,想清楚了能帮你躲过后面的绝大多数问题。很多人一上来就
docker run
一把梭,结果后面端口冲突、数据丢失、版本不对,各种问题全来找你。
2.1 选择 SRS 版本与镜像 Tag
SRS 官方在 Docker Hub 上的仓库名是
ossrs/srs
,我推荐直接用带主版本号的 tag,不要用
latest
。
latest
的问题在于它指向的版本是不可控的,今天拉可能还是 5.x,过几个月官方推了新版本,你重新拉就成了 6.x,配置文件变化可能让你措手不及。尤其是生产环境,镜像版本一定要锁定。
具体怎么选版本?目前 SRS 4 是很多老项目在用的稳定版本,SRS 5 则是当前的主力版本,RTC、SRT 相关能力明显更强,我这次配置用的就是
ossrs/srs:5
。如果你在 SRS 官方文档里看到一些比较新的语法,比如
rtc_server
、
http_hooks
这些,以 5.0 的文档为准。如果你要跑老项目,可能会依赖 4.0 时代的一些具体行为,那就用
ossrs/srs:4
。
还有一个小细节:SRS 官方镜像包含了 ffmpeg,路径在容器内的
/usr/local/srs/objs/ffmpeg/bin/ffmpeg
。这个很重要,后面我讲转码的时候会用到,容器内自带 ffmpeg 意味着你可以不依赖宿主机装 ffmpeg 就能完成很多操作。
2.2 端口规划:每个端口是干什么的
SRS 设计的时候把不同功能拆分到了不同的端口上,理解这些端口是理解整个部署流程的前提。我整理了一张表,方便你对照:
| 端口 | 协议 | 用途 |
|---|---|---|
| 1935 | TCP | RTMP 推流/拉流 |
| 1985 | TCP | HTTP API,查询状态、处理回调 |
| 8080 | TCP | HTTP Server,提供 HLS、HTTP-FLV 播放 |
| 8000 | UDP | WebRTC 音视频数据传输 |
| 443 | TCP | HTTPS,用于 WebRTC 播放和网页访问(按需映射) |
这里有个非常容易踩的坑:Docker 端口映射时,默认只映射 TCP,UDP 端口需要显式加
/udp
后缀。我见过不止一个人说 WebRTC 拉流黑屏,排查半天最后发现是 8000 端口的 UDP 没有映射出来。另外,8080 端口在 macOS 上经常被系统 AirPlay 接收器占用,如果你恰好用的是 macOS,记得提前检查。
2.3 目录挂载与持久化设计
SRS 的配置目录在容器内的
/usr/local/srs/conf/
,默认配置文件名是
srs.conf
。HLS 切片、录播文件、静态文件默认放在
/usr/local/srs/objs/nginx/html/
。这两个目录我建议都挂载到宿主机。
配置目录挂载出来,好处是你改配置不需要进容器,在宿主机改完重启容器就行;数据目录挂载出来,好处是 HLS 切片、录像文件会实实在在落在宿主机上,容器删了重建,数据还在。我自己习惯在宿主机上建一个
/data/srs
的总目录,下面分
conf
和
html
两个子目录,结构非常清晰。
这里补充一个权限相关的坑:挂载目录后,容器里 SRS 进程要往
html
目录写 HLS 切片和录像文件,如果宿主机的目录权限不对,SRS 会报写入失败。最简单粗暴的办法是把宿主机目录属主改成 root(因为容器内默认以 root 运行),或者用
chmod -R 777 /data/srs/html
,虽说不算精细,但个人服务器上完全够用。
2.4 Docker 环境检查(Windows/WSL2 踩坑提醒)
我知道不少读者是在 Windows 上折腾,这里单独说一句。Windows 上装 Docker Desktop 最常遇到的报错就是 “virtualization support not detected”,这个基本上两种情况:一是 BIOS 里 Intel VT-x / AMD-V 虚拟化没开,二是 Windows 的 Hyper-V 和 WSL2 功能没启用。你只需要进 BIOS 把虚拟化打开,再在“启用或关闭 Windows 功能”里勾上“虚拟机平台”和“适用于 Linux 的 Windows 子系统”,重启就好了。
Linux 服务器上装 Docker 就简单了,Ubuntu/Debian 用官方脚本
curl -fsSL https://get.docker.com | bash
装完就能用;CentOS 留意一下老版本 Docker 升级的问题,尽量用 Docker CE 的官方源装最新版。装完后输入
docker version
能同时看到 Client 和 Server 版本,说明 Daemon 正常跑起来了。这一步是最重要的,后面所有操作都依赖它。
3. 完整部署实操:从拉镜像到成功推流
理论准备差不多了,现在进入实操环节。我会按顺序走一遍完整流程,命令可以直接复制,但每一段命令我都会解释它干了什么,这样你遇到报错时也知道从哪里下手。
3.1 拉取镜像与创建配置
第一步自然是拉镜像:
docker pull ossrs/srs:5
老规矩,里面那段超时也不用慌,换个国内可访问的镜像源基本就能解决。
然后建目录、写配置:
mkdir -p /data/srs/conf
mkdir -p /data/srs/html
在
/data/srs/conf/srs.conf
里写入下面的内容:
listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
http_api {
enabled on;
listen 1985;
}
http_server {
enabled on;
listen 8080;
dir /usr/local/srs/objs/nginx/html;
}
rtc_server {
enabled on;
listen 8000;
udp 8000;
tcp 8000;
}
vhost __defaultVhost__ {
hls {
enabled on;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
rtc {
enabled on;
}
}
这个配置干了几件事:打开了 HTTP API、HTTP Server、WebRTC,并默认开启 HLS 和 HTTP-FLV 切片。
daemon off
表示前台运行,配合
srs_log_tank console
让日志直接打到标准输出,这样
docker logs srs
就能看到实时日志,排查问题特别爽。生产环境我也建议这样跑,容器本身有日志采集能力,比你埋在文件里再手动去看舒服多了。
3.2 启动容器:完整 docker run 参数拆解
配置写好了,接下来启动容器。我用的命令是:
docker run -d --name srs \
-p 1935:1935 \
-p 1985:1985 \
-p 8080:8080 \
-p 8000:8000/udp \
-p 8000:8000/tcp \
-v /data/srs/conf/srs.conf:/usr/local/srs/conf/srs.conf:ro \
-v /data/srs/html:/usr/local/srs/objs/nginx/html \
--restart=always \
ossrs/srs:5
拆开讲几个关键点:
-
-d:后台运行容器。 -
--name srs:给容器起个名字,后面操作方便。 -
-p:端口映射。这里注意 8000 我映射了 UDP 和 TCP 两个,虽然 WebRTC 主要走 UDP,SRS 5 也支持 TCP 模式,两边都开上免得以后排查问题。 -
-v:把宿主机配置挂到容器内,:ro表示只读。另一个挂载把 HLS 和录像文件落地到宿主机。 -
--restart=always:服务器重启后容器自动拉起,这个对长期运行的服务是必须的,不然机子一重启你还得手动docker start。
启动后立刻看日志:
docker logs -f srs
正常情况下能看到类似下面这行输出:
SRS 5.0-r2 ...
说明服务已经起来了。这时候访问
http://服务器IP:1985/api/v1/versions
会返回一段 JSON,里面包含 SRS 的版本号信息,说明 HTTP API 也通了。
3.3 验证服务与基础推流测试
服务起来了,接下来就是最激动人心的时刻:推一路流试试。推流工具有很多,OBS 是最常用的;但如果只是为了做技术验证,我更喜欢直接用 ffmpeg 推一个本地视频文件。这里有个非常省事的技巧,既然 SRS 镜像里自带 ffmpeg,我们直接在容器里就能推流:
docker exec -it srs ./objs/ffmpeg/bin/ffmpeg -re -i ./doc/source.flv -c copy -f flv rtmp://localhost/live/livestream
-re
的作用是按视频原始帧率读取文件,模拟真实直播流;
-c copy
是不重新编码,直接复制视频流。如果本机有 ffmpeg 也可以用:
ffmpeg -re -i input.mp4 -c copy -f flv rtmp://服务器IP/live/livestream
推上去之后,SRS 日志里会出现 publish 相关的记录,说明推流成功。如果你在浏览器里访问
http://服务器IP:8080/console/
,还能看到 SRS 的 Web 控制台,里面能看到当前在线流、连接数这些实时数据。这个控制台是 SRS 5 自带的,调试和演示都非常方便。
3.4 常见播放协议地址对照
流推上去了,怎么拉下来看?这里我用一张表总结一下播放地址的规律,方便你随时查:
| 播放方式 | 地址格式 | 说明 |
|---|---|---|
| RTMP |
rtmp://服务器IP:1935/live/livestream
| 兼容性最好,延迟相对较高 |
| HTTP-FLV |
http://服务器IP:8080/live/livestream.flv
| 推荐给浏览器和移动端使用 |
| HLS |
http://服务器IP:8080/live/livestream.m3u8
| 兼容性最好,视频切片播放,延迟最高 |
| WebRTC |
webrtc://服务器IP/live/livestream
| 延迟最低,但浏览器要求 HTTPS |
注意 WebRTC 这里有个前提:公网环境下浏览器会强制要求 HTTPS,否则摄像头和麦克风权限会用不了,播放自然就黑屏。如果你只是本地局域网测试,用 IP 地址可能还能放;如果涉及公网访问,建议直接上 Nginx 反代 + HTTPS。这个我在后面进阶部分专门讲。
4. 进阶配置:转码、鉴权与 HTTPS
基础能推能拉,其实已经满足很多场景了。但你要把它当生产服务使,转码、鉴权、HTTPS 这三件事迟早要面对。下面我给三个最常用的配置示例,你按需取用。
4.1 转码配置与性能提醒
转码是流媒体中非常常见的需求:你在服务器上收到一路高码率的 RTMP 流,要给带宽不足的观众分发低码率版本,或者要把源视频流转换成统一编码规格。SRS 封装了 FFmpeg 对转码的支持,配置起来很直观。在 vhost 里加一段:
vhost __defaultVhost__ {
transcode {
enabled on;
ffmpeg ./objs/ffmpeg/bin/ffmpeg;
engine ff {
enabled on;
vcodec libx264;
vbitrate 512;
vwidth 768;
vheight 432;
acodec aac;
abitrate 64;
}
}
}
这段的意思是:对进入这个 vhost 的所有流,用 x264 转成 512kbps、768x432 分辨率的视频,音频用 AAC 编码到 64kbps。启动这个配置后,你推一路 1080p 的流上去,SRS 会自动生成一路低码率流,播放地址的 stream id 后面会带上
_ff
后缀,比如
rtmp://ip:1935/live/livestream_ff
。
不过我要重点提醒:转码是极其吃 CPU 的操作。一个 720p 的转码任务大概能占掉一个完整的 CPU 核,1080p 的话,普通家用服务器基本能感觉到明显卡顿。所以没有特殊需求不要乱开转码,尤其在低配 VPS 上,转码会把整个服务拖垮。我自己的经验是:优先用
-c copy
做“不透传也不转码”的转发,只有当目标终端确实不兼容源编码时才开转码。
4.2 鉴权回调:防止别人盗播你的流
自建流媒体服务器最怕什么?最怕的是你推流的地址泄露,别人拿着你的地址往上推了一路不合规的内容,到时候麻烦的还是你。SRS 提供了 HTTP 回调鉴权机制:在推流或播放请求到达时,SRS 向你的业务服务器发一个 HTTP 请求,你的后端校验通过后返回指定格式的响应,SRS 才会放行。
配置非常简单:
vhost __defaultVhost__ {
http_hooks {
enabled on;
on_publish http://127.0.0.1:1985/auth;
on_play http://127.0.0.1:1985/auth;
}
}
这里
on_publish
对应推流鉴权,
on_play
对应播放鉴权。回调的地址可以指向你自己的认证服务,校验通过则响应 HTTP 200 且 body 为
0
,表示允许;返回非 0 则拒绝。这个机制很实用——它把“流媒体服务”和“业务逻辑”解耦了,推流前先走一遍账号体系校验,防止陌生人白嫖你的带宽和流量。
4.3 HTTPS 与 WebRTC 的配合
前面说过,浏览器里用 WebRTC 播放,必须要有 HTTPS。这里我推荐用一个最省心的方式:Nginx 反向代理。Nginx 监听 443 端口,配置好证书,然后把请求转发到 SRS 的 8080 端口。这样即使用户只访问了一行
https://srs.example.com/live/livestream.m3u8
,Nginx 也能把链路串起来。
Nginx 关键配置片段如下:
server {
listen 443 ssl;
server_name srs.example.com;
ssl_certificate /etc/nginx/ssl/srs.example.com.pem;
ssl_certificate_key /etc/nginx/ssl/srs.example.com.key;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
还有一个很多人容易忽略的坑:WebRTC 的 SDP 里会协商出用于音视频传输的 UDP 端口,也就是我前面反复强调的 8000 端口。这个端口在你的云服务器安全组里必须放行 UDP,否则就算 HTTPS 配好了,视频数据也传不到客户端那边。我自己的习惯是,安全组里把 1935/1985/8080 的 TCP、8000 的 UDP 全部单独列出来,也就是让每一个端口都有明确的注释,这样排错一目了然。
5. 常见问题速查与排查经验
最后这部分,我把实际部署中最常遇到的一类问题整理成一张速查表,并拆成 Docker 层和 SRS 层两个维度来排查,能帮你省掉不少抓头发的时间。
5.1 Docker 层的问题
| 现象 | 常见原因 | 解决方法 |
|---|---|---|
| Docker Desktop 启动报 virtualization support not detected | BIOS 虚拟化未启用 / Hyper-V 未开启 | 进 BIOS 开启 VT-x/AMD-V,启用 Windows 的“虚拟机平台”和 WSL2 功能 |
| 拉镜像超时或速度极慢 | 默认镜像源不稳定 | 配置国内可用的镜像加速器;必要时在多个加速源之间切换 |
容器启动后
docker ps
看不到或立即退出
| 端口被占用 / 配置错误 |
用
docker logs srs
看启动日志,别只盯着容器状态
|
| 容器内写文件报权限错误 | 挂载目录权限不足 |
在宿主机执行
chmod -R 777
或调整属主为 root
|
这里我特别想说一个理念:容器报错不要第一时间
docker rm
强删,而是先
docker logs
看输出。很多问题在日志里其实写得很明白,只是大家一慌就忘了这一步。我见过太多人因为端口冲突,反复删容器重来,最后发现是宿主机另一个程序占用了 8080 端口。
5.2 SRS 层的问题
| 现象 | 常见原因 | 解决方法 |
|---|---|---|
| HTTP API 返回 404 | 版本不对,API 路径或字段有差异 | 确认用了 SRS 4 还是 5,分别查对应版本的 API 文档 |
| 8080 端口访问不通 | HTTP Server 没启用或端口没映射 |
检查 srs.conf 里
http_server
是否
enabled on
,检查 docker run 的
-p
|
| HLS 播放 404 | HLS 没有开启,或切片目录不可写 |
在 vhost 里打开
hls enabled on
,检查挂载目录权限
|
| WebRTC 黑屏 | 浏览器要求 HTTPS / UDP 8000 被防火墙拦截 | 配置 Nginx 反代加证书;在安全组和宿主机防火墙放行 UDP 8000 |
5.3 推流播放中的问题
| 现象 | 常见原因 | 解决方法 |
|---|---|---|
| 推流被断开,日志提示 publish 被拒绝 | 鉴权回调返回失败 |
检查
on_publish
回调地址和返回值,确认 HTTP 响应 code 和 body
|
| 播放卡顿 | 推流码率过高 / 带宽不足 | 降低推流码率,或者在 SRS 中转码输出低码率流 |
| 延迟越来越高 | HLS 切片机制固有延迟 | 需要低延迟就别用 HLS,改 HTTP-FLV 或 WebRTC |
| 直播中断后重连需要几秒 | GOP 缓存机制没有开启 |
在 vhost 里确认
gop_cache on
,可以提升秒开和断线重连体验
|
这里多说一句 gop_cache:它相当于给播放器提供了一个 GOP 缓存的起点,让新加入的观众更快地看到画面,尤其适合观众频繁进出的场景。SRS 默认在 vhost 里开着,但如果你的配置是从旧版本直接抄的,可能就把它关掉了,播放器延迟、花屏这些问题都可能和它有关。
我个人在实际操作中的体会是,Docker 部署 SRS 之所以值得推荐,不是因为它省掉了配置的复杂度,而是它把“跑起来”和“跑得好”分开了:先用最小配置把服务跑起来,再针对具体场景一项项加配置,整个过程随时可以回滚。我第一次部署的时候也踩了不少坑,有一天晚上就是因为没有显式映射 8000 端口的 UDP,WebRTC 拉流怎么都是黑屏,后来用
tcpdump
在服务器上抓包才发现 UDP 包根本没进来。这个教训我一直记到现在:做流媒体服务,不只要查 TCP 端口,UDP 端口和防火墙策略同样重要。如果这篇文章能帮你少走一两个这样的弯路,那就算是值了。
更多推荐
所有评论(0)