使用Docker部署SRS流媒体服务器:从推流到WebRTC的完整指南
2026/9/15 14:40:25 网站建设 项目流程

在直播、音视频互动相关的项目里,SRS(Simple Realtime Server)是一个绕不开的名字。很多团队在早期调研流媒体方案时都会看到它,尤其是配合 Docker 部署 SRS 的方式,几乎成了搭建实时音视频流媒体平台最快的一条路。我最早接触 SRS 是在一个内部培训系统里,需要把讲师的屏幕和摄像头信号实时分发给几百人,当时对比过几套方案,最后选了 SRS,原因很简单:协议支持全、部署简单、社区活跃。如果你也是第一次接触这个方向,或者正在纠结怎么把手头的直播需求落地,这篇内容会从实际部署的角度带你完整跑通一遍。

这篇文章会覆盖为什么选择 SRS 加 Docker 的组合、部署前需要准备什么、如何用几条命令启动一个可用的流媒体服务,以及推流、拉流、鉴权、WebRTC 这些关键环节的实操方法。结尾还会分享一些我踩过的坑和排查思路,适合刚接触流媒体服务的开发者,也适合想快速验证业务方案的团队参考。

1. 为什么是 SRS + Docker:先搞清楚你到底要搭什么

1.1 SRS 是什么,它解决了什么问题

SRS 的全称是 Simple Realtime Server,是一个用 C++ 写的开源流媒体服务器。它的定位很简单:把各种来源的音视频流收进来,然后按需转发给不同协议的播放端。你可以把它理解成一个音视频的中转站——主播端用 RTMP 推流上来,观众端可以用 RTMP、HTTP-FLV、HLS 或者 WebRTC 拉流观看,SRS 负责处理这些协议之间的转换和分发。

在没有 SRS 这类服务之前,想自己搭一个直播平台意味着要处理一堆底层问题:协议怎么解析、缓冲怎么控制、切片怎么生成、并发上来怎么扛。SRS 把这些都封装好了,你要做的只是启动服务、配置协议、然后推流拉流。它支持的功能包括直播、录制、转码、鉴权、集群,甚至能对接 WebRTC 的 SFU 场景,很多商业产品的原型都是用 SRS 快速搭出来的。

1.2 为什么用 Docker 部署而不是直接装二进制

SRS 官方提供了编译好的二进制包,也可以从源码编译,但对于大多数场景,Docker 部署的优势非常明显。

首先是环境隔离。SRS 依赖一些系统库和特定的运行环境,如果用二进制部署,你需要自己处理依赖关系——比如在 CentOS 上缺这个包、在 Ubuntu 上缺那个库,一上午就浪费在装依赖上了。Docker 镜像把这些都打包好了,拉下来就能跑,省掉的不是几分钟,而是好几天的环境折腾。

其次是版本管理。升级 SRS 只需要换一个镜像 tag,然后重建容器。如果用二进制部署,升级意味着停服、替换文件、重新配置,出错的概率高很多。Docker 的方式是声明式的,你写清楚用哪个版本,跑起来就是这个版本,回滚也简单。

还有一个实际好处是清理方便。测试完不想用了,一条docker rm -f srs就干干净净,不会在系统里留下残留文件。对于经常做实验、搭原型的人来说,这种零负担的试用体验很重要。

1.3 什么场景适合这套方案

SRS + Docker 的组合适用于这些情况:

  • 要做直播产品的 MVP 验证,先跑通推拉流流程,确认产品形态。
  • 企业内部培训、活动直播,需要临时搭一个流媒体服务。
  • 想在自己的产品里集成音视频能力,但还不想引入昂贵的商业云服务。
  • 学习流媒体原理,想通过实际操作理解 RTMP、HLS、WebRTC 这些协议是怎么工作的。

不适用的情况也有:如果你的业务对延迟、并发、稳定性有极高的要求,而且团队没有专门维护流媒体服务的能力,那直接用云厂商的直播服务会更稳妥。自建 SRS 意味着你要自己负责监控、扩容、故障恢复,这些事情在业务初期容易被低估。

2. 部署前的准备:镜像、端口、目录规划

2.1 拿到 SRS 镜像的正确姿势

SRS 官方镜像发布在 Docker Hub 上,镜像名是ossrs/srs。在写这篇文章的时候,SRS 最新的稳定大版本是 5.x,相关命令我都会基于这个版本来说明。

