Docker部署SRS流媒体服务器:从零搭建实时音视频平台
2026/9/16 3:54:55 网站建设 项目流程

做实时音视频这几年,如果只让我选一个开源流媒体服务器,我会毫不犹豫推荐 SRS。Docker 部署 SRS 如今已经是搭建实时音视频流媒体平台最主流的玩法之一,容器化之后部署成本低到离谱,项目本身又足够活跃,遇到问题基本都能在社区找到答案。

这篇博文把我从零开始用 Docker 跑起 SRS 的全过程记录下来,包括为什么选 SRS 而不是 Nginx-RTMP、端口到底怎么开、配置文件怎么挂载、推流拉流怎么验证,以及我在实战中踩过的坑。不管你是刚接触流媒体的小白,还是已经在用其他方案想换过来的老手,这篇文章都能直接拿来抄作业。

1. 做实时音视频,为什么选择 SRS

1.1 先搞清楚 SRS 到底是什么

SRS 全称 Simple Realtime Server,是一个开源的实时流媒体服务器项目。它的核心能力就一句话:把音视频流收进来、转一下、再发出去。听起来简单,但做到极致并不容易,尤其是同时支持 RTMP、HLS、WebRTC、SRT、GB28181 这么多种协议,还能保持低延迟和高并发,这在开源圈里非常少见。

SRS 最初是从 RTMP 直播场景起家的,后来不断扩展,现在已经是国内开源流媒体服务器里生态最完整的项目之一。它的代码托管在 GitHub 上,star 数量相当可观,社区活跃度也高,winlin 等核心开发者常年在线回答 issue。我用了这么久的一个体会是,SRS 的文档虽然有些地方写得比较跳跃,但只要你愿意读,几乎每个配置项都有对应的场景说明,这在开源项目里算非常良心了。

那为什么偏偏要强调用 Docker 来部署 SRS?因为 SRS 本身是 C++ 写的,源码编译安装需要处理一堆依赖,比如 OpenSSL、FFmpeg、libsrtp 等等,稍有版本不匹配就编不过去。Docker 镜像把这些全打包好了,拉下来就能跑,省掉的不仅是编译时间,更是排查依赖问题的时间。

1.2 对比 Nginx-RTMP、ZLMediaKit,SRS 赢在哪

很多人第一次接触流媒体服务器,可能都是从 Nginx-RTMP 模块开始的。我早年也用过一段时间,它的配置确实简单,一个 rtmp 块就搞定推流。但用久了就会发现几个痛点:Nginx 官方已经不维护 RTMP 模块了,项目基本处于半停滞状态;WebRTC 支持等于没有,想做低延迟浏览器播放就得另起炉灶;HLS 切片虽然能做,但配置灵活性一般。

ZLMediaKit 是另一个很优秀的项目,性能和协议支持都很强,但它的上手门槛比 SRS 高一些,配置方式和周边工具链没有 SRS 那么完善。如果只是常规的直播、录播、低延迟播放场景,SRS 的开箱即用体验是最好的。

SRS 的差异化优势有这么几点:第一,WebRTC 支持做得非常顺滑,配合 WHIP/WHEP 协议,浏览器推流拉流的延迟可以压到 500 毫秒左右;第二,API 接口完善,通过 HTTP 接口就能查询服务器状态、踢流、获取流列表,方便二次开发;第三,Docker 镜像官方维护,升级和回滚都非常方便。所以我的结论是,如果你需要一个通用型实时音视频流媒体平台,SRS 是当前开源方案里的最优解之一。

2. Docker 部署 SRS 前的准备

2.1 环境要求与版本选择

在跑 SRS 之前,先确认你的 Docker 环境是好的。我在排查过不少“容器起不来”的问题后发现,很多其实不是 SRS 的锅,而是 Docker 本身的权限、虚拟化、网络问题。

首先确认 Docker 版本。建议用 Docker Engine 20.10 以上,老版本对容器网络和资源限制的支持不够好。执行docker version看 Client 和 Server 的版本,两个都有输出说明 Docker 守护进程跑起来了。如果你在 Linux 上用docker ps遇到 permission denied,那是当前用户没加入 docker 用户组,执行sudo usermod -aG docker $USER然后重新登录就行。

其次是镜像版本选择。SRS 官方镜像的命名规则是ossrs/srs,tag 有654等主要版本。我强烈建议直接用ossrs/srs:6,因为 SRS 6.0 在 WebRTC、SRT、GB28181、DVR 录播等方向都做了大量改进,尤其是 WebRTC 相关能力,5.0 和 6.0 的差距不是一点半点。

