Docker部署SRS流媒体服务器:从推流到WebRTC的完整实践
2026/9/16 1:22:26 网站建设 项目流程

做直播服务或者实时音视频应用的开发者,对 SRS 应该不陌生。这个国产开源流媒体服务器,一台普通机器就能扛住不小的并发,支持 RTMP、HTTP-FLV、HLS、WebRTC、SRT 这些主流协议,很多在线教育、电商直播、安防监控、视频会议项目都是在它上面长出来的。不过以前要在生产环境跑起来,得先编译、配依赖、调环境,一套流程下来没几个小时搞不定。用 Docker 部署 SRS 之后,这个门槛被拉得很低——一条命令启动服务,一个配置文件描述业务,想回滚版本也只是一行 docker tag 的事。

这篇文章我不打算写成官方文档的复读机,而是把我从零开始用 Docker 跑通 SRS 实时音视频链路的全过程拆开来讲,包括环境准备、端口规划、推流配置、鉴权回调、常见坑排查。内容覆盖从“先跑起来”到“生产可用”的完整路径,适合正在选型流媒体服务、打算自建直播平台,或者被云厂商带宽费逼到想自建的同学参考。

1. 为什么选 Docker 部署 SRS

1.1 SRS 到底能解决什么问题

实时音视频服务最麻烦的不是媒体协议本身,而是协议太多、链路太长。客户端推流用 RTMP,网页播放想用 HTTP-FLV,苹果生态要 HLS,低延迟通话又得走 WebRTC,不同端不同协议,服务端如果每种协议都自研一套,工作量直接爆炸。

SRS 做的事情就是把这些协议统一收编。它接收 RTMP 推流,内部转封装成 FLV、HLS,也能桥接 WebRTC 的低延迟传输,开发者不需要关心底层错综复杂的协议转换。配合 Docker 之后,整个服务变成一个黑盒镜像,映射几个端口就能对外提供服务,我本地 macOS 和线上 Linux 服务器跑的是同一套镜像,行为完全一致,这是源码编译很难做到的。

1.2 和源码编译部署相比,Docker 好在哪里

我第一次接触 SRS 的时候,官方文档推荐源码编译。在 CentOS 上要装 gcc、make、pcre-devel、openssl-devel,编译一次十分钟起步,中间只要某个依赖版本不对,就要花半小时上网查错误。后来切到 Docker,整体感受是两个词:干净、可回滚。

对比项Docker 部署源码编译部署
环境依赖无需安装,镜像内置需要 gcc、make、各种 devel 包
部署耗时分钟级编译至少 30 分钟
版本回滚切换镜像 tag 即可需要重新编译或备份二进制
多机扩展镜像一致性强每台机器环境容易漂移
资源隔离容器级隔离,可限 CPU/内存进程级,依赖宿主机环境

我最看重的是可回滚。有一次线上需要升级 SRS 小版本,源码部署的话要先备份原二进制,再重新编译替换,出问题很难迅速退回。Docker 部署只需要把 compose 文件里的镜像 tag 改回去再 up 一次,十几秒就回到旧版本。

1.3 哪些场景适合这套方案

如果你属于下面几类情况,Docker 部署 SRS 是性价比很高的路径:

  • 中小团队自建直播服务,不想被云厂商的流量费绑死
  • 在线教育、陪练、远程医疗需要低延迟音视频互动
  • 安防监控项目需要把摄像头 RTSP 流转成网页可播放的流
  • 短视频、UGC 产品要做开播、连麦、录制回放功能

这套方案的优势在资源可控。云厂商的 CDN 按流量计费,高峰期费用吓人,自建 SRS 之后,只要带宽规划合理,一台 4 核 8G 的云主机就能服务几千路直播观看,边际成本低很多。

2. 部署前的准备工作

2.1 硬件与系统要求

SRS 本身对硬件要求不高,纯转发场景 1 核 1G 的机器都能跑,但真要考虑生产使用,需要结合码率和并发量估算。

一个简单的估算方法:视频码率乘以同时观看人数,就是服务器需要承担的下行带宽。假设直播码率是 2Mbps,同时有 100 人观看,下行带宽需要约 200Mbps,换算成字节是 25MB/s 的持续吞吐。这种量级下,CPU 主要消耗在协议转封装上,WebRTC 转播会比纯 RTMP 转发多吃一些 CPU,4 核起步比较稳。

