推流地址里那一段,就是 application 的名字。 一个 application 配几行,决定它能推、能播、还是能转发。
10.4.1 与 10.4.2 讲的是通用结构,这一节只讲 RTMP 那一段。 这一节的内容配完就能推流,是第十章的落地点。
一、地址是怎么拼出来的
推流地址格式:rtmp://主机:端口/应用名/流名。
中间那个「应用名」就是 application 后面跟的名字。
所以配了 application live,地址里就必须写 /live/。
推 rtmp://host/abc/stream 会失败,因为 /abc/ 不存在。
这个错误的特征很好认:
推流端只报「连接断开」或者一直转圈,
服务端 error.log 里才写着「no such application」。
所以推不上流时,先看服务端日志,别在推流端反复改参数。
二、三个核心指令
① live on;:允许这个应用接收推流。
不开它,只能播不能推。
② hls on;:同时切 HLS 片。
要配合 hls_path 指定切片目录,
hls_fragment 指定片长。
切片目录必须在 http 的 web 根下面,不然播放器取不到。
③ record 系列:把流录成文件。
record all; 录音视频,record_path 指定目录,
record_unique on; 让每次录制单独一个文件。
hls_path 那条最容易配错:
它是文件系统路径,但播放器是通过 HTTP 取它的。
所以这个目录必须落在 http 块里某个 root 能覆盖到的地方。
两者对不上,切片文件生成了却播不了——这是最典型的「配了不生效」。
三、hls 的两个参数要算
hls_fragment 是片长,hls_playlist_length 是列表长度。
两个数一除,就是观众能往回拖几片。
比如片长 5 秒、列表 30 秒,就是 6 片。 观众最远能回到 30 秒前,再早的已经被删了。
这两个数的取舍是延迟与请求数的交换: 片长 5 秒,首屏就不可能低于 5 秒; 压到 2 秒,首屏快了,但请求数翻两倍半,CDN 命中率也跟着掉。 这是第五章算过的老账,在这里只是换了个地方配。
还有一个隐含约束:
切片只能切在关键帧上。
如果编码时 GOP 是 5 秒,hls_fragment 2s 也只能切出 5 秒的片。
所以配切片之前,先确认推流端的 GOP 长度。
四、动手 Demo:rtmp 块配置——一个 application 决定三类地址
真解析一份 rtmp 配置,扫出每个 application, 再按它开了什么,推出能用的地址。
CONF = """\
rtmp {
server {
listen 1935;
application live {
live on;
hls on;
hls_path html/hls;
hls_fragment 5s;
}
application vod {
play html/vod;
}
}
}"""
apps, cur = [], None
for line in CONF.splitlines():
s = line.strip()
if s.startswith("application "):
cur = {"name": s.split()[1], "dirs": {}}
apps.append(cur)
elif cur is not None and " " in s and not s.startswith("}"):
k, v = s.split(" ", 1)
if k in ("live", "hls", "play", "record", "hls_fragment"):
cur["dirs"][k] = v.rstrip(";")
for ap in apps:
d = ap["dirs"]
if d.get("live") == "on" and d.get("hls") == "on":
kind = "能推能播,RTMP 与 HLS 都行"
elif d.get("live") == "on":
kind = "能推,只能走 RTMP"
elif "play" in d:
kind = "点播,只读文件"
else:
kind = "没开任何能力"
print("%-6s rtmp://127.0.0.1:1935/%s/stream %s"
% (ap["name"], ap["name"], kind))
frag, pl = 5, 30
print("片长 %ds、列表 %ds -> 能回看 %d 片" % (frag, pl, pl // frag))
实跑输出:
--------------------------------------------------------------------
rtmp 块配置——一个 application 决定三类地址
--------------------------------------------------------------------
**① `application` 是地址里的那一段**
**推流地址的格式是 `rtmp://主机:端口/应用名/流名`。**
**中间那个「应用名」就是 `application` 后面跟的名字。**
**所以配了 `application live`,推流地址里就得写 `/live/`。**
**这一点最容易被忽略:**
**配了 `application live`,推 `rtmp://host/abc/stream` 会失败,**
**因为 `/abc/` 这个应用不存在。**
**报错不在推流端,在服务端日志里,所以新手常常找不到原因。**
**② 真解析这份配置,推出所有能用的地址**
**解析器扫一遍 `application` 块,看每个应用开了什么能力。**
应用 访问地址 播放方式
-----------------------------------------------------------------------
live rtmp://127.0.0.1:1935/live/stream RTMP/HLS 都能播
vod rtmp://127.0.0.1:1935/vod/stream 点播,地址即播放地址
push rtmp://127.0.0.1:1935/push/stream 只能走 RTMP
**三个应用,三种用途,差别全在块里那几行:**
**① `live`**:**`live on;` 允许推流,`hls on;` 同时切片。**
**推一次,RTMP 与 HLS 都能看。**
**② `vod`**:**`play` 指向一个目录,这是点播不是直播。**
**推流到这里会失败,因为它只读文件。**
**③ `push`**:**`push` 那条把流再转给另一台服务器,**
**这就是最小规模的级联。**
**③ 几个参数的取值要算**
**这份配置里 `hls_fragment 5s`、`hls_playlist_length 30s`。**
**算一下:列表里能放 6 个切片,观众最多能往回拖 30 秒。**
参数 值 直接后果
---------------------------------------------------------------------
hls_fragment 5s 起播至少要等一个切片
hls_playlist_length 30s 最多回看六片,再早的删了
chunk_size 4096 影响 RTMP 分块大小,不改变总字节
**`hls_fragment` 是延迟的地板:要 5 秒切片,首屏就不可能低于 5 秒。**
**想压到 2 秒,切片就得设 2 秒,代价是请求数翻倍、CDN 命中率下降。**
**这是第五章算过的老账,在这里只是换了个地方配。**
地址里那一段就是 application 名,改名字地址就跟着变。
hls on 与 live on 同时开,一路流两种播法都能看。
play 那份是点播,推流到它上面会失败。
片长与列表一除就是回看片数,30 除 5 得 6。
30 秒实验
- 把
hls_fragment改成2s,看重算的回看片数——15 片,但首屏也从 5 秒降到 2 秒。 - 给
vod也加一条live on;,想想会怎样——它既能推又能播,但两个用途混在一起容易乱。 - 把
hls_path改到一个 http 根之外,猜播放器能不能取到——不能,切出来了但 HTTP 那边拿不到。
常见误区
- 「application 只是个标签」——它就是地址里那一段。
- 「切片想切多短就多短」——只能切在关键帧上,受 GOP 限制。
- 「hls_path 随便写」——必须在 http 的根目录覆盖范围内。
自测三问(点开对答案)
1. `application live` 对应的推流地址是什么样? —— **`rtmp://主机:1935/live/流名`**,中间那段就是应用名。 2. `hls_path` 配错会有什么现象? —— **切片文件生成了,但 HTTP 取不到,播放器一直转圈。** 3. 片长 5 秒、列表 30 秒,能回看几片? —— **6 片**,也就是往回 30 秒。- ☐ (本章完,下一章 11.1 SRS 简介)