从零构建GB28181视频推流系统:Docker+SRS5实战指南

第一次接触GB28181协议时,我被它复杂的配置项和晦涩的文档折磨得够呛。作为国内安防领域的标准协议,GB28181在政府、金融等行业的视频监控系统中广泛应用,但它的学习曲线却异常陡峭。记得有一次紧急项目,客户要求在48小时内完成20路海康摄像头的云端接入,我几乎翻遍了所有能找到的中文资料,依然在SIP信令和媒体流分离的问题上栽了跟头。正是那次经历让我意识到,真正实用的技术方案不应该只停留在命令复制粘贴层面,而需要深入理解每个参数背后的逻辑。本文将分享如何用Docker和SRS5搭建稳定可靠的GB28181推流系统,重点解析那些官方文档没有明说的"潜规则"。

1. 环境准备与架构设计

1.1 为什么选择Docker+SRS5组合

在视频流处理领域,传统部署方式面临三大痛点:环境依赖复杂版本兼容性差系统资源占用高。Docker容器化方案能完美解决这些问题:

  • 隔离性:SRS5的GB28181模块对libsip库有特定版本要求,容器化避免了与系统现有库的冲突
  • 便携性:配置好的镜像可以快速复制到其他服务器,特别适合边缘计算场景
  • 资源控制:通过cgroups限制CPU/内存使用,防止视频转码耗尽主机资源

SRS5相较于前代版本的改进尤为关键:

特性 SRS4 SRS5
GB28181支持 需手动编译 原生集成
SIP协议栈 仅UDP 支持TCP/UDP双模式
媒体传输 多端口 单端口复用
稳定性 高频推流易崩溃 生产环境验证

1.2 系统资源规划建议

根据实际负载测试,不同路数的摄像头需要相应配置:

# 查看系统资源使用情况
docker stats srs5 --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 典型资源占用参考值
+------------+---------+-----------+
| 视频路数 | CPU占用 | 内存占用  |
+------------+---------+-----------+
| 1-5路     | 15%~30% | 300MB~1GB |
| 5-10路    | 30%~50% | 1GB~2GB   |
| 10路以上  | 50%+    | 2GB+      |
+------------+---------+-----------+

提示:实际压力会受分辨率(1080P/4K)、帧率(25fps/30fps)和关键帧间隔影响,建议预留20%余量

2. SRS5服务部署详解

2.1 容器化部署全流程

以下是在CentOS 7.5+上的完整部署步骤,关键操作都附有原理说明:

# 1. 安装Docker(已安装可跳过)
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable --now docker

# 2. 获取SRS5镜像(指定版本避免自动更新导致配置失效)
docker pull ossrs/srs:5.0.86

# 3. 准备持久化存储目录
mkdir -p /srs/{conf,objs,logs}
chmod -R 777 /srs  # 确保容器有写入权限

# 4. 启动临时容器提取默认配置
docker run -d --name srs_temp ossrs/srs:5.0.86
docker cp srs_temp:/usr/local/srs/conf /srs/
docker cp srs_temp:/usr/local/srs/objs /srs/
docker rm -f srs_temp

2.2 关键端口映射解析

SRS5的GB28181功能需要开放以下端口:

端口 协议 用途 是否必需
5060 TCP SIP信令通信
9000 TCP 媒体流接收
1935 TCP RTMP推拉流 可选
8080 TCP HTTP API/管理界面 推荐
8000 UDP 媒体流备用端口 可选

启动生产环境容器的正确姿势:

docker run -d --name srs5 \
  --restart=unless-stopped \
  --cpus=2 \  # 根据实际情况调整
  --memory=4g \  # 限制最大内存
  -p 5060:5060 \
  -p 9000:9000 \
  -p 8080:8080 \
  -v /srs/conf:/usr/local/srs/conf \
  -v /srs/objs:/usr/local/srs/objs \
  -v /srs/logs:/usr/local/srs/logs \
  ossrs/srs:5.0.86

3. GB28181核心配置剖析

3.1 stream_caster模块深度配置

编辑/srs/conf/docker.conf,以下配置项需要特别注意:

stream_caster {
    enabled on;
    caster gb28181;
    listen 9000;  # 媒体流接收端口
    
    # 转推RTMP地址,[stream]会自动替换为设备ID
    output rtmp://127.0.0.1/live/[stream];  
    
    # 公网IP或域名,必须与摄像头配置一致
    host 120.25.36.47;  
    
    sip {
        enabled on;
        listen 5060;  # SIP信令端口
        
        # 必须与host一致!这是最常见配置错误
        candidate 120.25.36.47;  
        
        # 设备认证信息(可选)
        auth {
            username: admin;
            password: 12345;
        }
    }
}