内存方面,SRS 进程本身占用很低,容器内通常不到 100MB,但 HLS 切片、录制文件会写磁盘,需要考虑磁盘 IO 和容量。我实践中发现,720p 视频 2Mbps 码率,一小时录制大约 900MB 磁盘,做录像回放功能时要按这个量级规划磁盘空间。

2.2 端口规划与防火墙放行

SRS 不像普通 Web 服务只开一个端口,它根据功能不同监听多个端口,部署前必须想清楚端口映射关系。

端口协议用途
1935TCPRTMP 推流与播放
1985TCPHTTP API,用于查询流状态、触发回调
8080TCPHTTP 服务,用于 HTTP-FLV、HLS 播放和管理控制台
8000UDPWebRTC 媒体传输
8001UDPWebRTC 媒体传输(多路复用)

这里面最容易漏的是 8000/8001 的 UDP 端口。很多同学 1935、8080 都映射了,结果 WebRTC 播放一直黑屏,排查半天发现是云服务器安全组没放行 UDP 端口。RTMP 和 HTTP 都走 TCP,云控制台一般默认放行,UDP 经常被忽略。

如果你在本地虚拟机测试,还要注意宿主机防火墙。CentOS 上用 firewalld 的话,需要执行firewall-cmd --add-port=1935/tcp --add-port=8080/tcp --add-port=8000/udp --add-port=8001/udp --permanent并 reload,否则外部设备推流拉流都会被拦。

2.3 Docker 环境安装要点

安装 Docker 这一步,不同系统坑不一样。Linux 上比较省心,用官方脚本安装后启动服务就行。Windows 和 macOS 需要安装 Docker Desktop,这里面有一个高频报错经常把人卡住——Docker Desktop 启动时提示 Virtualization support not detected。

这通常不是 Docker 的问题,而是系统虚拟化没开。Windows 需要确认三件事:BIOS 里开启 Intel VT-x 或 AMD-V,Windows 功能里启用“适用于 Linux 的 Windows 子系统”和“虚拟机平台”,然后执行wsl --set-default-version 2。改完这些重启 Docker Desktop 就能正常启动了。

安装完成后用docker --versiondocker compose version验证,两个命令都有输出,环境就算准备好了。

3. 直接用 docker run 快速启动 SRS

3.1 一条命令跑起来

如果想最快看到效果,直接执行下面这条命令:

docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ -p 8001:8001/udp \ registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5.0-r2

这里用了阿里云镜像仓库的地址,国内服务器拉取速度快,避免 Docker Hub 超时。镜像 tag 选择5.0-r2,是 SRS 5.0 系列比较稳定的版本,能同时支持 RTMP 和 WebRTC。

启动后执行docker logs -f srs看日志,出现start server successfully就说明 SRS 已经起来了。这时候在浏览器访问http://服务器IP:8080/console/,能看到 SRS 自带的管理控制台,当前流列表、连接数、CPU 占用都有,非常适合初期验证。

注意:这条命令用的是默认配置。默认配置下 WebRTC 的 candidate 会被设置成容器内网 IP,导致局域网外的设备无法建立 WebRTC 连接。本地测试没问题,如果要让外部设备也连得上,需要自定义配置,下一章会详细讲。

3.2 验证服务是否正常

服务起来之后,先别急着推流,用 API 接口快速验证一下:

curl http://服务器IP:1985/api/v1/versions

正常会返回版本信息 JSON。再查一下流列表:

curl http://服务器IP:1985/api/v1/streams

此时应该返回空数组。等推流上去之后,再请求这个接口就能看到流的 meta 信息,包括推流地址、视频分辨率、码率、在线观看人数。我在做监控脚本时就靠这个接口定期拉取流状态,实现自动报警。

3.3 默认配置有哪些限制

默认配置适合体验,但直接上生产肯定不行,主要限制有三个。

默认不开启 HTTP-FLV 转封装,网页端无法通过 FLV 地址拉流。默认不开启 HLS,苹果设备无法直接播放。WebRTC 的 candidate 指向容器内部 IP,外部设备连不上。

