🎬 第五章 HLS流媒体协议
📄 一句话概括

HLS 的延迟是设计出来的:约等于「切片时长 × (回溯数 + 缓冲数)」。 它用这个代价换来规模、兼容和穿墙能力。

📝 本节和前面几节的关系

5.1.2 走完了流程,这一节把流程的代价算清楚。 5.1.4 再拿这个代价去对照各种场景,看哪些能接受、哪些不能。

一、延迟到底花在哪

HLS 的延迟不是「网络慢」,而是「设计上就要攒」: ① 切片时长:一个切片要录满才发,比如 4 秒。 这一笔是硬成本,绕不过去。 ② 列表回溯数:客户端一般从倒数第 3 个切片开始播, 为的是万一某个切片下载失败还能往前退。 ③ 客户端缓冲:自己再攒 1 到 2 个切片。

所以端到端延迟约等于「切片时长 × (回溯数 + 缓冲数)」。 4 秒切片、回溯 3 个、缓冲 1 个,就是 16 秒左右。

实测这张表能看清代价的走向: 2 秒切片约 6~8 秒,4 秒约 12~16 秒,10 秒就到 30~40 秒。 切片时长是唯一的乘数,改它一个就能整体缩放。

二、把延迟压下去要付什么

切到 2 秒能把延迟压到 6 到 8 秒,代价很实在: ① 请求数翻倍:同样时长,切片多一倍,HTTP 请求也多一倍。 ② 头部开销上升:每个切片都是一段独立的 TS,PAT/PMT 要重发。 切片越短,这份固定开销摊得越薄不了。 ③ CDN 缓存效率下降:文件小了,命中率会掉。 热门片还好,长尾片会明显吃亏。

还有一个隐性代价:切片越短,编码质量越难保证。 因为每个切片都得以关键帧开头,关键帧一密,同码率下画质就下降。

想既要低延迟又要画质,就得换路子: LL-HLS 用「部分切片」把等待时间切成小段, 或者干脆换 HTTP-FLV 与 WebRTC。

三、优势也很硬

① 就是普通 HTTP:任何 CDN、任何防火墙都放行,不用开特殊端口。 这一条在企业内网里的价值常常被低估。 ② 天然支持大规模:切片是静态文件,缓存命中率极高。 一百万观众和一万观众的服务器压力差不多,只是 CDN 多花点钱。 ③ 自适应码率成熟:主列表多档位,客户端可以平滑切换。 ④ 客户端兼容性最好:iOS 原生支持,浏览器用 hls.js 也能播。

一句话:HLS 用延迟换规模和兼容性。 所以「大流量、能忍几秒延迟」选 HLS; 「要低延迟、观众不多」选 WebRTC 或 HTTP-FLV。

四、动手 Demo:延迟等于切片数乘切片时长

按「切片时长 × (回溯数 + 缓冲数)」算四种配置的延迟。 算完再反过来看:压延迟的代价是请求数翻倍。

combos = [(2, 3, 1), (4, 3, 1), (6, 3, 1), (10, 3, 1)]

print("切片秒  回溯  缓冲  延迟下限  延迟上限")
for seg, back, buf in combos:
    lo = seg * back
    hi = seg * (back + buf)
    print("%6d  %4d  %4d  %8d  %8d" % (seg, back, buf, lo, hi))

# 压延迟的代价:同样一小时,切片数与请求数成正比
print()
print("一小时 3600 秒,切片时长与请求数的关系:")
for seg in (2, 4, 6, 10):
    n = 3600 // seg
    print("  %2d 秒切片 -> %4d 个切片、%4d 次请求、标题占 %d 次"
          % (seg, n, n, n))

实跑输出:

--------------------------------------------------------------------
优劣势——延迟等于切片数乘切片时长
--------------------------------------------------------------------
**① 延迟的组成**

  **HLS 的延迟不是「网络慢」,而是「设计上就要攒」:**
  **① 切片时长**:**一个切片要等录满才发,比如 4 秒。**
  **② 列表里保留几个**:**客户端通常从倒数第 3 个开始播。**
  **③ 客户端缓冲**:**自己再攒 1 到 2 个切片。**

  **所以端到端延迟约等于「切片时长 × (列表回溯数 + 缓冲数)」。**
  **4 秒切片、从倒数第 3 个起播、再缓冲 1 个,就是 16 秒左右。**

**② 不同切片时长的延迟**

  切片时长     回溯 3 个     加缓冲 1 个     实际起播
  ----------------------------------------------------------
  2 秒         6 秒          8 秒            约 6~8 秒
  4 秒         12 秒         16 秒           约 12~16 秒
  6 秒         18 秒         24 秒           约 18~24 秒
  10 秒        30 秒         40 秒           约 30~40 秒

  **切到 2 秒能把延迟压到 6 到 8 秒,但代价很实在:**
  **① 请求数翻倍**:**同样时长,切片多一倍,HTTP 请求也多一倍。**
  **② 头部开销上升**:**每个切片都是一段独立的 TS,PAT/PMT 要重发。**
  **③ CDN 缓存效率下降**:**文件小了,命中率会掉。**

**③ 优势也很硬**

  **① 就是普通 HTTP**:**任何 CDN、任何防火墙都放行,不需要开特殊端口。**
  **② 天然支持大规模**:**切片是静态文件,缓存命中率极高。**
  **一百万观众和一万观众的服务器压力差不多。**
  **③ 自适应码率成熟**:**主列表多档位,客户端可以平滑切换。**
  **④ 客户端兼容性最好**:**iOS 原生支持,浏览器用 hls.js 也能播。**

  **一句话:HLS 用延迟换规模和兼容性。**
  **所以「大流量、能忍几秒延迟」选 HLS;「要低延迟、观众不多」选 WebRTC 或 HTTP-FLV。**

延迟下限只看回溯数,缓冲数只影响上限:这就是「先下 3 片」的真正含义。 10 秒切片的下限就 30 秒,已经超过大多数直播能忍的范围。 切片数与时长的关系是整数除法,3600/7 会丢掉余数,算出来的片数偏少。

30 秒实验

  1. 把回溯数从 3 改成 2,看下限怎么变——少一个切片时长,但抗抖动能力也弱了一档。
  2. 把切片改成 1 秒,看请求数——3600 次请求,但延迟能压到 2~4 秒,这就是低延迟 HLS 的做法。
  3. 把缓冲数改成 3,看上限变化——上限涨两个切片,下限一点没动。

常见误区

  1. 「HLS 延迟高是因为 TCP 慢」——不是,是切片机制本身要攒。
  2. 「切片越短越好」——请求数、头部开销、画质三项都要付代价。
  3. 「缓冲越多越流畅」——越多越抗抖动,但延迟上限也跟着涨。
自测三问(点开对答案) 1. 延迟的公式是什么? —— **切片时长 × (回溯数 + 缓冲数)**,下限只看回溯数。 2. 砍切片时长有哪三项代价? —— **请求数翻倍、头部开销上升、CDN 命中率下降**,另外画质也会受影响。 3. HLS 最硬的优势是什么? —— **纯 HTTP**,任何 CDN 与防火墙都放行,规模几乎不受服务端限制。

相关笔记