3、推流核心原理:视频采集 → 编码 → 封装 → 推流

这一章,我们聊聊推流的完整链路。

说白了,就是把摄像头或屏幕的画面,经过压缩、打包,最后通过 RTSP PUT 命令发出去。我刚开始接触这个流程时,总觉得每一步都很神秘。后来亲手搭了一遍,才发现核心逻辑其实很清晰。

核心链路: 视频采集 → 编码(H.264/H.265)→ 封装(RTP/RTCP)→ 推流(RTSP PUT)

RTSP推流核心链路流程图 RTSP 推流核心链路 视频采集 摄像头 / 屏幕 编码 H.264 / H.265 封装 RTP / RTCP 推流 RTSP PUT 关键说明: • 采集:获取原始视频帧(YUV/RGB),帧率通常为 15~30 fps • 编码:压缩原始数据,H.264 码率控制是关键,H.265 压缩率更高但计算开销大 • 封装:将编码后的 NAL 单元切片打包成 RTP 包,RTCP 负责反馈和同步 • 推流:通过 RTSP PUT 命令将 RTP 流发送到服务器

3.1 视频采集:从哪里拿到原始画面?

采集是整个流程的起点。你想想看,没有原始画面,后面编码、推流全是空谈。

常见的采集源有两种:

  • 摄像头(Camera):通过 V4L2(Linux)或 DirectShow(Windows)驱动获取帧数据。我习惯用 V4L2,因为它稳定,而且支持多种像素格式。
  • 屏幕(Screen):通过 X11、Wayland 或 Windows DXGI 抓取桌面画面。适合做录屏或直播。

采集到的原始数据通常是 YUV420P 或 RGB24。YUV 格式更常见,因为编码器直接吃它。

我的经验: 采集时一定要注意帧率控制。我曾经在项目中直接 while 循环读摄像头,结果 CPU 跑满,画面还卡顿。后来加了帧率限制(比如 30fps),问题就解决了。

3.2 编码:H.264 还是 H.265?

原始视频数据太大了。举个例子,1080p 的 YUV420P 一帧大约 3MB,30fps 就是 90MB/s。这带宽谁也扛不住。

所以必须编码压缩。H.264 和 H.265 是主流选择。

特性 H.264 (AVC) H.265 (HEVC)
压缩率 基准 比 H.264 高 30%~50%
计算开销 较低 较高(约 2~3 倍)
兼容性 几乎所有设备支持 较新设备支持
码率控制 CBR/VBR/CRF CBR/VBR/CRF
典型应用 直播、监控、视频通话 4K/8K 视频、高清直播

我个人习惯用 H.264 做直播,因为兼容性好,解码器遍地都是。H.265 虽然压缩率高,但编码器吃资源,推流端如果性能不够,反而会掉帧。

注意: 编码参数里,关键帧间隔(GOP)很重要。RTSP 推流一般设 2~3 秒一个关键帧。太长了,客户端拉流时等待时间长;太短了,码率会飙升。

3.3 封装:RTP 和 RTCP 在干什么?

编码后的数据是 NAL 单元(H.264)或 NAL 单元(H.265)。但网络传输不能直接扔 NAL 包,得用 RTP 协议封装。

RTP(Real-time Transport Protocol) 负责承载媒体数据。每个 RTP 包包含:

  • 时间戳(Timestamp)—— 用于播放同步
  • 序列号(Sequence Number)—— 用于丢包检测和排序
  • 负载类型(Payload Type)—— 标识编码格式
  • SSRC —— 同步源标识

RTCP(RTP Control Protocol) 负责控制信息。它不传媒体数据,而是传:

  • 发送报告(SR)—— 统计发送的包数、字节数
  • 接收报告(RR)—— 统计丢包率、抖动
  • 应用自定义包(APP)—— 扩展用

说白了,RTP 是快递员,RTCP 是客服。快递员送货,客服反馈有没有丢件、延迟多少。

封装流程: NAL 单元 → 分片(如果太大)→ 添加 RTP 头 → 打包成 RTP 包 → 发送

H.264 的 NAL 单元大小不一。如果 NAL 单元超过 MTU(通常 1500 字节),就得分片打包。我遇到过一个问题:分片顺序错了,客户端解码直接花屏。后来加了序列号校验才解决。

3.4 推流:RTSP PUT 到底怎么用?

RTSP 协议里,推流用的是 PUT 方法。但注意,RTSP 本身不传媒体数据,它只负责建立和控制会话。真正的媒体数据是通过 RTP 传输的。

推流流程大致如下:

  1. 客户端发送 OPTIONS 请求,确认服务器支持的方法
  2. 客户端发送 DESCRIBE 请求,获取媒体描述(SDP)
  3. 客户端发送 SETUP 请求,建立传输通道(UDP 或 TCP)
  4. 客户端发送 PUT 请求,开始推流
  5. 客户端持续发送 RTP 包,服务器接收并转发
  6. 推流结束,发送 TEARDOWN 请求关闭会话

避坑指南: 我曾经在 SETUP 阶段忘了指定传输模式(interleaved 或 UDP),结果服务器一直收不到数据。后来我统一用 TCP interleaved 模式,稳定多了。

下面是一个简化的 RTSP PUT 请求示例:

PUT rtsp://192.168.1.100:554/live/stream RTSP/1.0
CSeq: 4
Session: 12345678
Content-Type: application/x-rtp-stream
Content-Length: 1024

[RTP 数据包...]

注意,实际推流时,RTP 数据是持续发送的,不是一次性发完。服务器会持续接收直到收到 TEARDOWN。

3.5 整体流程回顾

把上面四步串起来,就是完整的推流链路:

  • 采集:从摄像头或屏幕获取 YUV 帧
  • 编码:用 H.264/H.265 压缩成 NAL 单元
  • 封装:将 NAL 单元打包成 RTP 包,RTCP 负责反馈
  • 推流:通过 RTSP PUT 命令发送 RTP 流到服务器

每一步都有坑,但核心逻辑不复杂。你只要把数据流想象成一条流水线:原材料进来,经过加工、包装,最后发货。嗯,就是这么回事。

一句话总结: 推流就是把原始画面压缩、打包、发出去。H.264 是主力,RTP 是载体,RTSP PUT 是命令。