这三个问题的根源都是配置太简略,需要自己挂载一份完整配置。下一章讲 docker compose 的时候就一并解决。

4. 用 docker compose 搭建生产级 SRS

4.1 编写 compose 文件

我建议任何稍微正式的部署都用 docker compose,原因很简单:端口映射、数据卷挂载、环境变量、重启策略都写在文件里,换机器部署不用回忆当初敲了什么命令。

下面是我实际使用的 compose 文件:

version: "3.9" services: srs: image: registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5.0-r2 container_name: srs restart: always ports: - "1935:1935" - "1985:1985" - "8080:8080" - "8000:8000/udp" - "8001:8001/udp" environment: - CANDIDATE=127.0.0.1 volumes: - ./conf/srs.conf:/usr/local/srs/conf/srs.conf - ./data:/usr/local/srs/objs/nginx/html logging: driver: json-file options: max-size: "50m" max-file: "3"

先创建项目目录,把上面的内容保存为docker-compose.yml,然后根据需求编写conf/srs.conf,最后执行docker compose up -d

这里有几个细节值得说明。restart: always保证机器重启后 SRS 自动拉起,避免人工干预。logging配置防止容器日志无限增长撑爆磁盘。./data挂载目录是 HLS 切片和录制文件的输出位置,必须放到宿主机持久化,否则容器重建历史录像全丢。

4.2 配置文件的重点解析

SRS 的配置格式类似 nginx,注释用#,层级通过花括号表示。下面是一份支持 RTMP 推流、HTTP-FLV/HLS 播放、WebRTC 低延迟播放、HTTP API 查询的完整配置:

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__ { http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } hls { enabled on; } }

配置里的关键点:

listen 1935是 RTMP 入口,max_connections决定最大连接数,我自己线上压过 500 并发,8G 内存的机器非常稳。http_api开启后,1985 端口提供 API,后面的鉴权回调也依赖它。http_remux是重点,开启后 RTMP 流自动转成 HTTP-FLV,网页播放器可以拉http://ip:8080/live/livestream.flv播放。rtc_server配了 candidate,WebRTC 能否连通的关键就在这个字段。

4.3 candidate 参数为什么必须设置

WebRTC 不同于 RTMP 这种服务器中转模式,它要协商出 P2P 或媒体服务器的传输地址。SRS 在容器里运行时,默认探测到的 IP 是容器的内网地址,外部浏览器拿到这个地址根本连不上。

我在 compose 里通过环境变量传入宿主机的 IP:

environment: - CANDIDATE=你的服务器公网IP或内网IP

配置文件中写candidate ${CANDIDATE},SRS 启动时会自动读取环境变量并替换。如果只在局域网内测试,填宿主机内网 IP 就行,比如192.168.1.100。如果要公网访问,必须填公网 IP,同时确保 8000/8001 的 UDP 端口在防火墙和安全组里放行。

有个调试技巧:如果 WebRTC 播放失败,先看一下 SRS 日志里 candidate 实际用的是什么 IP,和浏览器协商的地址是否一致。大多数 WebRTC 连不上的问题,都是 candidate 配置错误。

5. 推流与播放实测:打通第一个直播链路

5.1 用 OBS 推流到 SRS

服务端配好了,接下来做一次完整的推流播放测试。我推荐用 OBS,免费且跨平台。

打开 OBS 后进入“设置 -> 直播”,服务选择“自定义”,服务器填:

rtmp://服务器IP:1935/live

串流密钥填:

livestream

点“开始直播”,如果服务端配置没问题,几秒内 OBS 状态栏会显示“直播中”。这时候回到 SRS 管理控制台,就能在流列表里看到一条live/livestream的流,包括分辨率、码率、帧率信息。

注意:串流密钥不要包含特殊符号,SRS 默认配置下密钥里带?/会有歧义。我习惯把app固定为livestream用业务 ID,比如直播间号、设备序列号,这样后面做流转发和录制都好区分。

5.2 用 ffmpeg 验证推流

OBS 适合人工测试,如果要脚本化验证,推荐用 ffmpeg。把一段视频循环推到 SRS:

