最近帮一位朋友折腾直播推流,他家里老人过生日,想搞一个私人的实时音视频直播,一大家子人远程看。他没接触过流媒体这块,又想快速跑起来,我想都没想就推荐了 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 端口和防火墙策略同样重要。如果这篇文章能帮你少走一两个这样的弯路,那就算是值了。

Logo

邀请您加入社区

更多推荐