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

srs.conf 是主配置,语法和 Nginx 几乎一样。 区别只在它最深层只有两层,看到第三层基本是写错了地方。

📝 本节和前面几节的关系

11.4.1 讲了层级,这一节看主配置的实物。 11.4.3 与 11.4.4 是两份附加配置,各管一件事。

一、它长什么样

语法只有两种形式:键 值; 与 块名 { … }。 缩进不影响语义,只认分号与大括号,和 Nginx 一脉相承。

一份典型的主配置包含五个块:

① http_api:HTTP 接口,默认 1985,用来查状态、踢流。 ② http_server:内置 Web 服务,默认 8080,吐切片文件。 ③ vhost:虚拟主机,绝大多数参数都在这里面。 ④ rtc_server:WebRTC 用,要额外编译才有。 ⑤ srt_server:SRT 用,同样要额外编译。

五个块里,日常改得最多的是 vhost: hls、dvr、play、publish、cluster 全挂在它下面。

二、解析成树:最深两层

写一个三十行的解析器,把配置拆成树,就能看出层级: 根下面是五个块,vhost 下面是五个子块,到此为止。

这个「最深两层」不是巧合,是设计: SRS 没有更深的嵌套,所以要配的东西一定挂在某个块的第一层。 如果看到第三层,几乎可以肯定是括号写错了位置。

括号写错位置时,解析器会把后面的键挂到错误的父节点上。 SRS 本身也会这样——它不会报错,只会把参数算到别的块里。 所以「配了没生效」的另一个原因,就是括号少写了一个。

三、三条能自动查出来的错

这份配置的校验规则其实只有三条:

① 全局键不许进块:listen、max_connections、daemon 只能写在最外层。 ② hls_* 与 dvr_* 只许进对应的块:写在外面等于没写。 ③ 开关类只认 on 与 off:onn、true、1 都会被忽略。

第二条最坑:hls_fragment 写在 vhost 里,SRS 不报错。 它只是把这一行当成不认识的键,默默忽略掉, 于是你以为切片是十秒,实际用的是默认值。 拿这三条过一遍,八成的手写错误都能当场揪出来。

四、动手 Demo:srs.conf——把一份真配置拆成树

三十行的配置文本,先把结构解析出来, 再拿三条规则去查它。

SRS_CONF = """
listen              1935;
max_connections     1000;
http_api { enabled on; listen 1985; }
vhost __defaultVhost__ {
    play { gop_cache off; queue_length 10; }
    hls { enabled on; hls_fragment 10; hls_window 60; }
}
"""

root, ndir = srs_parse(SRS_CONF)   # 切成 键值 与 块
for depth, name, nd, nb in walk(root):
    print("  " * depth, name, nd, nb)

WRONG = [
    ("listen 1935;", "写进 vhost 里"),
    ("hls_fragment 10;", "直接写在 vhost 里"),
    ("enabled onn;", "值拼错"),
]
for a, b in WRONG:
    print(a, "->", b)

实跑输出:

--------------------------------------------------------------------
srs.conf——把一份真配置拆成树
--------------------------------------------------------------------
**① 它长什么样**

  **SRS 的配置语法和 Nginx 几乎一样:`键 值;` 或 `块名 { … }`。**
  **区别只在缩进不管用,只认分号与大括号。**

    listen              1935;
    max_connections     1000;
    daemon              off;
    srs_log_tank        console;

    http_api {
        enabled         on;
        listen          1985;
    }
    http_server {
        enabled         on;
        listen          8080;
        dir             ./objs/nginx/html;
    }
    vhost __defaultVhost__ {
        tcp_nodelay     on;
        min_latency     on;
        play {
            gop_cache       off;
            queue_length    10;
        }
        publish {
            mr              off;
        }
        hls {
            enabled         on;
            hls_path        ./objs/nginx/html;
            hls_fragment    10;
            hls_window      60;
        }
        http_remux {
            enabled     on;
            mount       [vhost]/[app]/[stream].flv;
        }
    }

**② 真解析成树**

  **写一个三十行的解析器,把这 35 行文本拆成树。**

  缩进     节点                         直属键值     子块
  -----------------------------------------------------------
  0        (根)                         4            3
  1          http_api                   2            0
  1          http_server                3            0
  1          vhost __defaultVhost__     2            4
  2            play                     2            0
  2            publish                  1            0
  2            hls                      4            0
  2            http_remux               2            0

  **一共 20 个键值、8 个块(含根)。**
  **最深的只有第 2 层:`vhost` 下面的 `hls`、`play`。**
  **SRS 的配置不会更深,看到第 3 层一定是写错了地方。**

**③ 三条能自动查出来的错**

  写错的写法           症状                  为什么要写对
  -------------------------------------------------------------------------
  listen 1935;         写进 vhost 里         listen 只属于全局层
  hls_fragment 10;     直接写在 vhost 里     hls_* 必须写在 hls 块内
  enabled onn;         值拼错                只认 on/off,拼错就当没写

  **第二条最坑:`hls_fragment` 写在 vhost 里,SRS 不报错。**
  **它只是把这一行当成一个不认识的键,默默忽略掉。**
  **于是你以为切片是 10 秒,实际用的是默认值。**

  **第三条同理:`onn` 不是 `on`,`enabled` 就等于没开。**
  **表现是「配了 HLS 但没有切片文件」,查半天查不出原因。**

  **所以这份配置的校验规则其实只有三条:**
  **① 全局键不许进块;② `hls_*`/`dvr_*` 只许进对应块;**
  **③ 开关类只认 `on` 与 `off`。**
  **拿这三条过一遍,八成的手写配置错误都能当场揪出来。**

解析结果:根下面三个块,vhost 下面四个子块,最深两层。 一共二十个键值、八个块,这就是一份主配置的全部结构。 三条规则查出来的错,SRS 一条都不会主动报,全靠自己扫。 最值得记的是第二条:hls_fragment 写错层等于没写。

30 秒实验

  1. 把 hls 块的右括号删掉,看解析结果会怎样——后面的键全挂到 hls 里面去,树变了但语法不错。
  2. 把 listen 1935; 挪进 vhost,猜 SRS 会不会报错——不报错,但 1935 不再被监听。
  3. 给 vhost 再加一层嵌套,看还认不认——不认,SRS 的块只有两层。

常见误区

  1. 「缩进决定层级」——不决定,只认分号与括号。
  2. 「参数写错会报错」——多数时候静默忽略,最难查。
  3. 「块可以随便嵌套」——SRS 只到两层,再深就不认了。
自测三问(点开对答案) 1. srs.conf 里最深几层? —— **两层**:根下面的块,块下面的子块。 2. `hls_fragment` 写在 `vhost` 里会生效吗? —— **不会**,它必须写在 `hls` 块里,写外面被忽略。 3. 括号少写一个会怎样? —— **后面所有键都挂到错误的父节点**,参数看着在、其实不在。

相关笔记