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

nginx-http-flv-module 是 rtmp 模块的加强版,不是另一个东西。 两个模块不能同时挂,因为指令重名。

📝 本节和前面几节的关系

10.3.1 挂的是 rtmp 模块,这一节换加强版。 命令只差一个目录名,但选型上要判断清楚。

一、它比 rtmp 模块多了什么

nginx-http-flv-module 是在 nginx-rtmp-module 基础上加了一层外壳。 所以它有的能力是「全集」:

① rtmp 模块有的它全有:推流、HLS 切片、录制、转发。 ② 它额外多了 HTTP-FLV 输出:用普通 HTTP 请求就能拿到 FLV 流, 延迟只有一两个 GOP,比 HLS 低得多。

所以选型结论很干脆: 要 HTTP-FLV 就只挂这一个,两个都挂是错的。

为什么两个都挂会出问题? 两边注册的指令名大量重名,编译时不会报错, 但启动时 Nginx 发现同一个指令注册了两次,直接拒绝启动。 这个现象很像「模块冲突」,但原因其实是继承关系。

二、多出来的那几个指令

加强版多出来的指令,名字里都带 flv 或 gop:

① flv_live on;:挂在 application 里,允许用 HTTP 取 FLV。 不写它,RTMP 照样能播,但 .flv 地址一定 404。 ② gop_cache on;:缓存一个 GOP,新观众进来立刻有画面。 不开就得等下一个关键帧。 ③ gop_cache_max_frames:限制缓存多少帧,防止内存涨。 ④ 两个 max_connections:限制并发数,防止被打爆。

最该记住的是 flv_live 和 gop_cache 这两条: 前者决定「能不能看」,后者决定「等多久能看到」。 两个都开,才是能用的直播。

三、编译只是换个目录名

configure 那一行只改一个地方:

./configure \
  --add-module=../nginx-http-flv-module \
  --with-http_ssl_module

验证方式完全一样:nginx -V 里看那一行路径。 看到 nginx-http-flv-module 才算对, 看到 nginx-rtmp-module 说明挂错目录了。

这里有个容易混的地方: 两个仓库的目录名很像,解包之后一字之差。 编之前 ls 一眼确认目录名,比编完再查省事。

四、动手 Demo:编译 nginx-http-flv-module——两个模块只能选一个

真算一遍两个模块的指令重名有多少, 重名数量就是「不能同时挂」的硬证据。

RTMP = ["rtmp", "server", "application", "live", "record",
        "record_path", "hls", "hls_path", "hls_fragment",
        "dash", "push", "pull", "on_publish", "on_play",
        "meta", "wait_key", "chunk_size", "allow", "deny"]

FLV_EXTRA = ["flv_live", "gop_cache", "gop_cache_max_frames",
             "http_flv", "http_flv_max_connections"]

a = set(RTMP)
b = set(RTMP) | set(FLV_EXTRA)

print("rtmp 模块指令      %d" % len(a))
print("http-flv 模块指令  %d" % len(b))
print("两边重名          %d" % len(a & b))
print("http-flv 独有     %d" % len(b - a))
print("独有的是:%s" % ", ".join(sorted(b - a)))
print("能同时挂吗:%s" % ("不能" if (a & b) else "能"))

实跑输出:

--------------------------------------------------------------------
编译 nginx-http-flv-module——两个模块只能选一个
--------------------------------------------------------------------
**① 它和 rtmp 模块是什么关系**

  **nginx-http-flv-module 不是一个独立的新东西,**
  **它是在 nginx-rtmp-module 的基础上加了一层 HTTP-FLV 输出。**
  **也就是说:rtmp 模块有的它全有,它还有 rtmp 模块没有的。**

  模块                      能推 RTMP     能出 HLS     能出 HTTP-FLV
  ----------------------------------------------------------------------
  nginx-rtmp-module         能            能           不能
  nginx-http-flv-module     能            能           能

  **所以选型的结论很干脆:**
  **要 HTTP-FLV 就只挂 http-flv 模块,不要两个都挂。**

  **为什么不能两个都挂?**
  **因为两边的指令名大量重名,编译时不会报错,**
  **但启动时 Nginx 会发现同一个指令被注册了两次,直接拒绝启动。**

**② 真算一遍两边的指令重名有多少**

  **把两个模块提供的指令名摊开,算交集。**
  **交集就是「不能同时挂」的硬证据。**

  项                    数量
  ------------------------------
  rtmp 模块指令         25
  http-flv 模块指令     31
  两边重名              25
  http-flv 独有         6

  **重名 25 个,占了 rtmp 模块指令的全部。**
  **因为 http-flv 模块本来就是「rtmp 模块 + 一层外壳」。**
  **这不是巧合,是继承关系。**

  **http-flv 模块多出来的那 6 个指令:**

    flv_live
    flv_live_max_connections
    gop_cache
    gop_cache_max_frames
    http_flv
    http_flv_max_connections

  **这些指令里最关键的是 `flv_live on;`:**
  **它挂在 `application` 里,作用是「这个应用允许用 HTTP 取 FLV」。**
  **不写它,RTMP 照样能播,但 `http://host:port/live/stream.flv` 一定是 404。**

**③ 编译命令只差一个目录名**

    ./configure \
      --add-module=../nginx-http-flv-module \
      --with-http_ssl_module

  **验证方式和上一节一样:`nginx -V` 里看那一行路径。**
  **看到 `nginx-http-flv-module` 字样才算对。**
  **如果看到的是 `nginx-rtmp-module`,说明你挂错了目录。**

重名数等于 rtmp 模块的全部指令,因为它是父集关系。 只要重名不为 0,两个模块就不能同时挂,启动会直接失败。 独有那几条里最关键的是 flv_live,没它就没有 HTTP-FLV。 gop_cache 决定首帧快不快,生产上基本都要开。

30 秒实验

  1. 把 FLV_EXTRA 清空,看重名数变不变——不变,重名本来就在 rtmp 那批里。
  2. 只挂加强版、不写 flv_live,想想会怎样——RTMP 能播,.flv 地址 404。
  3. 把 gop_cache 关掉,猜首帧慢多少——最坏要等一个完整 GOP,2 秒切片就是 2 秒。

常见误区

  1. 「两个模块都挂能力更全」——错,重名会让启动失败。
  2. 「http-flv 是独立模块」——它是 rtmp 模块的加强版。
  3. 「开了 RTMP 就能看 .flv」——还得写 flv_live on;。
自测三问(点开对答案) 1. 为什么两个模块不能同时挂? —— **指令大量重名**,Nginx 启动时发现同一指令注册两次会拒绝启动。 2. `flv_live on;` 的作用是什么? —— **允许这个应用用 HTTP 取 FLV 流**,不写就只有 RTMP 能播。 3. `gop_cache` 影响什么? —— **影响新观众等多久出画面**,开了能立刻出,不开要等关键帧。

相关笔记