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 秒实验
- 把
hls块的右括号删掉,看解析结果会怎样——后面的键全挂到hls里面去,树变了但语法不错。 - 把
listen 1935;挪进vhost,猜 SRS 会不会报错——不报错,但 1935 不再被监听。 - 给
vhost再加一层嵌套,看还认不认——不认,SRS 的块只有两层。
常见误区
- 「缩进决定层级」——不决定,只认分号与括号。
- 「参数写错会报错」——多数时候静默忽略,最难查。
- 「块可以随便嵌套」——SRS 只到两层,再深就不认了。
自测三问(点开对答案)
1. srs.conf 里最深几层? —— **两层**:根下面的块,块下面的子块。 2. `hls_fragment` 写在 `vhost` 里会生效吗? —— **不会**,它必须写在 `hls` 块里,写外面被忽略。 3. 括号少写一个会怎样? —— **后面所有键都挂到错误的父节点**,参数看着在、其实不在。- ☐ (本节完,下一节 11.4.3 ingest.conf)