🎬 第十一章 SRS搭建直播平台
📄 一句话概括

SRS 是国产开源的流媒体服务器,一路推流能同时出四种格式。 它的卖点不是性能,是「一个进程顶好几个」。

📝 本节和前面几节的关系

第十章用 Nginx 拼出直播能力,这一章换成一体化的 SRS。 11.2 开始装,装之前先弄清它到底能干什么。

一、它是什么

SRS 全称 Simple Realtime Server,国产开源,MIT 许可。 它的定位很直接:一台机器、一个进程,把直播要的协议全包了。

支持哪些协议,决定了它能接住什么客户端:

① RTMP:推流的事实标准,OBS、ffmpeg 都认它。 ② HTTP-FLV:延迟低、走 HTTP,能过大多数防火墙。 ③ HLS:兼容性最好,手机浏览器原生就能播。 ④ WebRTC:延迟最低,代价是要额外编译、要开 UDP。 ⑤ SRT 与 GB28181:广电与安防场景用的,默认都不开。

这几样不是并列关系,而是「一进多出」: 一路流推上去,上面几种地址同时能看。 这是它和「只能推不能拉」的转发工具最根本的区别。

二、四种输出的成本差在哪

很多人以为「多支持一种格式,带宽就多一份」,这是错的。 码流大小由编码决定,容器只往上加头。

真正的差别在【处理成本】上:

① RTMP 与 HTTP-FLV:在内存里换个封装就发出去,成本几乎为零。 ② HLS:要把切片写到磁盘,再由 HTTP 吐出去。 磁盘 IO 与重复的关键帧是它的两份额外开销。 ③ WebRTC:要把 H265 转码或重新打包,CPU 比前几种高得多。

所以「四种输出里只有 HLS 真的要花钱」这句话是准确的: 其余几种都是在内存里换个壳,HLS 是唯一要落盘的。 这也是第 126 号 Demo 里 HLS 那份数据最大的原因。

三、它比「流媒体服务器」宽

装完 SRS,你得到的其实是四样东西:

① 流媒体服务器:收流、转发、分发。 ② 小型 Web 服务器:http_server 一开,切片文件由它自己吐。 不用再装一个 Nginx。 ③ 录像机:dvr 块一开,每路流都能存成文件。 ④ 拉流器:ingest 让它主动去拉别人的流,方向正好反过来。

这四样合起来,才是「一个进程顶好几个」。 也正因为如此,它的配置文件比 Nginx 长得多——第十章的 Nginx 只管转发,SRS 连 Web 服务和录像都管。

四、动手 Demo:一次推流,四种输出各多大

同一段画面、同一套编码参数,只换容器, 把四种格式的字节数摆在一起看。

def encode_into(fmt):
    """真编一遍,直接写进指定容器。"""
    c = av.open(path, "w", format=fmt, options=opts)
    st = c.add_stream("libx264", rate=25)
    st.options = {"crf": "23", "preset": "veryfast", "g": "25"}
    for i in range(25):
        c.mux(st.encode(frame(i)))
    c.close()
    return 总字节数

for fmt in ("flv", "mpegts", "mp4", "hls"):
    print(fmt, encode_into(fmt))

# 再把 TS 拆开:定长 188 字节一包,看填充占多少
npk = len(raw) // 188
for i in range(npk):
    pkt = raw[i * 188:(i + 1) * 188]
    if pkt[3] & 0x20:            # 有适配域
        af += 1 + pkt[4]         # 长度字节 + 内容
print("包头", npk * 4, "填充", af, "负载", len(raw) - npk * 4 - af)

实跑输出:

--------------------------------------------------------------------
SRS 简介——一次推流,几种输出
--------------------------------------------------------------------
**① 它解决的核心问题**

  **没有 SRS 的时候,你想同时支持 RTMP、HTTP-FLV、HLS 三种播放,**
  **要么部署三个服务,要么自己写转发。**
  **SRS 把这件事变成配置项:一路流推上去,三种地址同时能看。**

  能力          配一行就有                额外开销
  ------------------------------------------------------------------
  RTMP 播放     默认就有                  没有,本来就是 RTMP
  HTTP-FLV      `http_remux`              几乎为零,只是换个封装
  HLS           `hls { enabled on; }`     要写磁盘,有明显 IO
  WebRTC        `rtc_server`              要额外编译,CPU 也高些

  **四种输出里,只有 HLS 真的要额外花钱**——**它要把切片写到磁盘,再由 HTTP 服务吐出去。**
  **其余几种都是在内存里换个封装,成本几乎为零。**

