ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于庐山派K230的低延迟Web监控系统实战

基于庐山派K230的低延迟Web监控系统实战 1. 项目背景与方案选型1.1 为什么是庐山派K230做视频监控项目很多人第一反应是直接买一套现成的网络摄像头或者用树莓派加USB摄像头折腾。我这次选庐山派K230核心原因是这颗芯片把采集、编码、推流、AI分析这几件监控项目最核心的事都集成到了一块板子上。庐山派K230用的是嘉楠科技的K230芯片双核RISC-V架构主频最高1.6GHz板载KPU神经网络加速单元和VPU视频处理单元。这里面对监控项目最关键的就是VPU它支持H.264/H.265硬件编码也就是说摄像头采集到画面之后可以直接由硬件完成编码压缩CPU几乎不参与。相比之下树莓派做H.264编码要么用软件编码x264吃掉大量CPU要么得外接编码模块成本和复杂度都上去了。另外一个关键点是K230上有MIPI CSI接口可以直接接OV5647、GC2093这类MIPI摄像头模块走的是传感器直连通道比USB摄像头少一层USB协议传输采集延迟更低供电和稳定性也更可控。再加上K230能跑完整的Linux系统V4L2、GStreamer这些标准视频栈都可以直接复用生态上不会像很多单片机方案那样得从零造轮子。1.2 低延迟Web监控的整体架构整个系统的目标很简单浏览器打开页面看到摄像头的实时画面延迟尽量低不需要装任何插件。围绕这个目标我最终采用的架构是端侧采集编码 标准流媒体协议 浏览器端低延迟播放三段式端侧庐山派K230连接MIPI摄像头V4L2采集视频帧VPU硬件编码为H.264传输K230通过RTSP或HTTP-FLV协议将H.264码流对外推送播放浏览器端使用WebRTC或FLV播放器拉流渲染选这种架构而不是直接让浏览器连RTSP是因为浏览器原生不支持RTSP协议除非装插件。所以必须做一次协议转换或者选浏览器原生支持的低延迟协议。实测下来WebRTC端到端延迟能到200到400毫秒MJPEG over HTTP能做到100到200毫秒HTTP-FLV配合MSE播放器在局域网内也能稳定在500毫秒到1秒。这三个方案各有取舍后面会逐个讲怎么落地。1.3 延迟从哪来先弄清瓶颈再动手做低延迟监控最忌讳的就是闷头调参数。我一开始也是先搭通链路再优化结果发现延迟高到没法用只能回头一个个环节排查。搭建之前把延迟来源拆清楚后面能少走很多弯路。完整的视频链路延迟由四部分构成采集延迟、编码延迟、网络传输延迟、播放端缓冲延迟。采集延迟主要来自摄像头感光芯片曝光和ISP处理通常30到60毫秒这块我们能控制的很少但MIPI直连比USB方案至少少5到10毫秒的传输开销。编码延迟和编码器的工作方式强相关如果编码器开了B帧因为要等后续帧到达才能重排延迟会多出2到3帧的时间所以低延迟场景必须关B帧。网络延迟在局域网内可以控制在10毫秒以内但WiFi的抖动和丢包重传会显著拉高。播放端缓冲延迟往往是最坑的很多播放器默认会缓冲2到3秒数据用于抗抖动如果不手动调小前面所有优化都白做。弄明白这个延迟模型之后优化的思路就清楚了编码端关B帧、控制GOP和码率传输端尽量走UDP或低缓冲通道播放端把缓冲拉到最小。2. 硬件准备与环境搭建2.1 庐山派K230开发板与摄像头选型庐山派K230板子我自己用下来对监控项目有用的接口集中在三块MIPI CSI摄像头接口、千兆网口、USB Type-C供电和数据。板子上一共两个MIPI CSI接口可以同时接两颗摄像头做双目或者扩展视角很方便不过本篇只用了一路。摄像头模块方面OV5647和GC2093是K230平台最常用的两款。OV5647就是树莓派Camera V1同款传感器500万像素最大支持1080p 30fps输出兼容性好、资料多CanMV和Linux SDK都默认支持。GC2093是200万像素传感器在低照度场景下的表现比OV5647好一些夜视监控场景优先选它。我这次用的GC2093理由是监控场景经常涉及光线变化这款传感器的动态范围和低光灵敏度更均衡。注意买摄像头模块时一定要确认排线接口方向。MIPI排线是金手指朝背板插入装反了轻则不出图重则烧坏板子接口。我第一次就插反了排查了半小时才反应过来。2.2 系统镜像烧录与开发板初始化庐山派K230支持CanMVPython开发环境和Linux SDK两种方式。监控项目我建议直接用Linux系统因为V4L2、GStreamer这套工具链在Linux下最成熟后续做RTSP推流、程序守护进程都方便。镜像烧录过程比较简单我用的是官方Linux SDK镜像一个SD卡搞定下载K230 Linux SDK镜像压缩包解压后得到.img文件Windows下用BalenaEtcherLinux下用dd命令烧录到SD卡SD卡插入板卡Type-C线连接电源开发板上电启动通过串口终端默认波特率115200登录系统或者插网线通过SSH登录上电之后第一件事是检查系统版本和驱动# 查看系统版本 cat /etc/os-release # 查看摄像头设备节点 ls /dev/video* # 查看V4L2设备能力 v4l2-ctl --list-devices正常情况下MIPI摄像头会被识别为/dev/video0。如果lsusb或者/dev下看不到设备大概率是MIPI驱动没有加载或者摄像头型号与内核配置不匹配。2.3 V4L2摄像头能力确认摄像头驱动正常加载后一定要先确认它支持哪些输出格式和分辨率后面所有编码参数都建立在这个基础上。执行v4l2-ctl -d /dev/video0 --list-formats-extGC2093在K230 Linux下通常直接输出NV12格式也有驱动会暴露MJPEG或H264直出的能力。我这块板子主输出格式是NV12分辨率覆盖640x480到1920x1080帧率最高30fps。这个信息很关键因为VPU硬件编码器吃的就是NV12这种YUV数据不需要再做格式转换省掉一层开销。如果发现摄像头输出的格式和预期不一致可以显式指定# 设置输出格式为NV121920x1080帧率30 v4l2-ctl -d /dev/video0 --set-fmt-videowidth1920,height1080,pixelformatNV12 v4l2-ctl -d /dev/video0 --set-parm30实测过程中如果设置帧率后画面闪烁或者偶发黑帧试试把帧率降到25fps原因是部分摄像头模块在30fps下的时钟同步会有点问题属于传感器的兼容性通病并不是驱动坏了。3. 视频采集与硬件编码实战3.1 用GStreamer验证采集成像确认V4L2设备正常后我用GStreamer先跑通采集到显示的完整链路。K230的Linux SDK里预装了GStreamer及相关插件常用的v4l2src、videoconvert、v4l2h264enc都是现成的。先做一步最小验证——采集画面并编码推流到PC端播放# 在K230上执行将摄像头采集的画面通过UDP传输到电脑 gst-launch-1.0 v4l2src device/dev/video0 ! \ video/x-raw,formatNV12,width1280,height720,framerate30/1 ! \ v4l2h264enc ! \ rtph264pay config-interval1 pt96 ! \ udpsink host192.168.1.100 port5600电脑端用VLC打开网络串流地址填rtp://0.0.0.0:5600只要能出画面说明采集和编码链路没问题。如果画面正常但颜色偏绿偏紫多半是摄像头的白平衡或颜色空间配置问题如果完全黑屏检查一下镜头保护膜是不是没撕这个听起来像段子但真有不少人栽在这。GStreamer这条命令里最关键的一个参数是rtph264pay的config-interval1意思是每隔1秒重复发送一次SPS/PPS参数集。这个参数直接决定了播放端能不能在任意时间点加入并快速出画。如果置为0播放器往往要等很久甚至卡在黑屏直到下一个关键帧到达才能解码。3.2 低延迟编码参数到底怎么调跑通基础链路之后正式开始做低延迟调优。这一步是整篇内容最核心的地方我用实际调试记录的对比来说话。首先是编码器的选择。K230 Linux下VPU硬件编码器通过v4l2h264enc插件调用它支持H.264 Baseline和Main Profile。注意默认配置下编码器会开B帧——对硬件编码器也会开B帧。我从GStreamer的调试日志里看到默认的v4l2h264enc参数帧序是IBBP也就是两个B帧夹一个P帧这种配置下编码延迟至少多出2帧时间。关闭B帧的方法是设置编码器属性gst-launch-1.0 v4l2src device/dev/video0 num-buffers-1 ! \ video/x-raw,formatNV12,width1280,height720,framerate30/1 ! \ v4l2h264enc \ bframes0 \ gop-size60 \ bitrate4000 \ ! h264parse ! \ rtph264pay config-interval1 pt96 ! \ udpsink host192.168.1.100 port5600参数含义对照着说bframes0禁用B帧。这是低延迟的第一要务宁可牺牲一点压缩率也要保证每一帧编码完立刻就能发送不需要等待未来帧gop-size60每60帧一个I帧也就是2秒一次关键帧。这个值不能太大否则播放端加入时等待关键帧的时间会更长但也不能太小因为I帧体积大频繁出现会浪费带宽bitrate4000码率设为目标值。720p30fps下4000kbps的H.264画质足够监控使用此外如果编码器驱动支持CBR恒定码率模式建议开启。CBR模式下码率波动小网络传输更平滑播放端不用频繁处理码率突变。注意不同版本的GStreamer插件属性名可能不一样有的叫bframes有的叫num-b-frames还有的硬件编码器不支持直接设置B帧参数。遇到这种情况先用gst-inspect-1.0 v4l2h264enc查看插件支持的属性列表再对照着调。3.3 硬件编码vs软件编码的实测对比为了验证硬件编码的必要性我做了一组对比实验同样的720p30fps输入分别用x264软件编码和VPU硬件编码记录延迟和CPU占用。编码方式CPU占用编码延迟画面质量同码率4Mbpsx264软件编码ultrafast85%到95%80到120ms一般有轻微马赛克VPU硬件编码10%以下20到40ms更好细节保留完整结果非常明显。K230的双核RISC-V虽然性能不弱但做软件x264编码还是吃力CPU直接跑满延迟还压不下去。切到VPU硬件编码后CPU占用掉到10%以下多余算力以后还可以跑KPU做AI识别——这也是我坚持选K230而不是普通开发板的原因之一。3.4 CanMV模式下的采集方案参考如果你不想折腾Linux和GStreamer庐山派K230还支持CanMV环境可以直接用Python脚本实现MJPEG网络输出。这种方式做快速原型验证很方便但低延迟场景我不推荐因为它用MJPEG编码单帧压缩比低、网络带宽占用大1080p下跑满30fps需要30Mbps以上带宽WiFi环境基本扛不住。它更适合用来做AI视觉验证、图像处理调试这类场景做正式监控项目还是建议走Linux硬件编码路线。CanMV下的示例代码大致长这样体验一把还是可以的import sensor import image import network import socket sensor.reset() sensor.set_framesize(sensor.VGA) sensor.set_pixformat(sensor.RGB565) # 创建socket server循环发送JPG数据 server socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((0.0.0.0, 8080)) server.listen(1)这种写法在局域网内做测试完全没问题浏览器直接打开地址加/stream端口就能看但千万别期待它能有多低的延迟或多高的并发。后面讲的Web端低延迟方案主要还是基于H.264硬件编码。4. Web端实时播放方案的选型与落地4.1 三种方案对比MJPEG、HTTP-FLV与WebRTCK230侧编码推流搞定后回到项目标题的核心诉求——Web端实时监控。浏览器不能直接播放RTSP需要把码流转换成浏览器能消费的协议。我分别实测了三种方案各有明确的适用场景。方案一MJPEG over HTTP这是实现成本最低的方案K230把每一帧画面编码为JPEG图片通过HTTP逐帧推送给浏览器浏览器用img标签直接渲染。我实测在VGA分辨率下延迟可以做到200毫秒左右非常惊艳。但缺点是每帧都是完整JPEG画面稍微复杂一点单帧就到了100KB以上720p下跑30fps需要24Mbps带宽一旦网络拥塞画面就开始卡顿。这个方案最适合开发阶段的链路验证或者局域网有线环境下的小分辨率监控。方案二HTTP-FLV MSE播放器HTTP-FLV是当前Web播放最实用的方案。把H.264裸流封装成FLV格式通过HTTP或WebSocket传输浏览器端用支持MSE的播放器解码播放。K230侧不需要额外做编码只需要把H.264数据塞进FLV容器。我用jessibuca这个播放器实测局域网内延迟稳定在500毫秒左右720p30fps下带宽只有4Mbps画质和流畅度都达到监控项目的基本要求。兼容性方面主流浏览器全部支持。方案三WebRTC这是延迟最低的方案实测能做200到400毫秒。但WebRTC是P2P架构需要信令服务器来交换SDP和ICE候选K230侧要么集成信令服务端要么依赖外部服务器转发。K230跑WebRTC链路对算力和内存都有一定压力尤其DTLS/SRTP加密协商过程本身就要消耗不少CPU。如果项目对延迟的要求是必须打游戏级别的同步那就选这个方案否则HTTP-FLV的性价比更高。4.2 推荐实战路线RTSP推流 webrtc-streamer转换考虑到开发效率和最终效果我推荐的组合拳是K230负责RTSP推流拉流端用webrtc-streamer把RTSP转成WebRTC浏览器播放。这套路线的优势在于K230侧只需专注推流不用操心WebRTC的复杂协议栈转换工作由独立进程完成K230的CPU占用可以压到最低。K230侧启动RTSP ServerLinux SDK自带的sample代码可以直接参考。进入SDK的sample目录找到rtsp_server相关的示例编译运行./sample_rtsp_server默认情况下它会使用板载摄像头并开启RTSP服务端口8554。用VLC验证一下# 在PC端执行或者直接在VLC图形界面打开地址 ffplay rtsp://192.168.1.188:8554/liveRTSP跑通后在PC上跑webrtc-streamer./webrtc-streamer rtsp://192.168.1.188:8554/live浏览器访问http://localhost:8080选择对应的视频流即可。webrtc-streamer内部完成了RTSP拉流、解码、重新编码WebRTC格式或者直接转封装浏览器端走原生WebRTC协议不需要任何插件。注意webrtc-streamer默认监听TCP端口8080SDK拉流时RTSP使用TCP连接如果遇到局域网防火墙记得放行8554和8080端口。另外webrtc-streamer颜值不高但是功能稳定Production环境做二次开发时可以考虑用它的WebRTC前端库。4.3 更轻量的备选H.264 over WebSocket HTML5播放如果你的Web端不想引入webrtc-streamer这种独立服务另一条实际可行的路是K230把H.264码流通过WebSocket推给浏览器浏览器端用MSEMedia Source Extensions直接解码播放。K230侧写一个简单的WebSocket服务端将编码后的H.264数据按帧发送。浏览器端维护一个Buffer队列按顺序append到SourceBuffer里。// 前端核心逻辑伪代码 const ws new WebSocket(ws://192.168.1.188:8080/video); const mediaSource new MediaSource(); const video document.getElementById(player); video.src URL.createObjectURL(mediaSource); mediaSource.addEventListener(sourceopen, () { const sourceBuffer mediaSource.addSourceBuffer(video/mp4; codecsavc1.42E01E); ws.onmessage (event) { sourceBuffer.appendBuffer(event.data); }; });这里有个前端的坑需要提醒如果K230侧只发H.264裸流不带时间戳浏览器MSE会因为没有正确的decodeTimestamp而判定数据无效。所以要么在发送前用h264parse把流封装成fMP4片段要么用appendWindowStart等API手工处理时间戳否则画面会只出第一帧或者完全黑屏。这个方案的优点是省掉了翻译服务缺点是调试成本高需要自己处理协议细节所以实际项目中我更推荐先走RTSP转换服务这条路。4.4 浏览器安全上下文问题这个坑是Web开发者的老朋友了。浏览器规定页面只有在HTTPS或localhost环境下才能使用getUserMedia等WebRTC采集接口。如果你部署的内网监控页面用的是HTTP协议且访问地址不是localhost浏览器会直接拒绝访问摄像头或者麦克风设备控制台报错当前页面非HTTPS安全上下文无法访问摄像头/麦克风。那浏览器播放RTSP转WebRTC的流是否也会被限制答案是如果只做拉流播放不调用getUserMedia采集本地设备那不受限制HTTP下也能播放。但如果你想让浏览器端也能主动采集摄像头比如做多路视频会议、双向对讲就必须给内网部署一套HTTPS证书。自签名证书会有浏览器安全警告要么用mkcert工具生成本地受信任的证书要么在内网搭建私有CA。这些都属于部署细节开发时可以先用HTTP跑通上线前再补证书。5. 延迟实测与问题排查实录5.1 延迟测量方法与实测数据优化做完了总得有数据说话。这里分享一个最土的延迟测量方法用手机秒表计时屏幕显示秒表画面把这个画面放在K230摄像头正前方同时用PC浏览器打开Web端监控页面对准屏幕拍摄一张照片。照片里秒表读数差异就是端到端延迟。我用这个方法在以下条件下实测了最终系统的延迟摄像头GC2093720p 30fps编码VPU硬件H.264720p30fps4Mbps传输K230接有线千兆网PC接同一交换机播放WebRTC方案场景端到端延迟局域网有线720p30fpsWebRTC播放260到380毫秒局域网有线720p30fpsHTTP-FLV播放520到800毫秒同一WiFi720p30fpsHTTP-FLV播放1.2到2秒同一WiFiVGA30fpsMJPEG播放350到600毫秒数据一目了然网络环境对延迟的影响比编码方案更明显。WiFi下的延迟波动主要来自网络抖动和播放器为抗抖动而增加的缓冲有线环境下WebRTC的延迟优势才能完全发挥。5.2 常见问题速查表整个项目折腾下来我把踩过的坑整理成一张速查表遇到的问题和对应的解决方案都列在这里症状可能原因解决方案摄像头无画面MIPI排线方向装反或未插紧关机重新插拔排线金手指朝背板方向摄像头无画面驱动未加载检查/dev/video0设备节点重新加载驱动模块画面花屏或绿屏ISP颜色格式配置错误将采集格式从RGGB改为BGGR或改用NV12直出画面卡顿严重Wi-Fi信号波动或带宽不足换有线网络或将分辨率降到VGA、码率降到2Mbps延迟突然拉高播放端缓冲过大手动调播放器缓冲参数最小化bufferTime播放器黑屏SPS/PPS参数未周期性发送在打包层设置config-interval1画面冻结过几秒恢复关键帧间隔过长缩小gop-size建议2秒一个I帧浏览器无法播放RTSP协议浏览器不支持必须转换成WebRTC或HTTP-FLV使用对应的播放器板子发热严重高码率编码导致VPU满载增加散热片和小风扇帮板子控制好温度5.3 供电和散热这两个坑最容易忽视庐山派K230在跑满编码器推流的时候发热量真不是闹着玩的。我刚开始裸板跑720p30fps硬件编码半小时后摸散热片已经烫手接着就开始偶发掉帧。定位到是VPU过热降频导致的问题。解决方法是加装散热片加5V风扇实测温度稳定在60度以下掉帧问题彻底消失。供电方面K230上跑硬件编码时MIPI摄像头和VPU同时工作峰值电流能到1.5A以上。我一开始用一个普通的手机充电头供电结果发现摄像头偶尔会出现条纹干扰换了5V/2A的电源之后问题消失。如果手边有示波器可以看看供电电压的纹波纹波太大时摄像头画质会明显下降。监控系统这种东西一跑就是24小时供电和散热这块的钱省不得。5.4 布线和网络部署的实战建议开发阶段怎么折腾都行但系统真要实际部署几点建议是我亲身换来的经验优先有线网络。即便你的路由器信号满格WiFi的帧间延迟抖动也无法预测想要稳定低延迟就必须用网线如果必须WiFi尽量把K230和路由器放同一房间信道选5GHz且避开邻居占用高的信道K230板载网口支持千兆但实际推流4Mbps码流百兆足够不用纠结交换机的档次摄像头安装位置避免强逆光和频繁闪烁的光源这些会导致码率飙升、画质劣化间接拉高延迟多路监控时每路码流控制在4Mbps以内比较稳妥带宽利用率不需要满留出余量能换来更好的稳定性6. 方案扩展与个人经验总结整个项目做下来我对这个系统最大的体会是低延迟监控的难点不在某一个环节而在每个环节都得踩在正确的位置上。采集端用MIPI直连、编码端开硬件编码关B帧、传输端走UDP、播放端压缩缓冲每一个决定单独看都不难但只有全部串起来延迟才能从能用变成好用。项目本身的扩展空间其实很大。K230这颗芯片上的KPU目前还闲着完全可以做移动侦测、人形识别、区域入侵报警这类AI能力一旦检测到事件再录制高码率视频或推送通知比一直满码率录制省资源的得多。又或者把多台K230组成摄像头集群统一接入一台流媒体服务器做一个多视角的Web监控平台。再进一步把录制的视频片段接入对象存储做一个自动滚动覆盖的云录像系统这套架构也可以平滑演进。工具链方面调试阶段多依赖V4L2和GStreamer的命令行工具它们虽然看起来不起眼但信息密度极高。gst-launch-1.0配合环境变量GST_DEBUG可以看到完整的管线状态比猜问题效率高得多。最后分享一个我自己的调试习惯每次改动参数后用固定方法测一次延迟并记录下来。延迟这个东西不量化就优化不了今天觉得快了明天又来一个现象没有基线数据根本说不清改动有没有生效。把每次修改的编码参数、网络环境和延迟数据记录在表格里后面复盘和排障都会非常高效。
返回列表