SRS流媒体服务器实战:从零搭建到多协议直播推流(含OBS+FFmpeg配置)

最近在帮一个在线教育团队搭建内部直播系统时,我再次用到了SRS。说实话,第一次接触SRS还是几年前,当时为了一个紧急的直播项目,需要在两天内搭建起一套能支持上千人同时在线的流媒体服务。试了好几个方案,要么配置复杂得让人头疼,要么性能达不到要求,最后在GitHub上发现了SRS,用下来发现这确实是个“宝藏”项目——配置简单、性能稳定,关键是协议支持全面。现在每次遇到需要快速搭建直播服务的场景,我第一个想到的就是它。

如果你正在寻找一个既能快速上手,又能满足生产环境要求的流媒体服务器,SRS绝对值得你花时间研究。这篇文章不会只给你一堆命令和配置文件,我会结合自己踩过的坑,从环境选择、协议对比、实战配置到性能调优,一步步带你搭建一个真正能用的SRS直播系统。无论你是想搭建个人直播间,还是为企业部署一套稳定的直播服务,这里面的经验都能帮你少走弯路。

1. 环境准备与SRS安装:选对系统,事半功倍

选择什么样的操作系统来部署SRS,直接影响到后续的维护成本和系统稳定性。我个人的经验是,Ubuntu LTS版本是最省心的选择,特别是对于新手。它的包管理器完善,社区支持好,遇到问题容易找到解决方案。CentOS/RHEL系列当然也可以用,但如果你对Linux系统管理不太熟悉,可能会在一些依赖库的安装上多花些时间。

注意:无论选择哪个系统,都建议使用最新的LTS版本。旧版本的系统虽然稳定,但可能会缺少一些新特性支持,或者需要手动编译较新版本的依赖库,徒增复杂度。

在开始安装之前,确保系统已经更新到最新状态。这个步骤看似简单,却能避免很多因版本不一致导致的奇怪问题。

# Ubuntu/Debian系统
sudo apt update && sudo apt upgrade -y

# CentOS/RHEL系统
sudo yum update -y

接下来安装编译SRS所需的基础工具链。这里有个小技巧:如果你打算在生产环境使用,建议一次性把可能用到的开发工具都装上,避免后续需要某个功能时又要重新编译。

# Ubuntu/Debian
sudo apt install -y git build-essential automake libtool pkg-config

# CentOS/RHEL  
sudo yum groupinstall "Development Tools" -y
sudo yum install -y git autoconf automake libtool

SRS提供了三种安装方式,每种适合不同的使用场景:

安装方式适用场景优点缺点
源码编译需要自定义功能、深度定制灵活性最高,可启用所有模块编译耗时,依赖解决稍复杂
Docker容器快速测试、隔离环境秒级部署,环境干净性能略有损耗,网络配置需注意
预编译包生产环境快速部署安装简单,官方优化版本可能不是最新

对于大多数用户,我推荐从源码编译安装。虽然多花几分钟编译时间,但你能获得最完整的特性支持,而且后续的配置调整也更有灵活性。编译过程其实很简单:

git clone https://github.com/ossrs/srs.git
cd srs/trunk

# 这里我习惯启用所有常用模块
./configure --prefix=/usr/local/srs \
            --with-http-api \
            --with-http-server \
            --with-ffmpeg \
            --with-transcode \
            --with-ingest \
            --with-ssl \
            --with-hls

make -j$(nproc)  # 使用所有CPU核心加速编译
sudo make install

编译完成后,SRS的可执行文件会安装在/usr/local/srs目录下。我建议创建一个systemd服务文件,这样服务器重启后SRS能自动启动,管理起来也更方便。

sudo tee /etc/systemd/system/srs.service << 'EOF'
[Unit]
Description=SRS Streaming Server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/srs/objs/srs -c /usr/local/srs/conf/srs.conf
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -QUIT $MAINPID
Restart=always
User=root
WorkingDirectory=/usr/local/srs

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable srs

2. 核心配置详解:从基础到生产级优化

SRS的配置文件srs.conf是它的“大脑”,理解每个配置项的含义,能让你在遇到问题时快速定位。先来看一个我经过多次实践优化后的基础配置模板:

listen              1935;
max_connections     1000;
daemon              on;
srs_log_tank        file;
srs_log_file        /var/log/srs.log;

http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}

http_api {
    enabled         on;
    listen          1985;
}

vhost __defaultVhost__ {
    # HLS配置
    hls {
        enabled         on;
        hls_path        ./objs/nginx/html;
        hls_fragment    5;      # 分片时长,影响延迟
        hls_window      60;     # 播放列表保留时长
        hls_cleanup     on;     # 自动清理旧文件
        hls_dispose     0;      # 分片删除延迟
    }
    
    # HTTP-FLV配置
    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
    }
    
    # DVR录制配置
    dvr {
        enabled      on;
        dvr_path     /data/rec/[app]/[stream].[timestamp].mp4;
        dvr_plan     session;  # 按会话录制
    }
}

