📹 第五章 FFmpeg二次开发IPC视频监控
📄 一句话概括

监控系统就四段:采集、传输、存储、显示。 延迟和故障都藏在这四段的接缝里——这一节把延迟一段段加起来。

📝 本节和前面几节的关系

上一节讲「要什么」,这一节讲「怎么搭」。四段结构是全章的地图。 缓冲换抗抖动的原理在 26 课,这里只算它的延迟代价。

一、四段结构

段 设备 关键指标
采集 IPC/模拟摄像机 + 编码芯片 分辨率、帧率、码率
传输 网线/光纤/交换机 带宽、丢包、抖动
存储 NVR/IPSAN/云 容量、写入速度、可靠性
显示 客户端/解码器/大屏 解码能力、延迟

这四段的边界就是故障的边界。 排查时先定位在哪一段,比逐个设备试要快得多。 最典型的误判:画面卡就怀疑摄像头,其实八成是传输段的带宽或丢包。

二、延迟是一段段加起来的

人眼对 200 毫秒以内基本无感,超过 400 毫秒开始「说话对不上」。 下面是按规格算的典型值,不是本机实测——本机没有摄像头也没有链路,测不出真的端到端延迟。

环节 典型耗时 说明
采集(曝光 + 读出) 33.3 毫秒 30 fps 一帧就是这么久
编码(软编 1080p) 30 毫秒 实测 240p 是 0.6 毫秒,按像素放大
网络(同城专线) 20 毫秒 跨省会到 50 以上
服务端转发 5 毫秒 流媒体服务器只搬包
解码 15 毫秒 硬解更快
显示(等刷新) 16.7 毫秒 60 Hz 屏幕

采集那一格占了三成,而且是硬下限:30 fps 意味着平均等半帧、最坏等一帧(33.3 毫秒)。 想降延迟就先提帧率——60 fps 能把这一格砍一半,代价是码率翻倍。

三、缓冲:拿延迟换稳定

缓冲是延迟的主要来源之一,但它是「故意加的」。 因为网络会抖,不缓冲就会卡。

缓冲帧数 增加延迟 能抗多大抖动
0 帧 0 0
1 帧 33.3 毫秒 33.3 毫秒
3 帧 100 毫秒 100 毫秒
10 帧 333 毫秒 333 毫秒

缓冲 3 帧只能抗 100 毫秒抖动,而公网抖动经常超过这个数。 所以「低延迟」和「不卡」在公网上没法同时满足——这是物理约束,不是实现问题。 监控的做法是「分码流」:本地主码流不追求低延迟,远程看的子码流才压延迟。

四、三个降延迟手段,各自的代价

手段 省哪一段 代价
tune=zerolatency 编码(去前瞻和 B 帧) 画质差一点
帧率提到 60 采集 + 显示 码率翻倍
TCP 改 UDP 网络(不重传) 丢包直接花屏
硬解 解码 兼容性差

第一行在监控里几乎必开:它关掉 B 帧和前瞻, 代价是同码率画质略降,好处是编码延迟从几百毫秒降到几十毫秒。 第二行要想清楚:帧率翻倍意味着码率翻倍,硬盘也跟着翻倍。降延迟和降成本在这里是直接对立的。

五、动手 Demo:端到端延迟,一点一点加起来

Demo 把六段耗时加起来,再算「缓冲几帧值不值」。 注意这些是规格算的典型值,不是实测——本机没有链路,我不硬编实测数字。

ITEMS = [("采集", 33.3), ("编码", 30.0), ("网络", 20.0),
         ("转发", 5.0), ("解码", 15.0), ("显示", 16.7)]
tot = 0
for name, ms in ITEMS:
    tot += ms
    print("累加到 %s: %.1f 毫秒" % (name, tot))
for n in (0, 1, 3, 10):
    print("缓冲 %d 帧 -> +%.1f 毫秒" % (n, n * 33.3))

实跑输出:

--------------------------------------------------------------------
端到端延迟,一点一点加起来
--------------------------------------------------------------------
**「实时」是个相对词。人眼对 200 毫秒以内的延迟基本无感,超过 400 毫秒就开始「说话对不上」。**
  **这一节把延迟拆开,看每一段各占多少。**

  **注意:下面是按规格算的典型值,不是本机实测**——本机没有摄像头也没有网络链路,
  测不出真实的端到端延迟。**我不硬编实测数字。**

  环节                      典型耗时    说明
  ------------------------------------------------------------------------------
  采集(一帧曝光 + 读出)   33.3 毫秒   30 fps 就是 33.3 毫秒一帧
  编码(软编 1080p)        30.0 毫秒   实测 240p 是 0.6 毫秒,1080p 按像素放大
  网络(同城专线)          20.0 毫秒   跨省会到 50 以上
  服务端转发                5.0 毫秒    流媒体服务器只搬包
  解码                      15.0 毫秒   硬解更快,软解更慢
  显示(等一个刷新周期)    16.7 毫秒   60 Hz 屏幕
  合计                      120.0 毫秒  这就是「点开看到画面」的时间

  **采集那一格占了三成**,而且**它是硬下限**:30 fps 意味着平均要等半帧,
  **也就是 16.7 毫秒,最坏 33.3 毫秒。**
  **想降延迟就先提帧率**——60 fps 能把这一格砍一半,代价是码率翻倍。

**几个常见的「降延迟」手段,和它们各自的代价:**

  手段                        省哪一段                  代价
  ----------------------------------------------------------------------------------
  `tune=zerolatency`          编码(去掉前瞻和 B 帧)   同码率画质差一点
  调高帧率到 60               采集 + 显示               码率翻倍
  TCP 改 UDP                  网络(不重传)            丢包直接花屏
  硬解                        解码                      兼容性差

  **第二行的取舍在监控里最典型**:**降延迟和保画质是矛盾的**,
  因为延迟的来源之一就是「多缓存几帧来抗抖动」。
  **缓冲就是在拿延迟换稳定**——这句话在 26 课讲播放器时说过一次,这里再说一次。

**算一下「缓冲 3 帧」值不值:**

  缓冲帧数      增加延迟        能抗多大抖动
  --------------------------------------------------
  0 帧          0.0 毫秒        0.0 毫秒
  1 帧          33.3 毫秒       33.3 毫秒
  3 帧          99.9 毫秒       99.9 毫秒
  10 帧         333.0 毫秒      333.0 毫秒

  **这张表藏着一个关键结论**:**缓冲 3 帧只能抗 100 毫秒的抖动**,而公网抖动经常超过这个数。
  **所以「低延迟」和「不卡」在公网上是没法同时满足的**,要低延迟就得接受偶尔卡一下,
  **这是物理约束,不是实现问题。**

合计 120 毫秒左右,落在「基本无感」的区间里,但这只是同城专线。 跨省时网络那一段从 20 涨到 50,总数就奔 150 去了。 缓冲那张表是纯算术,但它解释了一个常见困惑: 为什么同一个摄像头,本地看很流畅、远程看延迟大——远程那段缓冲加得更多。

30 秒实验

  1. 把帧率改成 60,重算采集和显示两段,看总延迟降多少、码率涨多少。
  2. 把网络那一段改成 50(跨省),看总数。
  3. 把缓冲加到 10 帧,算总延迟,想想「还能不能实时对话」。

常见误区

  1. 以为延迟只在网络上。 采集和编码加起来占一半,而且采集是硬下限。
  2. 以为缓冲是「实现不好才有的」。 它是故意加的,拿延迟换稳定。
  3. 以为提帧率只影响流畅度。 它还降延迟,但码率翻倍、硬盘翻倍。
自测三问(点开对答案) 1. 30 fps 的采集延迟为什么至少 16.7 毫秒? —— 平均要等半帧才有完整曝光。**最坏等一帧,33.3 毫秒。** 2. 缓冲 3 帧能抗多大抖动? —— 100 毫秒。**公网抖动经常超过这个数**,所以低延迟和流畅不可兼得。 3. 为什么监控要「双码流」? —— 主码流存本地、不追求低延迟;**子码流码率低、压延迟,给远程看**。

下一节把四段变成一个能算的方案:输入路数和天数,输出硬盘和带宽。

相关笔记