还要注意一下你的硬件架构。SRS 官方镜像支持 amd64 和 arm64,树莓派或者各类 ARM 开发板也能跑,只是部分高级功能(比如某些硬件编码加速)在 ARM 上支持不太好。如果只是软件转码或者直接转发流,ARM 完全没问题。

2.2 端口规划:这一节不看肯定踩坑

SRS 的端口规划是整个部署过程中最容易被忽略、也最容易出问题的地方。很多人容器起来了,结果推流失败,最后发现是端口没放通。

SRS 默认涉及这几个端口:

端口协议用途
1935TCPRTMP 推流和拉流
1985TCPHTTP API 接口,用于查询状态和管理
8080TCPHTTP 服务,提供 HLS、DASH 播放和简单演示页面
8000UDPWebRTC 推流(SRTP)
8001UDPWebRTC 拉流(SRTP)

在 Docker 部署的时候,这些端口都要映射到宿主机。尤其要注意 8000 和 8001 是 UDP 端口,写-p参数时必须显式带上udp关键字,否则默认只映射 TCP,WebRTC 肯定不通。

如果你在云服务器上部署,除了 Docker 的端口映射,还要去云控制台的安全组里把对应端口放开。我曾经排查过一个用户的 WebRTC 问题,Docker 映射没问题、防火墙也放行了,结果最后发现是安全组只开了 TCP,UDP 全被挡了。这种问题非常隐蔽,报错还容易误导人,所以建议动手部署之前,先把端口规划写在纸上。

2.3 配置文件和数据目录要提前想好

SRS 的默认配置可以直接用,但生产环境一般都要改。官方镜像里默认配置文件路径是/usr/local/srs/conf/srs.conf,日志和数据输出目录是/usr/local/srs/objs/

我建议在宿主机上先创建好配置挂载目录,后面修改配置就不用重新构建镜像了。例如:

mkdir -p /data/srs/conf mkdir -p /data/srs/objs

然后把你自己的srs.conf放到/data/srs/conf/下,启动容器的时候用-v参数挂载进去。这里有个小细节需要注意:宿主机目录的权限。如果挂载后 SRS 容器内无法写入日志或者 DVR 文件,通常是目录的用户 ID 和容器内进程的用户 ID 不匹配。SRS 官方镜像默认以 root 运行(dev 模式),所以一般权限问题不多,但如果你用了自定义启动参数或者非 root 容器,就要留意一下。

数据目录则要看你的业务场景。如果开启了 HLS,切片文件默认写在/usr/local/srs/objs/nginx/html下;如果开启了 DVR 录播,录制文件写在/usr/local/srs/objs/下。这些目录都要挂载出来,不然容器一删,所有录制内容全没了。

3. 一步步启动 SRS 容器

3.1 先来一条最简单的 docker run 命令

很多教程一上来就让你写 docker-compose,但对于第一次部署的人来说,用一条docker run命令把服务跑起来,能最快建立直观感受。

最简单的启动命令长这样:

docker run -d --name srs \ -p 1935:1935 \ -p 1985:1985 \ -p 8080:8080 \ -p 8000:8000/udp \ -p 8001:8001/udp \ ossrs/srs:6

-d表示后台运行,--name srs给容器起个名字,后面管理起来方便。端口映射有一条算一条,缺哪个后续哪个功能就不好使。跑完执行docker logs srs看一下输出,如果能看到类似SRS is running或者版本信息,说明容器已经正常启动了。

这个时候你可以先做个快速验证:在浏览器里访问http://你的服务器IP:8080,如果能看到 SRS 的默认演示页面,说明 HTTP 服务已经通了。页面虽然简陋,但意义重大——它说明 SRS 进程活着,端口映射对了,网络链路是通的。

3.2 Docker Compose:项目化部署的正确姿势

生产环境我从来不靠裸docker run维护服务,写一份docker-compose.yml,无论是参数管理还是服务编排都清晰得多。而且 SRS 往往不是孤立部署的,你可能还要同时起 Nginx、Redis、MySQL,用 Compose 统一管理才是正确姿势。

下面是我在项目里用的一份基础配置:

version: "3.8" services: srs: image: ossrs/srs:6 container_name: srs restart: always ports: - "1935:1935" - "1985:1985" - "8080:8080" - "8000:8000/udp" - "8001:8001/udp" volumes: - /data/srs/conf/srs.conf:/usr/local/srs/conf/srs.conf - /data/srs/objs:/usr/local/srs/objs environment: - TZ=Asia/Shanghai

restart: always非常关键,它保证 Docker 守护进程重启或者宿主机重启后,SRS 容器能自动拉起来。TZ=Asia/Shanghai设置时区,避免日志时间和本地时间对不上。

配置写好后执行:

docker compose up -d

如果docker compose命令不存在,说明你的 Docker 版本比较老,需要先升级 Docker 或者用docker-compose(带连字符)这个旧版本命令。

3.3 用自定义 srs.conf 替换默认配置

官方默认配置适合跑通流程,但如果你要做 HLS 切片、开启 WebRTC、改端口、加鉴权,就得自己写配置文件。

我先把一份带 HLS 和 WebRTC 的最小配置贴出来:

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; # WebRTC over TCP, not necessary for UDP } vhost __defaultVhost__ { rtc { enabled on; } hls { enabled on; hls_path ./objs/nginx/html; hls_fragment 5; hls_window 30; } http_remux { enabled on; mount [vhost]/[app]/[stream].flv; } }

这份配置我实际用过,跑直播和回放都够用。几个参数重点说一下:

hls_fragment 5表示切片文件每个 5 秒,hls_window 30表示时间窗口 30 秒,也就是最多保留最近 6 个切片。如果你要做低延迟直播,不想用 HLS,那就把hls这个段落注释掉,直接用http_remux输出 FLV 流,播放器用 flv.js 就行。

写好配置后,挂载进容器并重启:

docker compose restart srs

如果配置语法有问题,SRS 会直接把错误打在日志里。我踩过一次坑是配置文件里少了daemon off;,导致容器启动后 SRS 进程立刻进入后台运行,但 Docker 的前台进程找不到存活进程,容器就反复重启。这个参数务必保留。

4. 验证流媒体服务:推流拉流完整流程

4.1 用 FFmpeg 推流测试

服务起来了,配置也挂载了,接下来最关键的一步是验证链路通不通。最直接的方式就是用 FFmpeg 推一路流到 SRS。

首先确认本机装了 FFmpeg。没装的话,Ubuntu 执行sudo apt install ffmpeg,macOS 执行brew install ffmpeg,Windows 可以下载官方编译版或者用包管理器。

找一个视频文件,执行:

ffmpeg -re -i test.mp4 -c copy -f flv rtmp://你的服务器IP/live/livestream

-re表示按视频原始帧率读取,模拟实时推流效果;-c copy表示不转码,直接复制原始编码数据,省 CPU;rtmp://IP/live/livestream是推流地址,live是应用名,livestream是流名称,可以随意取。

推流开始后,终端会不断刷新发送速度。看到类似speed=1x的输出,说明推流正常。这时候再验证一下能不能从 SRS 拉流播放。

4.2 拉流播放验证 HLS 和 HTTP-FLV

播放验证我推荐用 VLC,跨平台且不需要额外插件。打开 VLC,选择“打开网络串流”,输入以下地址:

http://你的服务器IP:8080/live/livestream.m3u8

如果配置了 HLS,这个地址能直接播放,延迟大概在 5 到 10 秒之间,属于正常水平。想更低延迟就改用 HTTP-FLV 地址:

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

VLC 对 FLV 的支持没有 HLS 那么好,偶尔会出现有声音没画面或者打不开的情况,遇到这种情况我建议直接用网页播放器测。SRS 默认的演示页面里有一组测试播放器,你把流地址填进去,如果页面里的播放器能出画面,那说明 HTTP-FLV 链路没问题。

WebRTC 的验证稍微麻烦一点,SRS 提供了 WHIP 协议,地址一般是:

http://你的服务器IP:1985/rtc/v1/whip/?app=live&stream=livestream

不过 WebRTC 最好用官方的在线测试工具或者集成到自己的网页里测试,单纯用 VLC 是测不了的。

4.3 用 API 接口确认服务器状态

SRS 有一组 HTTP API,这是它的一个很大优势。部署完最好花两分钟把这些接口都试一遍,后续排查问题都用得上。

浏览器访问:

http://你的服务器IP:1985/api/v1/versions

正常情况下会返回一个 JSON,里面包含 SRS 的版本号、启动时间等信息。再访问:

http://你的服务器IP:1985/api/v1/streams

就能看到当前服务器上所有活跃的流,包括流名称、客户端数量、推流地址这些信息。这个接口在排查“流到底有没有上来”这种问题时特别好用,比翻日志快多了。

有些老版本 API 的路径略有差异,如果返回 404,可以访问http://你的服务器IP:1985/api/v1/看一眼 API 列表。

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

5.1 推流失败(握手超时)怎么解决

推流失败是最常见的问题,现象是 FFmpeg 一直卡在Handshaking然后报Connection timed out。遇到这种情况,我的排查顺序是固定的。

先确认端口通不通:

telnet 你的服务器IP 1935