**② 真测:同一段画面,封成四种格式各多大**

  **内容完全一样、编码参数完全一样,差别只在容器。**

  格式     字节数     封装耗时毫秒     相对最小
  -------------------------------------------------
  FLV      10503      144              1.00 倍
  TS       16920      76               1.61 倍
  MP4      10672      76               1.02 倍
  HLS      14026      79               1.34 倍

  **四种格式里最小的是 FLV,最大的是 TS。**
  **差距主要来自容器头与索引,不是画面质量**——**编码参数一模一样,码流本身大小相同。**

  **注意 HLS 那一行包含了三个切片文件加一份索引:**
  **切片之间有重复的关键帧信息,索引又有额外开销,**
  **所以它一定是几种格式里最吃亏的那个。**
  **这是「低延迟换兼容性」这笔交易里,HLS 付的那部分钱。**

**③ 顺手拆一下 TS:它比 FLV 胖的那部分在哪儿**

  **TS 是定长包:不管里面装多少,一个包永远占 188 字节。**
  **这份 16920 字节的 TS 正好切成 90 个包,一个字节都不剩。**

  组成部分                    字节      占这份 TS
  ---------------------------------------------------
  包固定头(每包 4 字节)     360       2.1%
  适配域填充(37 个包有)     2563      15.1%
  真正装数据的部分            13997     82.7%

  **90 个包里有 37 个带适配域,那些字节基本都是零。**
  **它们出现的唯一理由是:这一包没装满,得用填充把长度凑够 188。**

  **这就是 TS 比 FLV 胖的原因:FLV 的 tag 多长就写多长,**
  **TS 却要把每一段都补齐到 188 的整数倍。**
  **这段画面本身很小(10503 字节的 FLV),补出来的零就显得格外多;**
  **换成 1080p 的大码流,比例会降下来,但绝不会降到零。**

  **代价换来的是好处:任意一个 188 字节的边界都能直接开始解码,**
  **丢了包也知道下一个包从哪儿开始。广播系统要的就是这个。**

**④ 它还有两件常被忽略的事**

  **① 它自带 HTTP 服务**:**切片文件由它自己吐,不用再装一个 Nginx。**
  **`http_server { enabled on; }` 一行就有。**
  **② 它有 `dvr` 与 `ingest`**:**前者录像,后者主动去拉别的流。**
  **`ingest` 的意思正好反过来——不是别人推给我,是我去拉别人。**

  **所以 SRS 的定位其实比「流媒体服务器」更宽:**
  **它同时是一个小型 Web 服务器、一个录像机、一个拉流器。**
  **这也是它在国内用得广的原因之一:装一个顶好几个。**

四种格式最小的是 FLV,最大的是 TS,差 1.6 倍。 编码参数完全一样,差的全在容器上。 TS 胖在定长包:90 个包里 37 个带填充,一共 2563 字节的零。 HLS 那份还含三个切片文件加一份索引,所以它比 TS 也多。

30 秒实验

  1. 把 crf 从 23 改成 40,看四种格式的相对大小会不会变——会小幅变,但排序不变。
  2. 把帧数从 25 提到 100,看 TS 的填充比例怎么变——降下来,因为每包塞得更满。
  3. 只留 MP4 一种,猜总耗时会不会降到四分之一——不会,编码才是主要开销,封装只占一小截。

常见误区

  1. 「SRS 只做 RTMP」——它同时支持 HLS、HTTP-FLV、WebRTC、SRT。
  2. 「格式越多码流越大」——码流是编码定的,容器只往上加头。
  3. 「HLS 最省带宽」——刚好相反,它要落盘还要重复关键帧。
自测三问(点开对答案) 1. 一路推流最多能出几种播放格式? —— **教材列了四种**:RTMP、HTTP-FLV、HLS、WebRTC。 2. 四种输出里哪种成本最高? —— **HLS**,因为要把切片写进磁盘,还得自己再吐出去。 3. TS 为什么比 FLV 大? —— **定长 188 字节一包,塞不满就用适配域填零。**

相关笔记