一条直播链就是五段:采集、编码、封装、推流、分发。 前三段这本书已经讲完了,剩下的两段要靠服务器。
第十二章做完「采集」,这一章把后面几段接起来。 这是全书最后一章,也是把前面十二章拼成一件事的一章。
一、五段各归哪一层
先看全景,再一段一段对回前面学过的库。 段 做什么 归哪一层
一 采集:拿画面与声音 AVDevice 二 编码:压成码流 AVCodec 三 封装:装进容器 AVFormat 四 推流:送到服务器 AVIO 协议 五 分发:转给观众 流媒体服务器
前三段这本书已经全讲完了:采集在第十二章、编码在第八章、封装在第七章。 第四段是协议层,第五段根本不归 FFmpeg 管。 「不归 FFmpeg 管」这句话要点明:服务器是别人的程序,FFmpeg 只负责把码流送到它的门口。 所以这一章的一半篇幅在讲「门口之外」,而不是 API。
二、逐段问本机能不能做
真跑之前先问一遍,省得写到一半发现没有这条路。 段 用什么 结果
一 采集 gdigrab 能 二 编码 libx264 能 三 封装 flv 能 四 推流 rtmp 不能 五 分发 服务器 没有,本机没装
五段里四段能真跑,只有第四段的 rtmp 协议与第五段整段做不了。 这个结果是这一章的写法依据:能做到的做到极致,做不到的写清原因并给替代验证。 「替代验证」这个词很重要: 不能推 RTMP,但可以把「要推的那串字节」亲手生成出来、再亲手用 TCP 送到对面。 这就把「不知道对不对」变成了「只差最后一段协议封装」。
三、四种协议各管一段场景
没有一个协议能通吃,选型看场景。 协议 延迟量级 典型场景
RTMP 1~3 秒 主播上行推流(最常用) HTTP-FLV 1~3 秒 国内网页低延迟播放 HLS 6~30 秒 跨平台、可回看、能过 CDN WebRTC 0.2~1 秒 连麦、会议、超低延迟
延迟差在哪:RTMP 与 HTTP-FLV 是「收到就转」, HLS 要把画面切成几秒一个的 ts 片、再写一个索引,才能播——切片这件事本身就决定了它快不了。 WebRTC 快是因为它换了传输层:走 UDP,丢包不重传,宁可糊一下也不等。 代价是它需要一整套信令与穿透,工程复杂度高一个量级。 所以行业里的常规组合是「上行 RTMP、下行 HLS 或 HTTP-FLV」: 推流端只挑一个协议,播放端按观众设备挑。 服务器在中间做转协议,这一层叫「转推」。
四、延迟是从哪攒起来的
直播的延迟不是一个数,是好几个缓冲加起来的。 环节 攒多少 能不能省
采集缓冲 一帧到几帧 能,但会卡顿 编码缓冲 B 帧越多越久 能,关 B 帧 服务器缓存 一个 GOP 能,改 gop cache 播放器缓冲 几秒 能,但要防抖
第三行那个「一个 GOP」是很多人不知道的: 服务器为了让新观众一进来就能播,会缓存一个关键帧间隔的码流。 这个缓存对延迟的贡献等于一个 GOP 的时长,两秒一个 GOP 就白等两秒。 这条与第八章接上了:GOP 越长压得越好、延迟越大。 所以「清晰又低延迟」是个取舍,直播里常把 GOP 定在两秒,点播才敢定十秒。
五、这一章六节怎么排
按「能不能真跑」来排,不是按教材顺序的难度。 节 讲什么 能不能真跑
13.2 流媒体服务器与握手 能,自己扮一次 13.3 RTMP 推流 能,手工分块推 13.4 两个 C++ 封装类 不能,只讲设计 13.5 OpenCV 磨皮 能,全真跑 13.6 磨皮接进推流 能,全真跑
99 篇里唯一「只讲设计不跑代码」的是 13.4,因为沙箱里没有任何 C++ 编译器, 这一点到那一节会明说。 其余五节都有实测数据,包括最像「只能讲概念」的 13.2。 那一节用两个 socket 把 RTMP 握手真的走一遍,收到的字节数与回抄校验都是真跑出来的。
六、动手 Demo:把直播链拆成五段,逐段问本机能不能做
五段逐段试一遍:抓一帧桌面、建一个 x264 编码器、查 flv 与 rtmp 在不在表里。
import av
def can_capture():
try:
av.open("desktop", format="gdigrab",
options={"framerate": "5", "video_size": "32x24"}).close()
return "能"
except Exception as e:
return type(e).__name__
def can_encode():
av.codec.Codec("libx264", "w")
return "能"
tab = av.formats_available
print("采集", can_capture())
print("编码", can_encode())
print("封装 flv", "能" if "flv" in tab else "不能")
print("推流 rtmp", "能" if "rtmp" in tab else "不能")
print("分发 服务器", "本机没装")
实跑输出:
--------------------------------------------------------------------
把直播链拆成五段,逐段问本机能不能做
--------------------------------------------------------------------
**① 一条直播链就五段**
段 做什么 归哪一层
----------------------------------------------
一 采集:拿画面与声音 AVDevice
二 编码:压成码流 AVCodec
三 封装:装进容器 AVFormat
四 推流:送到服务器 AVIO 协议
五 分发:转给观众 流媒体服务器
**前三段这一本书已经全讲完了**,第四段是协议层,第五段根本不归 FFmpeg 管。
**② 本机逐段验一遍**
段 用什么 结果
------------------------------------------
一 采集 gdigrab **能**
二 编码 libx264 **能**
三 封装 flv **能**
四 推流 rtmp **不能**
五 分发 服务器 没有,本机没装
**五段里四段能真跑,只有第四段的 rtmp 与第五段整段做不了。**
**这一章的重点就在「四段怎么接起来」与「做不到的那段怎么交代」。**
**③ 四种直播协议各管一段场景**
协议 延迟量级 典型场景
------------------------------------------------------
RTMP 1~3 秒 主播上行推流(最常用)
HTTP-FLV 1~3 秒 国内网页低延迟播放
HLS 6~30 秒 跨平台、可回看、能过 CDN
WebRTC 0.2~1 秒 连麦、会议、超低延迟
**延迟差在哪**:RTMP 与 HTTP-FLV 是「收到就转」,
**HLS 要把画面切成几秒一个的 ts 片、写一个索引,才能播**——**切片这件事本身就决定了它快不了。**
**所以行业里的常规组合是「上行 RTMP、下行 HLS 或 HTTP-FLV」**:
**推流端只挑一个协议,播放端按观众设备挑。**
**④ 延迟是从哪攒起来的**
环节 攒多少 能不能省
------------------------------------------------------------
采集缓冲 一帧到几帧 能,但要冒卡顿风险
编码缓冲 B 帧越多越久 能,关 B 帧
服务器缓存 GOP 一个 能,改服务器的 gop cache
播放器缓冲 几秒 能,但要防抖
**第四段那个「GOP 一个」是很多人不知道的**:
**服务器为了让新观众一进来就能播,会缓存一个关键帧间隔的码流。**
**这个缓存对延迟的贡献等于一个 GOP 的时长**,两秒一个 GOP 就白等两秒。
**⑤ 这一章怎么讲**
节 讲什么 能不能真跑
--------------------------------------------------
13.2 流媒体服务器与握手 能,自己扮一次
13.3 RTMP 推流 能,手工分块推
13.4 两个 C++ 封装类 不能,只讲设计
13.5 OpenCV 磨皮 能,全真跑
13.6 磨皮接进推流 能,全真跑
**28 篇里唯一「只讲设计不跑代码」的是 13.4**,**因为沙箱里没有任何 C++ 编译器**,
这一点到那一节会明说。
五段里四段能跑,只有 rtmp 协议与流媒体服务器做不了。 rtmp 不在格式表这件事就是整章写法的依据:能做的做到底,做不到的说清原因。
30 秒实验
- 把
gdigrab换成dshow,看结果变成什么(提示:OSError)。 - 打印
av.formats_available里含rt的所有名字,看 rtsp 在不在。 - 用
av.codec.Codec("libx264","w")读long_name,看它是哪家的实现。
常见误区
- 以为直播链是 FFmpeg 一个人干完的。 第五段是别人的服务器。
- 以为延迟只有一个来源。 采集、编码、服务器、播放器四处都在攒。
- 以为 HLS 慢是协议写得差。 它要先切片,天生就慢。
自测三问(点开对答案)
1. 直播链的五段是什么? —— 采集、编码、封装、推流、分发。 2. 为什么 HLS 比 RTMP 慢一个量级? —— 它要把画面切成几秒一个的 ts 片再写索引,切片本身就要等。 3. 服务器缓存为什么会加延迟? —— 它缓存一个 GOP 好让新观众立刻能播,代价就是一个关键帧间隔的等待。- ☐ (本节完,下一节 13.2 流媒体服务器的搭建)