
在直播、音视频互动相关的项目里SRSSimple 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_server的port设置为 8000如果并发高可以配置一个端口范围比如 8000 到 8100。在生产环境做网络策略时这些 UDP 端口经常被遗忘导致 WebRTC 推拉流失败这是非常典型的问题后面在排查部分会专门讲。2.3 目录挂载与配置管理Docker 部署虽然方便但容器是临时的如果配置和数据都存在容器内部容器删除之后就全没了。所以我会习惯性把配置目录和日志目录挂载到宿主机上。对于 SRS 来说最值得挂载的是conf目录因为你会需要修改srs.conf来做各种自定义配置。日志目录我也会挂载出来方便排查问题。mkdir -p /data/srs/conf mkdir -p /data/srs/logs挂载的方式在下一节启动命令里会体现。这里想强调的是配置文件的修改是 SRS 运维的关键操作挂载到宿主机之后你可以直接在宿主机上用vim或nano编辑配置改完重启容器即可生效不用进入容器操作。如果需要保留录制文件那还需要规划一个录制文件的存储目录同样挂载出来。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 ffmpegUbuntu 用apt install ffmpegWindows 可以去官网下安装包。推流命令可以这样写ffmpeg -re -f lavfi -i testsrc2size1280x720:rate30 -f lavfi -i sinefrequency1000:sample_rate44100 -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按CtrlN输入上面的地址点播放。也可以用 ffplayffplay 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.log4. 进阶配置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_server的candidate参数指向的是服务器公网 IP 或内网可达 IP。如果直接用默认配置SRS 会自动探测本机 IP但多网卡机器上经常探测到不正确的 IP导致 WebRTC 握手失败。这时候需要手动在配置里指定 candidatertc_server { enabled on; listen 8000; # 重点改为你的服务器实际 IP candidate 192.168.1.100; }改完配置后重启容器WebRTC 播放地址可以在 SRS 自带的播放器页面测试http://你的服务器IP:8080/players/webrtc.html?applivestreamtest打开这个页面点击播放如果画面秒开且延迟极低说明 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 地址就要带上 tokenrtmp://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 srsSRS 的日志里会明确写出是哪一行配置有问题按提示修改后重启容器即可。5.2 推流成功但拉流黑屏这种问题很常见。ffmpeg 推流命令正常输出日志API 也能查到流但播放器就是黑屏。很大概率是编码参数和播放器不兼容。具体来说SRS 默认配置里对 HLS 的切片格式有要求如果推上来的是 B 帧较多的编码流可能导致部分播放器无法解码。解决方法是推流端在编码时加上-bf 0参数禁用 B 帧并加上-gop_size设置关键帧间隔。我常用的推流命令会这样写ffmpeg -re -f lavfi -i testsrc2size1280x720:rate30 -f lavfi -i sinefrequency1000:sample_rate44100 -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 架构可以做到分发层面的横向扩展这是在并发规模增长后必须考虑的方向。