这个配置启用了SRS最常用的几个功能:RTMP监听(1935端口)、HTTP服务(8080端口)、管理API(1985端口),以及HLS和HTTP-FLV输出。其中几个关键参数需要特别注意:

  • hls_fragment:这个值直接影响HLS的延迟。默认10秒意味着观众至少会有10秒的延迟。对于需要较低延迟的场景,可以设置为3-5秒,但要注意太小的值会增加服务器负载。
  • max_connections:最大连接数限制。根据服务器配置调整,普通4核8G的服务器设置1000-2000比较合理。
  • dvr_path:录制文件的存储路径。确保这个目录有足够的磁盘空间,并且SRS进程有写入权限。

防火墙配置是很多新手容易忽略的一步。SRS需要开放以下端口:

# 如果使用ufw(Ubuntu)
sudo ufw allow 1935/tcp  # RTMP
sudo ufw allow 8080/tcp  # HTTP/HTTP-FLV/HLS
sudo ufw allow 1985/tcp  # API管理
sudo ufw allow 8000/udp  # WebRTC(如果启用)

# 如果使用firewalld(CentOS)
sudo firewall-cmd --permanent --add-port=1935/tcp
sudo firewall-cmd --permanent --add-port=8080/tcp  
sudo firewall-cmd --permanent --add-port=1985/tcp
sudo firewall-cmd --reload

在实际项目中,我遇到过好几次因为防火墙没配置好,导致外网无法推流播放的情况。一个快速测试的方法是,在服务器本地用telnet命令检查端口是否真的开放了:

telnet localhost 1935

如果连接成功,说明端口监听正常。然后再从外部网络测试,就能快速定位是防火墙问题还是网络问题。

3. 协议选择与实战推流:RTMP、HLS、HTTP-FLV、WebRTC深度对比

选择什么样的推流和播放协议,直接决定了最终的用户体验。很多开发者一开始只关注功能实现,等用户反馈延迟高、卡顿时才回头来优化协议,这时候往往要改动大量代码。我们先来看看这几种主流协议的对比:

协议延迟兼容性适用场景配置复杂度
RTMP1-3秒需要Flash或特定播放器传统直播、OBS推流低
HTTP-FLV1-3秒需要JavaScript播放器网页直播、移动端中
HLS10-30秒原生支持iOS/Android点播、高兼容性直播低
WebRTC<1秒现代浏览器实时互动、视频会议高

RTMP虽然因为Flash的没落而风光不再,但它仍然是OBS等专业推流软件的首选协议,配置简单,延迟也相对较低。如果你主要面向桌面端,或者推流端使用OBS,RTMP仍然是个不错的选择。

HTTP-FLV可以看作是RTMP的“升级版”,它使用HTTP协议传输,能穿透大多数防火墙和代理,在网页端通过flv.js等库就能播放。我最近的项目基本都转向了HTTP-FLV,因为它既保持了低延迟,又解决了RTMP在移动端的兼容性问题。

HLS最大的优势是兼容性——iOS和Android原生支持,几乎能在所有设备上播放。但它的延迟通常较高,适合对实时性要求不高的场景,比如赛事回放、课程录播等。

WebRTC是真正的“未来之星”,它能实现500毫秒以内的超低延迟,适合在线教育、视频会议等需要实时互动的场景。不过WebRTC的配置相对复杂,需要处理NAT穿透、TURN服务器等问题。

在实际配置中,我建议同时启用多种协议,让客户端根据自身能力选择最合适的。SRS的配置非常灵活:

vhost __defaultVhost__ {
    # 启用所有协议
    hls {
        enabled on;
        hls_fragment 5;
        hls_window 60;
    }
    
    http_remux {
        enabled on;
        mount [vhost]/[app]/[stream].flv;
    }
    
    # WebRTC配置(需要额外编译支持)
    rtc {
        enabled on;
        rtmp_to_rtc on;
        rtc_to_rtmp on;
    }
}

推流测试时,我习惯先用FFmpeg做快速验证,因为它的参数灵活,能模拟各种推流场景:

# 测试视频文件推流
ffmpeg -re -i input.mp4 -c:v copy -c:a copy -f flv rtmp://localhost/live/test

# 摄像头实时推流(Linux)
ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -preset ultrafast -f flv rtmp://localhost/live/camera

# 屏幕捕获推流
ffmpeg -f x11grab -s 1920x1080 -i :0.0 -c:v libx264 -f flv rtmp://localhost/live/screen

# 生成测试信号推流(无实际输入源时)
ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 -c:v libx264 -f flv rtmp://localhost/live/testpattern

对于大多数用户来说,OBS Studio是更友好的推流工具。在OBS中配置SRS推流只需要几步:

  1. 打开OBS设置,进入“推流”选项卡
  2. 服务类型选择“自定义”
  3. 服务器地址填写:rtmp://你的服务器IP/live
  4. 串流密钥可以任意填写,比如obs_demo
  5. 点击“确定”后,在主界面点击“开始推流”

这里有个细节需要注意:OBS默认的编码参数可能不适合你的服务器配置。如果推流后播放卡顿,可以尝试降低视频码率(比如从6000Kbps降到2000Kbps),或者使用更快的编码预设(如“veryfast”代替“medium”)。

