基于开源RTSP服务器的AI视觉低延迟推流链路设计与实践

发布时间:2026/10/18 6:19:40
基于开源RTSP服务器的AI视觉低延迟推流链路设计与实践 做AI视觉也有一阵子了。前几年发愁的主要是模型怎么提准后来发现更头疼的是另一件事检测结果明明很快可推流到显示器上总是慢半拍画面都过了二十米框还卡在人身后。试过不少官方平台推流方案延迟基本都在几百毫秒甚至一秒以上。后来我基于开源RTSP服务器组件做了一套实时视频转发链路普通安防摄像头接进来AI检测画面直接叠加后重新推流内网实测端到端延迟降到了140毫秒以内体感上已经是接近于实时的画面。这篇文章把整体思路、关键参数、实测数据和踩坑记录全部拆开讲适合正在做摄像头接入、目标检测、事件识别这类项目的开发者参考。1. 为什么需要一套“画面直通”的RTSP链路1.1 传统推流方案慢在什么地方很多人以为AI检测项目的延迟主要来自模型推理时间实际上并不是。一个中等规模的检测模型单帧推理只要二三十毫秒而视频画面从摄像头到浏览器往往要经过三四道“中间商”。传统做法通常是这样的摄像头先把RTSP流推到某个云平台云平台转码成HLS或FLV协议再分发到Web端播放。这段链路里最花时间的是转码和缓冲。转码要等关键帧重新计算播放端为了保证流畅又会主动攒几百毫秒的数据。再加上公网来回的传输时间延迟很容易突破1秒。在项目演示、值班监控、远程操作这类场景里一秒延迟意味着你在屏幕上看到的已经是被检测物体离开后的画面。就算你的模型识别率再高实际使用体验还是拉胯。所以我做这套链路时定的原则很简单能不转码就不转码能不缓存就不缓存。1.2 为什么直接用RTSP而不是重新选协议安防摄像头最通用的协议就是RTSP只要支持ONVIF标准的设备基本都对它有原生支持。这意味着不需要改摄像头固件不需要在设备上装额外Agent只要拿到设备的IP、端口、用户名密码就能取到视频流。另外RTSP本身非常适合局域网低延迟传输。视频数据传输走的是RTP链路是面向实时的UDP制式只要网络不丢包数据到了直接解帧显示天然没有长时间缓冲的毛病。相比之下HLS切片协议为了保证协议可承载性故意把数据切成了3到6秒一个分段低延迟方案根本不可能在它身上落地。我做这套服务器的时候选型很简单底层用开源媒体服务做RTSP的接收与分发上层用级联推流加AI推理标注模块。这样既能拉开灵活性又不用重复造协议轮子。1.3 整条链路的完整处理路径先画一张逻辑链路图用文字描述就是摄像头RTSP原始流 - 拉流端解码 - AI模型推理与目标叠加 - 标注后的画面重新推流到本机RTSP服务器 - 多个客户端实时拉取观看这里有一步需要特别说明我没有采用“只转发不处理”的纯中转方式因为AI检测的画面必须叠加检测框和标签。如果直接在原始流上做转发那看到的就是没有AI结果的裸画面价值大打折扣。但另一方面我也尽量不做多次转码。典型的做法是只解码一次、叠加一次、编码一次然后交给RTSP服务器分发。每一步都尽可能避免多余的缓冲这是后面能保持低延迟的关键。2. 零延迟RTSP服务器的原理与参数基础2.1 RTSP、RTP这些协议到底怎么理解聊技术之前先帮不熟悉的同学把概念理清楚。RTSP是控制协议它负责“点菜”客户端通过DESCRIBE问服务器有哪些媒体信息通过SETUP确定怎么收通过PLAY开始播放。而实际的视频数据走的是RTP协议相当于后厨往上菜口送菜。至于RTCP则是客户端和服务端之间对账用的比如统计丢包、延迟等。这里面的关键点是RTSP本身不做视频数据的传输它只负责“调度”。所以优化延迟的时候真正的重点应该放在RTP传输层面以及解码播放层的缓冲策略上。你还可以打个生活化比方RTSP像餐厅服务员负责记录客人需求RTP是传菜电梯负责把菜送到餐桌而播放器里的缓存区就相当于客人面前堆着的一排碟子——如果服务员为了保险把所有菜先攒齐再一次性上第一口饭就注定要晚很久。2.2 延迟到底从哪里来我整理出的三类来源我把实际测试中遇到的延迟来源归成三类。第一类是编码参数带来的结构性延迟。视频编码中用到的GOP长度、B帧策略直接影响延迟。GOP指的是两个关键帧之间夹了多少个普通帧播放端要等到关键帧才能开始解码所以GOP越长初始延迟越大。B帧是双向预测帧它会引用后面帧的数据导致解码时必须等后边的帧到了才能完整解出当前帧这对低延迟是很不友好的。第二类是网络缓存和抖动缓冲。播放器为了对抗网络抖动会在接收端开缓冲区等拿到足够的数据才开始播放。这个缓冲区越大画面越稳但延迟也越高。很多播放器默认缓冲策略偏保守所以延迟高的根源真不在服务器而在播放端。第三类是系统本身的转码处理延迟。只要编码格式转换就必须等到一个完整帧数据的输入输出再加上CPU调度和内存拷贝延迟几十毫秒是正常的。多次转码就会叠加出几百毫秒。2.3 零延迟方案到底怎么配置才算落地我的思路是“三路并进”第一编码侧尽量使用低延迟参数。摄像头端如果支持的话把编码档位调到“低延迟”或“极速档”关闭B帧GOP设置为1秒或者更短确保播放端等待关键帧的时间很短。很多安防摄像头的后台设置里都有一栏“编码档位”很多人默认用“均衡”或“流畅”改到“极速”之后画面延迟肉眼可见地减小。第二服务端只做单帧处理不排队、不聚合。神经网络的推理过程只依赖当前帧不能用攒一批再处理的方式。我实际实现时用的是逐帧回调处理完立刻写回RTSP服务服务端层面也尽量做无队列直接透传。第三播放端关闭缓冲。能手动设置缓冲时间的播放器就把它调到最小或直接设为0用FFmpeg命令行拉流时对应参数可以调成实时流模式。后面讲播放器的时候我会给具体示例。需要说明的是这里说的“零延迟”其实是一个工程目标不是真的0毫秒。我在局域网内测出来的端到端延迟能到120到140毫秒级别对活体检测和实时报警这种场景已经足够贴近实时了。3. 核心实现从摄像头到AI再到客户端3.1 服务器部署与依赖准备我建议用一个独立的Linux服务器来做这套RTSP服务不跟摄像头直连的笔记本放在一起避免无线网络波动影响效果。硬件方面一台CPU稍好一点的普通主机就够了未必需要插独立显卡。如果AI模型比较大可以用支持NVIDIA推理加速的机器或者用带有边缘算力的盒子。软件方面我用的是开源媒体服务作为RTSP网关然后再用Python封装一层推理推流逻辑。需要用到的核心组件包括开源RTSP服务程序负责监听8554端口接收推流把流分发给多个拉流端GStreamer或FFmpeg负责拉取摄像头RTSP流、解码、编码以及最终的推流Python、OpenCV、目标检测模型负责AI推理和检测框叠加实际部署时不需要装一大堆软件装好上面这几样就够跑了。3.2 摄像头取流地址与编码参数配置安防摄像头的RTSP地址通常有固定格式但不同厂商会有差异。最常见的格式类似下面这样rtsp://用户名:密码摄像头的IP地址/Streaming/Channels/101其中末尾的101通常表示主码流102表示子码流。做主码流时分辨率高、码率高画质好但帧频可能受传感器限制子码流分辨率低码率低更适合在带宽有限时用作检测输入。我在方案里建议用主码流做检测和推流的上游同时把摄像头的编码设置为H.264。因为H.264的兼容性最好播放端几乎都能直接解。摄像头端还需要注意两个参数关键帧间隔也叫I帧间隔设置为50或更小相当于2秒一个关键帧。如果设太大播放时按秒级的时间才等到第一帧延迟感会特别明显。码率上限根据实际分辨率设置1080P的话可以设定4Mbps到6Mbps之间保证画面细节和传输稳定。这些都是基于常见安防摄像头的通用设置不是只针对某一品牌。实际界面里的文字可能叫法不同但内部原理是通用的。3.3 AI检测推理与叠加推流的代码骨架核心的AI推理推流部分我用Python写了骨架代码。关键点是拉流、推理、叠加、推流四个环节串成一条直通管道不在中间堆积帧。import cv2 import time import numpy as np # 拉取摄像头RTSP流这里用OpenCV的VideoCapture cap cv2.VideoCapture(rtsp://你的摄像头地址/Streaming/Channels/101) # 设置读取缓冲为尽量小避免OpenCV端的输入缓冲积压 cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 输出编码参数使用MP4V或H264编码均可关键是要和推流目标匹配 frame_width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps int(cap.get(cv2.CAP_PROP_FPS)) # 创建VideoWriter输出到本机RTSP服务器的某个路径 out_rtsp_url rtsp://127.0.0.1:8554/ai_result writer cv2.VideoWriter( out_rtsp_url, cv2.VideoWriter_fourcc(*H264), fps, (frame_width, frame_height) ) # 加载你的检测模型这里以OpenCV DNN读取ONNX模型为例 net cv2.dnn.readNetFromONNX(det_model.onnx) while True: ret, frame cap.read() if not ret: # 摄像头断流时等一会儿再重连 time.sleep(0.5) continue start time.time() # 正常推理流程 blob cv2.dnn.blobFromImage(frame, 1/255.0, (640, 640), (0, 0, 0), swapRBTrue) net.setInput(blob) outputs net.forward() # 对检测结果画框和标签略根据自己的模型输出结构写 # frame draw_detections(frame, outputs) # 写出一帧推到RTSP服务器 writer.write(frame) # 控制推理帧率避免无限占用CPU fps 1.0 / (time.time() - start)这里有两个细节值得展开说说。第一个是OpenCV的CAP_PROP_BUFFERSIZE很多人在用OpenCV拉RTSP流的时候遇到延迟大其实和这个缓存关系很大。默认情况下OpenCV会尽量缓存几帧保证处理不卡顿可一旦推流端帧率高、处理端跟不上缓存区就一直排队延迟就变得越来越高。把它设为1配合循环里的即时读取能有效减少输入排队延迟。第二个细节是VideoWriter推流地址指向本机的RTSP服务端口。这样摄像头原始流在AI处理后有了一条独立的推理后链路多个客户端只从本机RTSP服务器拉流不需要各自重新推理节省整体算力。这个两级结构对部署很关键一台终端设备上的推理结果可以同时被多块屏幕观看。3.4 客户端实时播放的调整方法如果把视频推到RTSP服务器之后直接用默认播放器拉流可能还是会发现延迟不小。问题多半出在播放端。我通常用FFmpeg命令行来做快速验证命令大致是这样的ffplay -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 0 -rtsp_transport tcp rtsp://127.0.0.1:8554/ai_result这里几个参数的作用是-fflags nobuffer关闭播放器的整体缓冲。-flags low_delay启用低延迟解码模式。-probesize 32限制启动探测的数据量让画面尽早出来。-analyzeduration 0不要求分析足够多的媒体数据再开始播放。-rtsp_transport tcp强制走TCP传输避免UDP在复杂网络环境下的丢包抖动。如果是局域网环境且网络很干净把TCP改成UDP能进一步减少传输开销但代价是对丢包更敏感。视频监控车间这种场景推荐TCP稳定优先延迟差异其实只有几毫秒。如果项目方一定要用浏览器看画面可以再叠加一层WebRTC网关把RTSP流桥接给浏览器原生播放。浏览器不能直接播放RTSP但它对WebRTC的支持很好延迟也控制在低延迟范围内。这一步会让链路稍微复杂一些但整体依然比云平台方案低不少。4. 实测记录与常见问题排查4.1 用手表对着屏幕拍延迟到底多少测延迟的方法很多但最直观的就是“摄像头前放一个精度到0.1秒的电子秒表把显示终端摆在旁边手机对着两者录一段视频然后逐帧看秒表跳到某一秒和画面显示到那一秒的时间差”。我拿这个办法在办公室做了几次实测结果差得还挺明显链路方案端到端延迟备注摄像头 - 云平台 - 浏览器播放780ms - 1200ms随公网波动摄像头 - 本地RTSP转发 - 播放器200ms - 260ms纯转发无AI摄像头 - AI推理叠加 - 本地RTSP - 播放器120ms - 140ms当前方案实际效果这个结论说明一个事AI推理本身不是延迟的大头要不要经过大量转码、缓存才是。检测模型推理一帧不超过三四十毫秒只要管道顺畅总时长就能控制在200毫秒以内。另外我也测过不同摄像头设置对延迟的影响。把GOP从默认的75帧缩短到25帧把编码档位从“均衡”调成“极速档”首帧出现时间能明显提前整体延迟也降了30毫秒左右。4.2 花屏、卡顿、断流问题怎么排查我在实际项目里遇到过三个高频问题基本都能通过调整参数解决。第一个是播放画面花屏或者前几秒马赛克。这种现象多数是GOP和丢包共同作用的结果。GOP太长时播放器在半路进入流等不到关键帧就只能解码残缺的参考帧画面自然花了。解决方法是缩短关键帧间隔并让摄像头和播放器都使用同一个传输协议避免TCP和UDP来回切换导致的不连贯。第二个是AI推理推流一段时间之后开始掉帧画面像幻灯片。这通常是处理速度跟不上输入速度。我们看到推流端的while循环是按摄像头帧率跑的但推理耗时可能大于帧间隔。这时候应该主动丢帧比如在检测队列里只保留最新一帧而不是继续用队列缓冲。丢一帧推理结果远比播放画面延迟累加要好。第三个是客户端看一会儿就断流需要手动重连。原因一般是服务器侧的连接超时设置过短或者摄像头端达到最大并发连接数。调整方法有两步一是把RTSP服务器的超时时间适当调大二是限制单个摄像头的直连数量让AI处理模块只用一个连接取流客户端全部从本机服务器取流转发不要每个客户端都直接连摄像头。4.3 多路摄像头接入时的带宽与并发控制这套零延迟RTSP服务器还有一个使用场景就是同时接入多路摄像头画面。我在实验室一次性接8路1080P摄像头本地RTSP服务完全扛得住但网络带宽先成了瓶颈。8路×5Mbps的码率大约是40Mbps普通无线很难稳定支持。解决办法是给每路视频分主码流和子码流。检测与叠加可以用子码流720P或960P就够带宽占用只有主码流的三分之一而最终推流到播放器时如果想要更高画质再切回主码流。像“地磅识别”“人数统计”这种对分辨率要求不高的场景全链路用子码流就够了。并发播放端的数量也要有数。开源RTSP服务本身能支撑几十路并发拉流但消耗的是服务器的带宽出口。外网观看时服务器上行带宽决定了能同时放几路。比如服务器上行只有50Mbps那一路1500Kbps的子码流最多只能同时播放30路左右。超了就会卡顿。5. 不同场景怎么用以及我个人的真实建议5.1 适合用这套方案的场景我自己落地过的项目里有三类场景特别适合这套零延迟RTSP服务器。第一类是质检工位。检测结果需要立即反馈到产线屏幕操作员看到框的同时就要做出判断根本接受不了一秒以上的延迟。用这套链路后AI框几乎是跟着实物走的操作员舒适感提升非常多。第二类是值班室监控。值班员需要快速从大屏上发现异常而不是盯着一个延迟滞后的画面猜下一秒发生什么。多个大屏同时拉取AI标注后的流服务器只需要推一路标注结果节省值班室的整体算力。第三类是专业演示和验收。给客户做技术验证时客户往往要求亲眼看“模型识别到目标后框跟着动”。如果画面延迟大到目标都走出了视野演示效果就直接翻车。低延迟链路是这类场景的刚需。5.2 不建议做什么这套方案不适合拿来替代大规模录像存储系统。RTSP低延迟追求的是“实时”而存储强调的是不断流、不丢失两者优先级不同。如果要长时间录像归档建议摄像头同时开辟一路流给NVR做存储AI检测单独走低延迟转发互不干扰。它也不太适合公网超长距离传输。走公网时网络抖动和带宽波动都会严重影响低延迟效果UDP丢包会导致画面频繁花屏。这时应该换成WebRTC或SRT这类抗弱网更友好的协议而不是硬扛RTSP。我之所以一直说局域网内测就是不想让大家误以为任何公网环境都能轻松跑到140毫秒。5.3 几条真正值钱的实战建议根据我自己的经验最后分享几个容易被忽略的细节。第一摄像头和服务器尽量用网线直连。无线网络就算信号很好偶尔一个几十毫秒的波动对于1秒延迟无所谓但对140毫秒的低延迟链路是致命的。第二给摄像头分配固定IP避免系统重启后RTSP地址变化导致整个链路失效。这个问题在长期运行的项目里特别常见服务器端代码不会自动适配但配置好固定IP后根本不用考虑它。第三不要盲目追高码率。在实际项目中把1080P的码率从8Mbps降到4Mbps肉眼几乎看不出差别但带宽压力小一倍花屏概率大幅下降。第四在做AI推理推流时要把模型推理结果的展示和处理并行化。比如画框、写文字这些操作可以放到单独线程执行避免阻塞主循环读取摄像头新帧。我在早期版本里就是因为画框花了30毫秒导致整体延迟增加了近一倍。我在实际使用中发现这套链路最大的价值不是“数字上有多少毫秒”而是当检测结果真正到达现场应用时不再让工作人员产生那种“画面慢了半拍”的别扭感。无论是值班监控还是项目演示能实时看见AI的眼光才是这些系统真正落地可信的前提。这套基于开源RTSP服务器的改造思路后续还可以扩展出WebRTC低延迟网页端、SRT公网传输等变种但核心的“少转码、少缓存、逐帧直通”这条原则始终不会变。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询