常见坑点排查

  1. hostcandidate不一致会导致SIP信令不通
  2. 防火墙未放行5060和9000端口
  3. NAT环境下需要额外配置STUN服务器

3.2 海康摄像头配置指南

登录摄像头Web界面(通常为http://摄像头IP),在网络->高级配置->平台接入中:

  • 基本参数

    • 协议类型:GB/T28181-2016
    • 传输协议:TCP(必须!)
    • SIP服务器ID:34020000002000000001(按实际填写)
    • SIP服务器地址:您的SRS服务器IP
  • 媒体参数

    • 音频编码:AAC(G.711会导致流无法播放)
    • 采样率:44100Hz
    • 视频编码:H.264/H.265
    • 流类型:主码流/子码流
  • 高级选项

    • 注册有效期:3600(建议值)
    • 心跳间隔:60(保持连接活跃)

注意:不同型号海康摄像头的菜单路径可能略有差异,DS-2CD3系列通常在"系统管理"而非"网络"中

4. 运维监控与故障处理

4.1 实时状态监控方案

通过SRS内置的HTTP API获取推流状态:

# 获取活动流列表
curl http://localhost:8080/api/v1/streams/

# 示例返回(简化版)
{
  "code": 0,
  "streams": [
    {
      "id": "34020000001320000001",
      "name": "Camera01",
      "vcodec": "h264",
      "acodec": "aac",
      "clients": 3,
      "send_bytes": 4587921
    }
  ]
}

推荐配置Prometheus监控指标:

# prometheus.yml 片段
scrape_configs:
  - job_name: 'srs'
    static_configs:
      - targets: ['srs-server:8080']
    metrics_path: '/api/v1/prometheus'

4.2 常见故障速查表

现象 可能原因 解决方案
摄像头注册失败 SIP端口不通/密码错误 检查5060端口和auth配置
能注册但无视频流 媒体端口(9000)未开放 验证telnet服务器9000端口
视频卡顿 网络带宽不足 降低分辨率或启用子码流
音频不同步 时间戳异常 检查摄像头NTP配置
WebRTC无法播放 未启用HTTPS 配置SSL或使用HTTP-FLV协议

遇到SIP信令问题时,可以启用调试日志:

docker exec srs5 sed -i 's/warn;/debug;/g' /usr/local/srs/conf/docker.conf
docker restart srs5
tail -f /srs/logs/srs.log  # 观察信令交互过程

5. 进阶优化技巧

5.1 负载均衡与集群部署

当单节点无法承受流量压力时,可采用以下架构:

[摄像头] --> [SRS边缘节点] --> [中心SRS集群] --> [CDN/播放端]

关键配置要点:

  • 边缘节点配置forward将流转推到中心集群
  • 中心集群启用cluster模式
  • 使用Keepalived实现VIP故障转移

5.2 安全加固措施

  1. SIP安全

    • 修改默认认证信息
    • 配置IP白名单
    sip {
        enabled on;
        allow 192.168.1.0/24;  # 只允许内网摄像头注册
    }
    
  2. 媒体加密

    • 启用SRT加密传输
    • 配置HTTPS播放地址
  3. 系统防护

    # 限制容器资源
    docker update srs5 --cpus 2 --memory 4g --memory-swap 4g
    
    # 防止DDoS攻击
    iptables -A INPUT -p tcp --dport 5060 -m connlimit --connlimit-above 50 -j DROP
    

5.3 低成本存储方案

对于需要录像的场景,推荐使用FFmpeg转存:

ffmpeg -i rtmp://localhost/live/34020000001320000001 \
  -c copy \
  -f segment \
  -strftime 1 \
  -segment_time 3600 \
  -segment_format mp4 \
  /recordings/%Y-%m-%d_%H-%M-%S.mp4

结合minio实现分布式存储:

# 定时上传脚本示例
import os
from minio import Minio

client = Minio(
    "minio.example.com",
    access_key="your-key",
    secret_key="your-secret",
    secure=True
)

for file in os.listdir("/recordings"):
    client.fput_object(
        "video-archive", file,
        f"/recordings/{file}"
    )
    os.remove(f"/recordings/{file}")

在项目交付后的三个月里,这套方案稳定支撑了某智慧园区200+摄像头的实时接入。最让我意外的是,当初为了快速上线采用的Docker部署方式,在后续的横向扩展中展现出了惊人的灵活性——当需要新增50路摄像头时,我们只用了不到1小时就完成了边缘节点的扩容。

更多推荐