ffmpeg -re -stream_loop -1 -i test.mp4 \ -c copy -f flv rtmp://服务器IP:1935/live/livestream

-re表示按视频原始帧率读取,模拟实时推流而不是瞬间推完。-stream_loop -1让视频无限循环。-c copy直接复制编码数据,不重新编码,CPU 占用极低。跑起来后再拉流验证:

ffplay rtmp://服务器IP:1935/live/livestream

能看到画面就说明整个 RTMP 链路已经通了。

5.3 各种播放协议地址对照

SRS 最方便的地方是一条推流,多种协议播放。推流地址是rtmp://ip:1935/live/livestream,那么对应的播放地址如下:

协议播放地址适用场景
RTMPrtmp://ip:1935/live/livestream传统播放器、低延迟要求低
HTTP-FLVhttp://ip:8080/live/livestream.flv浏览器播放、PC 直播
HLShttp://ip:8080/live/livestream.m3u8苹果设备、点播兼容
WebRTCwebrtc://ip:8080/live/livestream低延迟互动、连麦

延迟层面,RTMP 和 HTTP-FLV 通常 1 到 3 秒,HLS 会因为切片缓冲延迟到 5 到 10 秒,WebRTC 可以做到 500 毫秒以内。做在线答题、连麦互动必须上 WebRTC,纯直播观看用 HTTP-FLV 就够了,没必要增加 WebRTC 的复杂度。

6. 后端鉴权与 HTTP 回调:把控制权握在自己手里

6.1 为什么推流接口不能裸奔

服务跑起来之后,最紧急的事情是加鉴权。SRS 默认情况下只要知道你的 IP 和端口,任何人往你的 1935 端口推流,你的服务器就得转发、存储,相当于被人白嫖了带宽和磁盘。更危险的是,你正在直播的内容可能被别人用你的服务器转播到其他平台。

有两种思路做鉴权:内置 token 和 HTTP 回调校验。内置 token 配置简单,但 token 拼在 URL 里容易在日志中泄露。HTTP 回调方式更灵活,由你自己的后端服务决定是否允许推流和播放,适合已有用户体系的业务。

6.2 用 HTTP 回调实现对推流和播放的鉴权

SRS 在推流开始、推流结束、播放开始、播放结束这几个节点会向配置好的回调地址发 HTTP 请求。我在 vhost 配置里加上:

vhost __defaultVhost__ { http_hooks { enabled on; on_publish http://宿主机IP:7000/srs/publish; on_unpublish http://宿主机IP:7000/srs/unpublish; on_play http://宿主机IP:7000/srs/play; on_stop http://宿主机IP:7000/srs/stop; } }

回调 JSON 里会带上appstreamparam,param 就是 URL 里的查询参数。比如推流地址写成:

rtmp://ip:1935/live/livestream?token=abc123

后端收到 on_publish 回调后,解析 token 字段,判断是否合法。返回0表示允许,返回非 0 值 SRS 就会拒绝推流。

注意一个容器网络细节:SRS 容器内的 localhost 和宿主机不是同一个,回调地址不能写http://localhost:7000。在 Linux 上可以用http://172.17.0.1:7000,这是 Docker 默认网桥的宿主机地址。如果用的是 Docker Desktop,直接写http://host.docker.internal:7000更方便。

6.3 录制与 HLS 回看的配置技巧

很多直播业务需要自动录制,SRS 支持在推流时直接存成 FLV 文件。vhost 里加一段:

vhost __defaultVhost__ { dvr { enabled on; dvr_path ./data/[app]/[stream].[timestamp].flv; dvr_plan session; } }

dvr_plan session表示每个推流会话存一个文件,推流断开文件就封存。dvr_path支持按变量自动分目录,我用[app][stream]区分不同直播间。

录制文件默认存在容器内的工作目录,但我在 compose 里挂载了./data到宿主机,所以文件会直接写在宿主机上,方便后续转存对象存储或做点播系统。这里要提醒一句,录制文件增长很快,一定要配合定时清理策略,比如用 crontab 删除 7 天前的文件,否则再大的磁盘也扛不住。

7. 常见问题与排查技巧实录

7.1 Docker 启动失败与环境问题

SRS 容器起不来,先看日志:docker logs srs。最常见是端口被占用,报错信息里会明确说 listen 端口失败。用netstat -tlnp | grep 1935查一下占用进程,改掉冲突的端口映射就行。

Windows 上 Docker Desktop 特别容易遇到Virtualization support not detected的报错,这个我在前面说过,本质是系统的硬件虚拟化或 WSL2 没开。还有一个容易被忽略的点:改完 BIOS 虚拟化设置后,如果 Windows 功能里的“虚拟机平台”没勾选,Docker Desktop 依然起不来。

7.2 WebRTC 播放黑屏或卡在连接中

WebRTC 连不上是最让人头疼的,因为表面现象只是黑屏,日志信息还少。按这个顺序排查:

先确认 8000/8001 UDP 端口在防火墙和安全组放行,用nc -u -z或 telnet 测试 UDP 端口连通性。然后看 SRS 日志里 candidate 的实际值,docker logs srs | grep candidate。最后用浏览器控制台看 WebRTC 的 ICE candidate 信息,如果显示的 IP 和服务器公网 IP 不一致,说明 candidate 配置有问题。

我踩过一次很隐蔽的坑:云服务器有内网 IP 和公网 IP 两张网卡,填公网 IP 后发现服务器自身无法通过 WebRTC 播放,是因为公网 IP 的 UDP 包被安全组拦了。最后发现安全组只放行了 TCP 端口,UDP 没放。这个问题排查了我一个下午。

7.3 推流失败或频繁断开

OBS 推流几秒后断开,先看是不是 token 校验失败。如果没用 token,关闭鉴权测试一次。排查网络层面,尝试从服务器本机推流:ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/test,本机能推通则说明是防火墙或云安全组的问题。

还有一种情况是推流地址写错了。RTMP 推流地址的结构是rtmp://ip:port/app/streamappstream不能随意带路径分隔。如果配了 HTTP 回调,要确认回调地址返回了0,返回非 0 会被 SRS 判定为拒绝推流。

7.4 延迟和画质的调优方向

如果你对延迟有要求,优先用 WebRTC 或 HTTP-FLV,不要用 HLS。HLS 的切片时长直接决定延迟下限,SRS 默认是 10 秒一个切片,浏览器播放还要缓冲几个切片,延迟很容易到 30 秒。可以把 hls 配置里的切片时长调小:

hls { enabled on; hls_fragment 2; hls_window 10; }

画质方面,SRS 本身不做转码,画质取决于推流端的码率设置。OBS 里建议视频码率设 3000 到 6000Kbps,关键帧间隔 2 秒,编码器用硬件编码降低 CPU 占用。

7.5 安全加固的几条建议

最后说安全。自建流媒体服务暴露在公网,等于给所有人开了一扇门,不加防护迟早被刷流量甚至植入恶意内容。

端口尽量只放行业务需要的。如果管理控制台不需要公网访问,8080 端口在安全组里只对办公网 IP 开放。升级域名尽量走 HTTPS/WSS,SRS 5.0 支持在配置里挂证书,避免播放地址被运营商劫持。对推流接口做 token 校验,对播放接口做防盗链校验,这些都是上线前必须完成的动作。

容器本身也要限制资源,compose 里加上:

deploy: resources: limits: cpus: "2.0" memory: 2G

防止某个直播间流量异常时把整台机器拖垮。日志大小限制我前面已经写在 logging 配置里,生产环境千万别省略这个,不然/var/lib/docker被日志撑爆的教训会很难忘。

这套 Docker 加 SRS 的组合,我在线上稳定跑了大半年,最深刻的体会是:流媒体服务并没有想象中那么遥不可及,关键是选对工具、把基础配置吃透。如果你也准备自建实时音视频平台,照着这篇文章的路径走一遍,先把 RTMP 推流和 HTTP-FLV 播放跑通,再一步步加 WebRTC、鉴权、录制这些高级功能,整个过程会比预想中顺利很多。最后再分享一个小技巧,SRS 的配置文件和 nginx 很像,改配置之前一定先备份,上线前用docker compose config检查一下 compose 文件的语法,很多低级错误都能提前发现。

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

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

立即咨询