强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

09 - 流媒体服务器

流媒体服务器

9.1 服务器选型概览

服务器语言License特点适用场景
SRSC++MIT高性能、功能全面、中文社区活跃直播平台、企业级
Nginx-RTMPCBSD基于 Nginx、简单易用中小型项目
MediaSoupC++/Node.jsMITSFU、WebRTC 优先视频会议
WowzaJava商业功能完整、技术支持企业级
Red5JavaApacheJava 生态Java 项目

9.2 SRS(Simple Realtime Server)

SRS 是国内最流行的开源流媒体服务器,由 Winlin 主导开发。

9.2.1 核心特性

特性说明
RTMP 推流完整支持,包括 Enhanced RTMP (H.265/AV1)
HLS 输出支持 HLS/DASH/HTTP-FLV/WebRTC
集群Origin-Edge 集群、RTMP 中转
转码集成 FFmpeg 转码
录制FLV/MP4 录制
DVR直播回放
HTTP API管理和统计 API
WebRTCRTMP↔WebRTC 互转
GB28181安防监控接入

9.2.2 安装方式

# Docker(推荐)
docker pull ossrs/srs:5

# 源码编译
git clone https://github.com/ossrs/srs.git
cd srs/trunk && ./configure && make

# 二进制包(Ubuntu)
sudo apt install srs

9.2.3 核心配置文件

# conf/srs.conf
# SRS 主配置文件

listen              1935;
max_connections     1000;
srs_log_tank        console;

# HTTP API
http_api {
    enabled         on;
    listen          1985;
}

# HTTP Server(HLS/HTTP-FLV)
http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}

# RTMP 配置
vhost __defaultVhost__ {
    # 最小延迟配置
    min_latency     on;

    # GOP Cache(关键帧缓存)
    gop_cache       on;
    gop_cache_max_frames 2500;

    # 队列配置
    queue {
        enabled     on;
        capacity    2500;
    }

    # 转 HLS
    hls {
        enabled         on;
        hls_fragment    2;
        hls_window      10;
        hls_path        ./objs/nginx/html;
        hls_m3u8_file   [app]/[stream].m3u8;
        hls_ts_file     [app]/[stream]-[seq].ts;
    }

    # 转 HTTP-FLV
    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
    }
}

9.2.4 SRS 启动与管理

# 启动 SRS
./objs/srs -c conf/srs.conf

# Docker 启动
docker run --rm \
    -p 1935:1935 \
    -p 1985:1985 \
    -p 8080:8080 \
    -v $(pwd)/conf:/usr/local/srs/conf \
    ossrs/srs:5

# 查看状态
curl http://localhost:1985/api/v1/summaries

# 查看流列表
curl http://localhost:1985/api/v1/streams

9.3 Nginx-RTMP

Nginx 的 RTMP 模块,适合轻量级场景。

9.3.1 安装

# Ubuntu
sudo apt install nginx libnginx-mod-rtmp

# 或从源码编译
wget http://nginx.org/download/nginx-1.24.0.tar.gz
git clone https://github.com/arut/nginx-rtmp-module.git
tar xzf nginx-1.24.0.tar.gz && cd nginx-1.24.0
./configure --add-module=../nginx-rtmp-module
make && sudo make install

9.3.2 配置文件

# nginx.conf

rtmp {
    server {
        listen 1935;
        chunk_size 4096;
        buflen 1s;

        # 直播应用
        application live {
            live on;
            record off;

            # 关键帧缓存
            wait_key on;
            wait_video on;

            # HLS 输出
            hls on;
            hls_path /var/www/hls;
            hls_fragment 2s;
            hls_playlist_length 10s;
            hls_cleanup on;

            # 录制(可选)
            # record all;
            # record_path /var/records;
            # record_suffix -%d-%b-%y-%T.flv;

            # 推流鉴权(可选)
            # on_publish http://localhost:8080/auth/publish;
            # on_publish_done http://localhost:8080/auth/publish_done;
        }

        # 点播应用
        application vod {
            play /var/videos;
        }

        # 回放应用
        application hls {
            play /var/www/hls;
        }
    }
}

http {
    server {
        listen 8080;

        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /var/www;
            add_header Cache-Control no-cache;
            add_header Access-Control-Allow-Origin *;
        }

        # 统计页面
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        # 推流鉴权接口
        location /auth {
            proxy_pass http://localhost:3000;
        }
    }
}

9.3.3 Nginx-RTMP vs SRS 对比

维度Nginx-RTMPSRS
性能中等高(优化更好)
功能基础 RTMP/HLS全功能(WebRTC、GB28181 等)
配置Nginx 风格独立配置语法
HTTP API无原生支持完整 REST API
集群手动配置原生支持 Origin-Edge
社区英文为主中文为主、活跃
适用小型项目、快速搭建中大型直播平台

9.4 推流与拉流测试

推流测试

# FFmpeg 推流(文件)
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/stream1

# FFmpeg 推流(摄像头+麦克风)
ffmpeg -f v4l2 -i /dev/video0 -f alsa -i default \
    -c:v libx264 -preset veryfast -b:v 2000k \
    -c:a aac -b:a 128k \
    -f flv rtmp://localhost:1935/live/stream1

# OBS 推流设置
# 服务: 自定义
# 服务器: rtmp://your-server-ip:1935/live
# 串流密钥: stream1

拉流测试

# RTMP 播放
ffplay rtmp://localhost:1935/live/stream1

# HTTP-FLV 播放
ffplay http://localhost:8080/live/stream1.flv

# HLS 播放
ffplay http://localhost:8080/live/stream1.m3u8