拉镜像的命令很简单:

docker pull ossrs/srs:5

如果你在国内服务器上拉取 Docker Hub 镜像比较慢,可以配置镜像加速器,或者直接使用阿里云容器镜像服务上的同步镜像。这里不展开讲加速器怎么配,但要提醒一句:镜像源配置属于基础环境问题,最好在部署前就调通,免得后面每次拉镜像都卡住。

镜像拉下来之后,可以用docker image inspect ossrs/srs:5查看镜像的详细信息,比如默认的工作目录、暴露的端口等。对于 SRS 5 来说,镜像默认的工作目录是/usr/local/srs,配置文件在conf/srs.conf,日志在objs/srs.log,这些路径后面都会用到。

2.2 端口规划:基础端口和它们的用途

SRS 涉及的协议不少,每个协议对应不同的端口,部署前最好把端口规划想清楚,不然跑起来之后再来改配置,容易把自己绕晕。

端口协议用途
1935RTMP接收 RTMP 推流和 RTMP 拉流
1985HTTP API提供管理接口,比如查询流状态
8080HTTP提供 HTTP-FLV、HLS 拉流和 Web 管理页面
8000/udpWebRTCWebRTC 媒体传输端口

需要注意,WebRTC 使用的 UDP 端口默认是 8000,并且会根据并发播放情况动态扩展,SRS 默认配置里rtc_serverport设置为 8000,如果并发高,可以配置一个端口范围,比如 8000 到 8100。在生产环境做网络策略时,这些 UDP 端口经常被遗忘,导致 WebRTC 推拉流失败,这是非常典型的问题,后面在排查部分会专门讲。

2.3 目录挂载与配置管理

Docker 部署虽然方便,但容器是临时的,如果配置和数据都存在容器内部,容器删除之后就全没了。所以我会习惯性把配置目录和日志目录挂载到宿主机上。

对于 SRS 来说,最值得挂载的是conf目录,因为你会需要修改srs.conf来做各种自定义配置。日志目录我也会挂载出来,方便排查问题。

mkdir -p /data/srs/conf mkdir -p /data/srs/logs

挂载的方式在下一节启动命令里会体现。这里想强调的是,配置文件的修改是 SRS 运维的关键操作,挂载到宿主机之后,你可以直接在宿主机上用vimnano编辑配置,改完重启容器即可生效,不用进入容器操作。如果需要保留录制文件,那还需要规划一个录制文件的存储目录,同样挂载出来。

3. 从零到一:用 Docker 快速跑起一个可用平台

3.1 最简单的启动命令

SRS 的默认配置已经包含了一套可用的基础设置,包括 RTMP、HTTP-FLV、HLS 的推拉流支持。第一次启动不需要改任何配置,直接用默认配置跑起来就行。

docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ -v /data/srs/conf:/usr/local/srs/conf \ -v /data/srs/logs:/usr/local/srs/objs \ ossrs/srs:5

启动之后,用下面的命令确认容器状态:

docker ps | grep srs

如果状态是Up,说明服务已经起来了。这时可以访问http://你的服务器IP:8080,如果能看到 SRS 的默认页面,说明 HTTP 服务正常。

这里有个细节:把/usr/local/srs/objs挂载到宿主机的/data/srs/logs,不仅日志会写到宿主机,录制文件默认也会写到这个目录下面,所以挂载的是 objs 目录而不是单独某个日志文件。

3.2 推流测试:用 ffmpeg 模拟一路直播信号

服务启动之后,第一件要做的事就是推流测试。没有真实摄像头和麦克风没关系,用 ffmpeg 可以很方便地生成一路测试信号。

如果你本地没有 ffmpeg,先装一下,macOS 用brew install ffmpeg,Ubuntu 用apt install ffmpeg,Windows 可以去官网下安装包。

推流命令可以这样写:

ffmpeg -re -f lavfi -i testsrc2=size=1280x720:rate=30 -f lavfi -i sine=frequency=1000:sample_rate=44100 -c:v libx264 -preset ultrafast -tune zerolatency -c:a aac -f flv rtmp://127.0.0.1:1935/live/test

这条命令的含义是:用 ffmpeg 生成一路 1280x720、每秒 30 帧的测试画面,加一路 1kHz 的正弦波音频,编码成 H.264 和 AAC,然后通过 RTMP 协议推到本地的 SRS 服务,推流路径是live/test