通则显示Connected,不通则卡住或者报错。如果 1935 端口不通,99% 是端口没映射或者防火墙/安全组没放行。然后再确认 SRS 日志,执行docker logs --tail 50 srs,看看有没有收到来自你这台机器的连接请求。如果在日志里看到了连接但握手失败,可能是 RTMP 推流地址格式不对,检查一下是不是少了live应用名。

还有一个小概率问题:推流机器的系统时间不对。RTMP 握手对时间戳比较敏感,时间差太大会握手失败。

5.2 Docker 日志怎么高效查看

SRS 容器运行中,调试信息基本都在日志里。我常用的命令是:

# 查看最近100行日志 docker logs --tail 100 srs # 实时跟踪日志输出 docker logs -f srs # 按时间过滤 docker logs --since 5m srs

不过要注意,SRS 配置文件里srs_log_tank决定日志输出到哪里。如果写成file,日志会写到 SRS 自己的日志文件里,docker logs就看不到。调试阶段建议像我上面的配置一样,写成console,让 Docker 直接收集标准输出,排查问题最方便。

5.3 宿主机重启后容器不自动启动

很多人部署完 SRS 觉得万事大吉,结果服务器重启了一次,发现服务回不来。这个极大概率是因为启动容器时没有设置restart策略。

docker run启动的话,加参数--restart always;用 Compose 的话,在 service 下写restart: always。这个没啥好说的,属于基础习惯问题,但在实际项目里就是有大量人漏掉。

如果已经启动的容器没加这个参数,又不想重新创建容器,可以执行:

docker update --restart always srs

5.4 常见问题速查表

问题可能原因解决方案
容器反复重启配置文件缺少daemon off;在 srs.conf 开头加daemon off;
1935 端口连不上端口未映射或防火墙拦截检查 docker 端口映射和安全组放行
WebRTC 连不上8000/8001 UDP 端口未放行确认映射的是 UDP 协议,安全组同步放开
HLS 播放打不开未开启 hls 配置或端口被占用检查 srs.conf 中 hls 配置,确认 8080 端口映射
Docker 权限报错用户未加入 docker 组sudo usermod -aG docker $USER后重新登录
Docker Desktop 虚拟化检测失败BIOS 中虚拟化技术未开启重启进 BIOS,开启 Intel VT-x 或 AMD SVM
镜像拉取慢网络原因给 Docker 配置 registry-mirrors 加速器,选择可访问的镜像源

如果你同时用 Docker Desktop 在 Windows/macOS 上跑 SRS,Windows 下比较容易遇到 Hyper-V 或者 WSL2 相关的问题。SRS 镜像本身没有问题,问题基本都出在 Docker 环境上。遇到 Docker Desktop 启动失败,优先检查 BIOS 里的虚拟化开关,这个在热搜词里出现频率很高,说明确实是大众难题。

5.5 一个隐蔽的坑:HLS 文件权限与目录挂载

最后分享一个我真正踩过的坑。当时我在服务器上用 Docker 部署 SRS,开启 HLS 录播,推流一直正常,但播放 m3u8 时始终 404。翻日志发现切片文件写不进去,报的是权限错误。

排查后发现,宿主机上创建的/data/srs/objs/nginx/html目录属主是 root,而 SRS 容器内进程没有写权限。解决方法是直接在宿主机上调整目录属主:

chown -R 0:0 /data/srs/objs

或者更简单粗暴一点,直接chmod -R 777 /data/srs/objs,反正是内部服务,问题不大。但如果你对安全要求高,建议了解一下容器镜像里 SRS 进程实际使用的 UID 和 GID,再去对应设置宿主机目录的属主。

这个问题的隐蔽之处在于,SRS 推流本身是正常的,没有任何报错,只有 HLS 切片写不进去,导致播放端拿到 m3u8 但里面引用的 ts 文件全都不存在。我当时排查了很久才发现是权限问题,所以特别提醒一下。

实战体会

SRS 是我目前接触到的最适合快速搭建实时音视频平台的服务器,尤其是配合 Docker,十分钟内就能从零跑到推拉流全通。做这个部署的时候,我最大的感受是步骤本身不复杂,真正耗时的是排查各种环境问题:端口没开、UDP 忘映射、目录权限不对、配置文件少了个daemon off。所以这篇文章花了大量篇幅讲排查思路,而不是只给命令。

最后再分享一个小技巧:SRS 的官方镜像里其实内置了多个示例配置,在容器里执行ls /usr/local/srs/conf/就能看到。需要什么场景的配置(比如 WebRTC、SRT、GB28181),直接找到对应的.conf文件,拷出来改改就能用,比自己从零写靠谱得多。这个细节官方文档提得不多,但是真节省时间。

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

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

立即咨询