# curl 检查 HLS
curl -s http://localhost:8080/live/stream1.m3u8

9.5 Origin-Edge 集群

SRS 支持 Origin-Edge 两级集群架构:

                    ┌─────────────┐
    推流端 ────RTMP───→│   Origin    │
                    │   (源站)     │
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
        ┌──────────┐┌──────────┐┌──────────┐
        │  Edge 1  ││  Edge 2  ││  Edge 3  │
        │ (边缘)   ││ (边缘)   ││ (边缘)   │
        └────┬─────┘└────┬─────┘└────┬─────┘
             │           │           │
             ▼           ▼           ▼
         观众群 1     观众群 2     观众群 3

Origin 配置

# origin.conf
listen 1935;

vhost __defaultVhost__ {
    # Origin 不需要特殊配置,接收推流即可
    gop_cache on;
}

Edge 配置

# edge.conf
listen 1935;

vhost __defaultVhost__ {
    # Edge 模式:从 Origin 拉流
    cluster {
        mode          remote;
        origin        192.168.1.10:1935;
        # 多源站(备源)
        # origin        192.168.1.11:1935 192.168.1.12:1935;
    }

    # 回源超时
    source_retry      3000;

    # 本地缓存
    gop_cache on;
}

9.6 SRS HTTP API

SRS 提供完整的 HTTP REST API 用于管理和监控:

常用 API

# 服务器概览
curl http://localhost:1985/api/v1/summaries

# 流列表
curl http://localhost:1985/api/v1/streams

# 特定流信息
curl http://localhost:1985/api/v1/streams?app=live&stream=stream1

# 客户端列表
curl http://localhost:1985/api/v1/clients

# 特定客户端信息
curl http://localhost:1985/api/v1/clients/{id}

# 关闭客户端(踢人)
curl -X DELETE http://localhost:1985/api/v1/clients/{id}

# 启动转码
curl -X POST http://localhost:1985/api/v1/transcode \
    -d '{"app":"live","stream":"stream1",
         "ffmpeg":"./objs/ffmpeg/bin/ffmpeg",
         "input":{"url":"rtmp://127.0.0.1:1935/live/stream1"},
         "output":{"url":"rtmp://127.0.0.1:1935/live/stream1_low",
                    "e":"-c:v libx264 -b:v 500k -s 640x360"}}'

# 录制
curl -X POST http://localhost:1985/api/v1/dvr \
    -d '{"app":"live","stream":"stream1","action":"start"}'

9.7 推流鉴权

SRS HTTP 回调鉴权

#!/usr/bin/env python3
"""
SRS 推流鉴权服务
"""

from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import urllib.parse


# 允许的推流密钥
VALID_STREAM_KEYS = {
    "stream_key_abc123": "user1",
    "stream_key_def456": "user2",
}


class AuthHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers.get('Content-Length', 0))
        body = self.rfile.read(content_length).decode('utf-8')
        params = urllib.parse.parse_qs(body)

        action = self.path
        stream_key = params.get('stream', [''])[0]
        app = params.get('app', [''])[0]

        print(f"[Auth] {action} app={app} stream={stream_key}")

        if action == '/api/v1/streams/auth':
            # 推流鉴权
            if stream_key in VALID_STREAM_KEYS:
                print(f"[Auth] ✅ 允许推流: {VALID_STREAM_KEYS[stream_key]}")
                self.send_response(200)
                self.end_headers()
                self.wfile.write(b'0')
            else:
                print(f"[Auth] ❌ 拒绝推流: 无效密钥")
                self.send_response(403)
                self.end_headers()
                self.wfile.write(b'-1')
        else:
            self.send_response(200)
            self.end_headers()

    def log_message(self, format, *args):
        pass  # 静默日志


if __name__ == '__main__':
    server = HTTPServer(('0.0.0.0', 8081), AuthHandler)
    print("鉴权服务运行在 http://0.0.0.0:8081")
    server.serve_forever()

SRS 配置:

vhost __defaultVhost__ {
    http_hooks {
        enabled on;
        on_publish http://localhost:8081/api/v1/streams/auth;
        on_unpublish http://localhost:8081/api/v1/streams/auth;
    }
}

9.8 SRS 性能优化

配置建议

# 生产环境优化配置
listen 1935;
max_connections 1000;
min_latency on;

vhost __defaultVhost__ {
    # TCP 优化
    tcp_nodelay on;

    # GOP Cache
    gop_cache on;
    gop_cache_max_frames 2500;

    # 消息队列
    queue {
        enabled on;
        capacity 2500;
        # 队列等待超时(秒),超过则丢帧
        jitter_algorithm default; # 或 low_latency
    }

    # 低延迟模式
    atc on; # 绝对时间戳

    # TCP 发送缓冲区
    send_min_interval 10;

    # 减少 chunk 头开销
    chunk_size 60000;
}

注意事项

  1. 防火墙:确保开放 1935 (RTMP)、8080 (HTTP)、1985 (API) 端口
  2. ulimit:高并发场景需调高系统文件描述符限制(ulimit -n 65535
  3. 时间戳跳变:推流端时间戳异常会导致播放问题,SRS 的 atc on 可缓解
  4. HLS 延迟:HLS 的延迟主要由 hls_fragmenthls_playlist_length 决定
  5. 回源风暴:Edge 节点需配置缓存,避免所有请求都回源
  6. HTTPS:生产环境务必使用 RTMPS (TLS) 或通过 HTTPS 分发 HLS

扩展阅读


上一章08 - 音频编解码 下一章10 - 流中转与分发 — 了解 CDN、转码与录制