SRS视频服务器Docker部署:端口映射不一致导致的WebRTC播放失败解析
1. 为什么WebRTC播放会失败?
最近在帮朋友部署SRS视频服务器时遇到一个典型问题:用Docker启动服务后,RTMP推流正常,但WebRTC始终无法播放。经过排查发现,这其实是端口映射不一致导致的经典问题。很多新手在使用Docker部署SRS时都会踩这个坑,今天我就把完整排查过程和解决方案分享给大家。
先说说问题现象:当我们通过docker run -p 1936:1935 -p 8001:8000这样的命令启动容器时,虽然视频能正常录制到宿主机目录,但用SRS自带的播放器测试WebRTC流时,控制台会报"ICE连接失败"的错误。这其实是因为Docker的端口映射机制和WebRTC的协商机制产生了冲突。
2. 端口映射不一致引发的连锁反应
2.1 Docker端口映射的本质
Docker的-p参数实现的是NAT端口转发,其工作流程是这样的:
- 外部请求到达宿主机的1936端口
- Docker引擎将请求转发到容器的1935端口
- 容器内SRS服务处理请求
问题就出在WebRTC的ICE协商阶段。当客户端请求播放时,SRS服务器会根据配置文件中的listen 1935和listen 8000生成SDP描述。这个描述告诉客户端:"请连接我的1935和8000端口"。但客户端实际需要连接的却是宿主机的1936和8001端口,这就导致了连接失败。
2.2 WebRTC的ICE协商过程
WebRTC建立连接时需要完成ICE协商,主要包含这几个步骤:
- 客户端请求播放时,服务器返回SDP描述
- SDP中包含候选地址(candidate)和端口信息
- 客户端尝试与这些地址建立连接
当端口映射不一致时,SDP中的端口(1935/8000)与实际可访问的端口(1936/8001)不匹配,ICE协商就会失败。这就好比有人告诉你"请到301房间找我",但实际他却在302房间等你,自然找不到人。
3. 两种配置方案的对比分析
3.1 错误配置示例
# 错误示范:内外端口不一致
docker run -p 1936:1935 -p 8001:8000/udp ...
对应的SRS配置:
listen 1935;
rtc_server {
listen 8000;
candidate 公网IP;
}
这种配置会导致:
- RTMP推流正常(因为客户端直接使用1936端口)
- 视频录制正常(不依赖端口映射)
- WebRTC播放失败(ICE协商端口不匹配)
3.2 正确配置方案
# 正确做法:保持内外端口一致
docker run -p 1936:1936 -p 8001:8001/udp ...
对应的SRS配置:
listen 1936;
rtc_server {
listen 8001;
candidate 公网IP;
}
关键调整点:
- Docker映射保持内外端口一致
- SRS配置文件改用宿主机端口
- 确保防火墙开放相应端口
4. 完整部署流程与验证
4.1 正确部署步骤
- 启动容器(注意端口一致):
docker run -d --name srs \
-p 1936:1936 -p 1985:1985 \
-p 8080:8080 -p 8001:8001/udp \
-v /path/to/dvr:/usr/local/srs/static/DVR-video \
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4 \
./objs/srs -c conf/rtmp2rtc.conf
- 修改配置文件:
listen 1936;
rtc_server {
enabled on;
listen 8001;
candidate 你的公网IP;
}
- 重启服务使配置生效:
docker restart srs
4.2 效果验证方法
- 推流测试:
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://服务器IP:1936/live/stream
- 播放验证:
- 访问
http://服务器IP:8080/players/rtc_player.html - 输入流地址
webrtc://服务器IP:1936/live/stream - 观察视频是否能正常播放
- 检查ICE连接:
- 浏览器开发者工具查看WebRTC连接状态
- 确认使用的端口是8001而非8000
5. 常见问题排查指南
5.1 端口占用问题处理
如果遇到端口冲突,建议:
- 使用
netstat -tulnp查看端口占用情况 - 选择未被占用的端口组合,例如:
- 1936 → 1936
- 8001 → 8001
- 8081 → 8081
5.2 防火墙配置要点
确保宿主机防火墙放行以下端口:
- TCP: 1936(RTMP)
- UDP: 8001(WebRTC)
- TCP: 1985(HTTP API)
- TCP: 8080(Web管理)
对于云服务器,还需要配置安全组规则。我曾经遇到过因为忘记开安全组UDP端口,排查了整整一个下午的惨痛经历。
5.3 其他可能的问题
- NAT穿透问题:如果服务器位于多层NAT后,需要配置正确的
candidate地址 - TURN服务器:在复杂网络环境下可能需要配置TURN服务器
- SRS版本差异:不同版本配置项可能有细微差别,建议使用最新稳定版
6. 深入理解端口映射机制
6.1 Docker网络模式对比
Docker支持多种网络模式,部署SRS时需要注意:
| 网络模式 | 特点 | 适用场景 |
|---|---|---|
| bridge | 默认模式,NAT转发 | 单机部署 |
| host | 直接使用宿主机网络 | 需要避免端口映射问题 |
| overlay | 多主机网络 | 集群部署 |
对于大多数场景,使用bridge模式并保持端口一致是最佳选择。
6.2 WebRTC端口使用规律
WebRTC通信需要以下端口:
- 3478 UDP:STUN服务
- 49152-65535 UDP:动态分配的媒体端口
- 配置的UDP端口(如8001):应用层通信
因此除了配置的8001端口外,还需要确保服务器的UDP端口范围开放。
7. 高级配置技巧
7.1 多实例部署方案
当需要部署多个SRS实例时,可以这样配置:
# 实例1
docker run -p 1936:1936 -p 8001:8001/udp ...
# 实例2
docker run -p 1937:1937 -p 8002:8002/udp ...
每个实例需要:
- 使用独立的端口组
- 配置独立的存储目录
- 修改对应的配置文件
7.2 使用docker-compose管理
推荐使用docker-compose.yml来管理部署:
version: '3'
services:
srs:
image: registry.cn-hangzhou.aliyuncs.com/ossrs/srs:4
ports:
- "1936:1936"
- "8001:8001/udp"
volumes:
- ./dvr:/usr/local/srs/static/DVR-video
command: ["./objs/srs", "-c", "conf/rtmp2rtc.conf"]
这样部署和管理都更加方便,也减少了手动输入命令出错的可能性。
8. 性能优化建议
8.1 内核参数调优
对于高并发场景,建议调整以下内核参数:
# 增加UDP缓冲区大小
sysctl -w net.core.rmem_max=26214400
sysctl -w net.core.wmem_max=26214400
# 增加文件描述符限制
ulimit -n 65535
8.2 SRS配置优化
在rtmp2rtc.conf中可以调整:
rtc_server {
# 每个连接的工作线程
worker_processes 4;
# 心跳间隔
heartbeat_timeout 30s;
# 带宽限制
max_bandwidth 100m;
}
这些参数需要根据实际服务器配置和业务需求进行调整。
更多推荐
所有评论(0)