4. 生产环境部署与性能调优

当你的直播服务从测试环境走向生产环境时,有几个关键点需要特别注意。我根据实际运维经验,总结了一套SRS生产环境的最佳实践。

安全配置是首要考虑的问题。默认配置下,任何人都可以向你的SRS服务器推流,这显然是不安全的。SRS提供了基于IP的简单鉴权机制:

vhost security_vhost {
    # 推流鉴权:只允许特定IP推流
    security {
        enabled     on;
        allow       publish 192.168.1.100;  # 允许的推流IP
        deny        publish all;            # 拒绝其他所有IP
        allow       play all;               # 允许所有客户端播放
    }
}

对于更复杂的鉴权需求,比如基于Token的动态鉴权,可以通过SRS的HTTP回调功能实现。当有客户端推流或播放时,SRS会向预设的HTTP接口发送请求,由你的业务服务器决定是否允许。

性能监控方面,SRS内置的HTTP API提供了丰富的状态信息。我通常会在服务器上部署一个简单的监控脚本:

#!/bin/bash
# 实时监控SRS状态
while true; do
    clear
    echo "====== SRS状态监控 ======"
    echo "时间: $(date)"
    echo ""
    
    # 获取服务器摘要信息
    curl -s http://localhost:1985/api/v1/summaries | jq '.'
    
    # 获取当前活跃流
    echo ""
    echo "当前活跃流:"
    curl -s http://localhost:1985/api/v1/streams | jq '.streams[] | {app, stream, clients}'
    
    # 系统资源监控
    echo ""
    echo "系统资源:"
    top -bn1 | grep "Cpu\|Mem"
    
    sleep 5
done

这个脚本每5秒刷新一次,显示SRS的推流数、客户端连接数以及系统资源使用情况。当并发量上升时,你可以快速发现瓶颈所在。

性能调优需要根据实际负载情况调整。以下是一些经过验证的优化参数:

# 网络优化
sndbuf 10485760;  # 发送缓冲区大小
rcvbuf 10485760;  # 接收缓冲区大小
tcp_nodelay on;   # 禁用Nagle算法,减少延迟

# 工作进程优化
worker_processes 4;  # 根据CPU核心数调整

# HLS优化(平衡延迟和性能)
hls {
    hls_fragment 3;      # 更小的分片,降低延迟
    hls_window 30;       # 更短的播放列表
    hls_cleanup on;
    hls_dispose 0;
    hls_m3u8_interval 2; # m3u8更新间隔
    hls_ts_file [app]/[stream]-[seq].ts;
}

# 连接限制(防止资源耗尽)
max_connections 2000;

如果单台服务器无法满足需求,SRS支持集群部署。常见的架构是“源站-边缘”模式:一台源站服务器接收所有推流,然后分发给多台边缘服务器,由边缘服务器服务播放请求。

# 边缘服务器配置
origin_cluster on;
vhost __defaultVhost__ {
    cluster {
        mode remote;
        origin 192.168.1.100:1935;  # 源站服务器地址
    }
}

在实际部署中,我建议至少使用2台边缘服务器做负载均衡。可以使用Nginx作为反向代理,将播放请求分发到不同的边缘服务器:

# Nginx负载均衡配置
upstream srs_servers {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://srs_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

日志管理也是生产环境不可忽视的一环。SRS默认将日志输出到文件,但长时间运行后日志文件会变得很大。我习惯用logrotate做日志轮转:

sudo tee /etc/logrotate.d/srs << 'EOF'
/var/log/srs.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 root root
    postrotate
        /usr/bin/killall -HUP srs 2> /dev/null || true
    endscript
}
EOF

这个配置会让SRS日志每天轮转一次,保留30天的压缩日志。当磁盘空间紧张时,你可以快速清理旧的日志文件。

最后,关于故障排查,我总结了一个快速检查清单:

  1. 推流失败:检查防火墙、端口是否开放;检查SRS进程是否运行;查看SRS日志tail -f /var/log/srs.log
  2. 播放卡顿:检查服务器带宽是否充足;降低推流码率;调整播放器缓冲区大小
  3. 高延迟:启用低延迟配置;考虑使用HTTP-FLV或WebRTC替代HLS;检查网络路由
  4. CPU使用率高:检查是否启用了转码;降低视频分辨率;使用硬件加速编码

有一次我遇到一个奇怪的问题:推流正常,但播放时断时续。最后发现是服务器的TCP连接数达到了上限。通过调整max_connections和系统级的ulimit设置解决了问题。所以当遇到异常时,不要只盯着SRS本身的配置,系统层面的限制也要考虑进去。

SRS的社区相当活跃,遇到问题时可以在GitHub上搜索相关issue,很可能已经有人遇到过类似问题并给出了解决方案。对于企业级应用,如果担心自己维护的稳定性,也可以考虑购买商业支持服务。不过从我个人的使用经验来看,SRS的稳定性已经足够好,只要配置得当,连续运行几个月不出问题是常态。

Logo

邀请您加入社区

更多推荐