推流开始后,终端会不断输出编码日志,看到类似frame=fps=的输出就说明正在推流。这时打开另一个终端窗口,用 API 查一下流状态:

curl http://127.0.0.1:1985/api/v1/streams

如果返回的 JSON 里有stream字段,且 name 是test,说明 SRS 已经成功接收了这路流。

3.3 拉流播放:RTMP、HTTP-FLV、HLS 三种播放方式对比

流推上来了,接下来就是拉流观看。SRS 默认支持三种主流的播放协议,各有特点。

RTMP 拉流:地址是rtmp://你的服务器IP:1935/live/test。RTMP 基于 TCP,延迟中等,大约在 1-3 秒,兼容性不错,很多老牌播放器都支持。

HTTP-FLV 拉流:地址是http://你的服务器IP:8080/live/test.flv。HTTP-FLV 的特点是通过 HTTP 传输 FLV 格式的数据,兼容性好且容易穿透防火墙,延迟也控制在 1-3 秒,是目前 Web 端播放最常用的方式。

HLS 拉流:地址是http://你的服务器IP:8080/live/test.m3u8。HLS 会把流切成一个个小切片文件,播放器按顺序加载,延迟通常在 5-15 秒,但优势是稳定性和兼容性最好,几乎所有平台都能播。

验证播放效果,最省事的方式是用 VLC 播放器:打开 VLC,按Ctrl+N,输入上面的地址,点播放。也可以用 ffplay:

ffplay http://你的服务器IP:8080/live/test.flv

如果画面和声音都正常,说明这一整套推拉流链路已经通了。到这里,一个最基础的直播平台就已经跑起来了,从零到一整个过程不超过十分钟。

3.4 通过 API 和日志确认服务状态

前面提到用 API 查流状态,这里再补充几个有用的接口。

SRS 的 HTTP API 默认监听在 1985 端口,常用的接口有:

  • GET /api/v1/versions:查看 SRS 版本信息。
  • GET /api/v1/summaries:查看运行统计,包括内存、CPU、网络等。
  • GET /api/v1/streams:查看当前所有活跃的流。
  • GET /api/v1/clients:查看当前连接的客户端。

这些接口在排查问题时非常有用,比如同时有几十路流推上来,你想确认某一路是否在线,直接查 streams 接口就行。

日志方面,SRS 的日志默认会输出到挂载的 objs 目录下,文件名为srs.log。日志级别默认是trace,信息量很大,包括每一条流的推拉事件、连接建立和断开记录。用tail -f实时查看日志是排查问题的基本操作:

tail -f /data/srs/logs/srs.log

4. 进阶配置:WebRTC、鉴权、转码与更多玩法

4.1 开启 WebRTC:把延迟压到 500ms 以内

RTMP 和 HLS 虽然能满足大部分直播需求,但它们有一个共同的短板:延迟偏高。RTMP 大约 1-3 秒,HLS 更是有 5-15 秒的延迟。如果要做视频连麦、在线课堂这种强互动场景,这个延迟是不可接受的。这时候就要上 WebRTC。

WebRTC 基于 UDP 传输,延迟可以做到 500 毫秒以内,SRS 对 WebRTC 的支持非常完整,既支持 WebRTC 推流,也支持 WebRTC 拉流。

默认配置下 SRS 已经启用了 WebRTC 监听,但我们还需要做两件事:一是确保 UDP 端口(默认范围 8000-8100)在防火墙里放行;二是确认 SRS 配置里的rtc_servercandidate参数指向的是服务器公网 IP 或内网可达 IP。

如果直接用默认配置,SRS 会自动探测本机 IP,但多网卡机器上经常探测到不正确的 IP,导致 WebRTC 握手失败。这时候需要手动在配置里指定 candidate:

rtc_server { enabled on; listen 8000; # 重点:改为你的服务器实际 IP candidate 192.168.1.100; }

改完配置后重启容器,WebRTC 播放地址可以在 SRS 自带的播放器页面测试:

http://你的服务器IP:8080/players/webrtc.html?app=live&stream=test

打开这个页面,点击播放,如果画面秒开且延迟极低,说明 WebRTC 已经调通了。

4.2 给流媒体服务加上鉴权,防止被刷流量

自建流媒体服务最怕的一件事就是被人发现地址后盗用带宽。SRS 提供了多种鉴权方式,最常用的是 HTTP 回调鉴权和 URL 防盗链。

HTTP 回调鉴权的思路是:在推流或拉流的时候,SRS 先把请求发给你自己的鉴权服务,你的服务返回 0 表示允许,返回非 0 表示拒绝。这适合已有用户体系的场景,比如你想只有登录用户才能推流。

配置方式是在srs.conf里添加回调配置:

http_hooks { enabled on; on_publish http://你的业务服务器:端口/auth/publish; on_play http://你的业务服务器:端口/auth/play; }

URL 防盗链的思路是:在推流地址或拉流地址上附加一个 token 参数,SRS 根据配置的密钥和过期时间校验 token。适合一些临时授权的场景。

vhost __defaultVhost__ { play_token_secret your_secret_key; publish_token_secret your_secret_key; }

配置好之后,RTMP 地址就要带上 token:

rtmp://192.168.1.100:1935/live/test?token=你的加密串&expire=过期时间

token 的计算规则是 md5(流名字 + 过期时间戳 + 密钥),具体算法文档里有详细说明。鉴权这块要花些时间,但很有必要,否则一旦地址泄露,服务带宽会被白白消耗。

4.3 转码与多码率输出

默认情况下 SRS 只做协议转封装,不对视频流做转码——也就是说,你推上来的是 4K 超高清,观众看到的也是 4K,而且就算某个观众的网速只有 2Mbps,他也必须下载 4K 的码率。这在真实场景中会带来极大的播放卡顿。为了照顾不同网络条件的观众,我们需要在服务器端做转码,输出多档码率。

SRS 的转码功能基于 FFmpeg 实现,内置了转码模块。下面是一个简单的转码配置,把原始流转成 720p 和 480p 两路:

vhost __defaultVhost__ { transcode { enabled on; ffmpeg { output rtmp://127.0.0.1:1935/[app]/[stream]_sd; engine { enabled on; vcodec libx264; vbitrate 1000k; vwidth 1280; vheight 720; } } } }

转码是 CPU 密集操作,尤其你同时开多路转码的时候,对服务器计算资源的消耗会非常明显。处理不好,服务很容易被拖垮。这里有一个实际建议:如果业务没有硬性要求,优先把转码放在云端处理,或者只对高码率的源流做一次转码,生成一个低码率备份流,不要无条件地对所有流都开转码。生产环境中我见过不少因为转码开太多导致 SRS 进程 CPU 打满、所有流都卡死的案例,加资源不如先想清楚业务需求。

4.4 用 docker-compose 固化你的整套配置

直接用docker run命令部署适合测试,但如果要把这套服务固化下来,比如提交到 Git 仓库,或者在新的服务器上快速重建,最好用 docker-compose。docker-compose 可以把端口映射、目录挂载、环境变量、网络配置都写在一个文件里。

下面是一个日常使用的docker-compose.yml示例:

version: '3' services: srs: image: ossrs/srs:5 container_name: srs restart: always ports: - "1935:1935" - "1985:1985" - "8080:8080" - "8000:8000/udp" - "8001:8001/udp" - "8002:8002/udp" volumes: - /data/srs/conf:/usr/local/srs/conf - /data/srs/logs:/usr/local/srs/objs

写好之后,一条命令就能启动整个服务:

docker-compose up -d

用 docker-compose 还有一个好处:你可以同时编排多个服务。比如你的业务需要一个回调鉴权服务,那你可以在同一个 compose 文件里定义 SRS 和你自己的鉴权服务,两个容器在同一个 Docker 网络里,可以直接用服务名互相访问,省去了配置内网 IP 的麻烦。

5. 踩坑实录与问题排查技巧

5.1 容器启动失败或端口冲突

如果docker run之后容器立刻退出,最常见的两个原因是端口被占用和配置文件语法错误。

端口被占用的情况很好排查:

netstat -tlnp | grep 1935

看到有进程占用,要么改用其他端口,要么停掉占用进程。

配置文件语法错误的排查方式是把容器日志拉出来看:

docker logs srs

SRS 的日志里会明确写出是哪一行配置有问题,按提示修改后重启容器即可。

5.2 推流成功但拉流黑屏

这种问题很常见。ffmpeg 推流命令正常输出日志,API 也能查到流,但播放器就是黑屏。很大概率是编码参数和播放器不兼容。

具体来说,SRS 默认配置里对 HLS 的切片格式有要求,如果推上来的是 B 帧较多的编码流,可能导致部分播放器无法解码。解决方法是推流端在编码时加上-bf 0参数,禁用 B 帧,并加上-gop_size设置关键帧间隔。我常用的推流命令会这样写:

ffmpeg -re -f lavfi -i testsrc2=size=1280x720:rate=30 -f lavfi -i sine=frequency=1000:sample_rate=44100 -c:v libx264 -preset ultrafast -bf 0 -g 60 -c:a aac -f flv rtmp://127.0.0.1:1935/live/test

另一个黑屏原因是 HLS 切片还没有生成好。HLS 播放需要先有完整的切片文件,推流开始后大约要等 5-10 秒才能播放。用 VLC 打开 HLS 地址,如果提示 404 或者找不到资源,多半是切片还没就绪,多等几秒再试。

5.3 WebRTC 不通,十有八九是端口和 IP 问题

WebRTC 是踩坑重灾区,我见过的失败案例里,九成以上出在两层地方。

第一层是防火墙或安全组没放行 UDP 端口。RTMP 和 HTTP 是 TCP 端口,很多运维人员都很熟悉,但在云服务器的安全组里,UDP 端口经常被遗漏。WebRTC 使用 UDP 传输媒体数据,UDP 8000-8100 这些端口必须放行。在云服务器的控制台检查一下安全组入向规则,同时也检查服务器本地的防火墙,这在部分操作系统里可能是独立的另一道关卡。

第二层是 candidate 地址配错。SRS 需要知道自己的对外 IP,如果配置的 candidate 是内网 IP,而访问者在公网,WebRTC 的 SDP 协商就会失败。遇到 WebRTC 播放不了,优先检查两件事:确认 UDP 端口能通,确认 candidate 是客户端能访问到的 IP。

判断 UDP 端口是否通的简单方法,在服务器上抓包看有没有入向的 UDP 包:

tcpdump -i any udp port 8000

如果是公网访问,至少要能看到正常的数据包交互。

5.4 磁盘暴涨与日志清理

SRS 运行时间长了,两个地方会特别吃磁盘:日志文件和 HLS 切片。

日志文件在objs/srs.log,虽然单条日志不大,但并发量上来之后,几 GB 的日志文件很容易出现。SRS 本身有日志轮转机制,但如果你用的是挂载到宿主机的 objs 目录,需要额外确认轮转是否正常。

HLS 切片是另一个容易忽视的磁盘杀手。默认配置下,HLS 切片会不断生成,旧切片会被清理,但清理逻辑依赖配置项。如果你在测试环境频繁推流、频繁停止,偶尔会出现残留。最好的办法是给录制和切片目录配置独立挂载,并定期用 cron 做清理,避免磁盘被打满导致 SRS 写不了切片直接挂掉。

这里分享一个我自己的小经验:上线前就把磁盘告警配置好,磁盘使用率超过 80% 就通知人处理。流媒体服务一旦磁盘满,表现是流突然全部断掉,而且容器不会自动恢复,恢复时需要手动清理磁盘再重启,中间的业务影响是实实在在的。

6. 从部署到维护的心得

整套流程走下来,SRS 与 Docker 的组合给我的感觉是:上手门槛确实低,但真正要跑得稳,还需要对协议和底层机制有足够理解。Docker 帮你省掉了环境问题,但流媒体服务本身的容错和监控,是你自己需要承担的。

我个人在实际项目中总结出的经验大致是这样:第一,部署规范要早定——端口、目录、命名这些尽量一次性规划好,后面换方案的成本远高于一开始多想几分钟的成本;第二,监控是自建流媒体必备的配套设施——SRS 自带 API 提供了足够的指标,接入一套简单的告警并不复杂;第三,升级前先看 release notes——SRS 迭代快,一些小版本之间配置格式会变化,贸然升级老配置不一定兼容。

如果你只是做技术验证,这篇文章里的内容完全够用了。如果你要把 SRS 用在正式业务中,建议除了部署之外,再花时间研究一下集群方案和边缘节点设计。SRS 支持 Origin 和 Edge 架构,可以做到分发层面的横向扩展,这是在并发规模增长后必须考虑的方向。

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

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

立即咨询