给几百 GB 监控瘦身:一个从 freezedetect 一路打到 NPU 的迭代血泪史

故事有一个非常普通的开头:'家里监控攒了几百 GB,能不能压一压?'。需求也很朴素——画面没动静的时候就别存了。谁能想到这句话最后把我带着走完了从 freezedetect 到 YOLOv8n、从怀疑人生到 240 张/秒的全过程。这篇就是那条完整的折腾轨迹,数字全是我那台 Core Ultra 5 235H 上一格一格记录下来的。

机器:Core Ultra 5 235H / Arc 140T / NPU / OpenVINO 2026.5.0.dev / ffmpeg 9.0.1 / Windows。时间跨度 2026-09-05 ~ 09-13。

第一幕:freezedetect 对着噪点怀疑人生

第一版方案很'常识':用 ffmpeg 的 freezedetect 找出'画面冻结'的段落,剪掉就完事了。demo 跑通了,第一版 180s 压缩到 66s,当时觉得今天收工了。然后晚上把真素材喂进去,发现不对:

  • 监控夜晚全是噪点:传感器抖动让'静止画面'看着处处在动,freezedetect 把动静全放行了
  • 调 n 参数扫表发现 -48dB 是峡谷(26%活动)而其他档都在 40~78%——阈值敏感又非单调
  • 它区分不了'静止'和'有人'——有人站在不动和没人画面,帧差是一回事

最开始我还想用更聪明的阈值、更宽的窗口去补救,折腾了几个小时,最后还是用户的一句话把方向拍死了:'检测标准就是有人就保留。'这根本不是阈值问题,是语义问题。freezedetect 这类运动检测,死刑。

第二幕:手写 OpenVINO 前后处理,团灭

既然要'识别有人',就得请出目标检测。这台机器的 NPU 摆着不用可惜,于是我把 yolov8n.pt 导成 OpenVINO IR,然后——手写 letterbox、手写 BGR、手写 NMS 坐标解码。结果没有任何一套能跑对:检测框坐标乱飞、置信度全不对、FCOS 解码也翻车。

折腾了接近两天之后,认输的方式很彻底:推理必须走 ultralytics 官方路径 model.predict(device="intel:NPU"),前后处理它全包。之前所有'我自己写解析'的时间全部打了水漂——这大概是整个故事里最贵的一课,也是我最想让你避开的坑。

第三幕:'GPU 很慢'是个假消息

官方路径跑通后我开始测吞吐,结果 NPU 单进程 32 张/s,GPU 单进程也才 65.6——感觉核显也没强到哪去。直到我把喂料方式从 cv2 全量解码换成 ffmpeg 抽帧进内存管道……等等,故事又反转了。

真相是 cv2 的 hwdownload 回读把 CPU 吃满了,GPU 一直在空等。换抽帧后 GPU 单进程稳定 65.6、4 进程 147.8、核显+NPU 混合池干到 240 张/s。这台'跑不动'的机器,实际比我想象的能打 7 倍。差点被我自己的测试方法骗过去。

第四幕:把检测从'瓶颈'变成'顺便'

检测变快了,但一小时视频的检测仍然要 40s(99 倍实时),而切割还停在'切片重编码'这种慢动作上。这轮我做三件事,把流水线推进到最终形态:

  1. copy 流复制切割替代重编码:44 片 2.8s vs 单命令 87.2s,快 24 倍
  2. rawvideo 管道 + 缩 640x360:不落盘、字节减 4 倍,检测 32.6s→23.2s
  3. gpu_ratio 0.6 + 3 秒采样:任务按能力分配消除空等,检测干到 8s/小时视频(~440x)

千里眼不是 AI 有多神,而是'哪块硬件该干多少活,被精确算准了'。检测最终快过了解码本身,从瓶颈变成了整个流程里最不值一提的环节。

最终回:一夜,502GB 变 235GB

最后一战是 D 盘全量:1677 个目录、近 8 万文件、502.5GB,全部只读不删。用 Windows 计划任务拉起一个自包含的 Python 启动器,从晚上 23:51 跑到早上 06:26:

502.5GB / 1,677 目录 / 79,027 文件
成片235.7GB / 1,554 个(123 个无人目录无成片)
压缩−53%
耗时~6.5 小时
错误0

早上 6 点多起来看日志,1677/1677 全部完成、0 错误。那一刻的心情,大概只有'爽'字能形容。几百 GB 的占盘监控,变成了正常人眼看板的一晚量。

回看:这些弯路值不值

时间成果教训
freezedetect180s→66s demo运动≠有人,语义问题没有阈值解
手写 OpenVINO全部失败官方路径是唯一活路
cv2 测速假 'GPU慢'测速方法错,结论全错
混合池 + 调优240 张/s多进程喂饱 + 按能力分配
全盘批跑502→235GB,0 错误计划任务 + 断点续跑才稳
给想抄作业的人:每阶段的具体参数和实测数字都在对应的专文里:新手上路 → NPU 跑 YOLOv8n 教程;全部坑 → NPU OpenVINO 避坑录;吞吐曲线 → 三档吞吐天梯;完整流水线 → 监控只留有人实战。数据来自本机实测,仅供参考。

The story has a very ordinary beginning: 'my home surveillance racked up a few hundred GB, can it be compressed?' The requirement was plain — don't keep frames where nothing happens. Who knew that sentence would carry me from freezedetect to YOLOv8n, from doubting every result to 240 FPS? This is that full trajectory, every digit recorded on my little Core Ultra 5 235H.

Box: Core Ultra 5 235H / Arc 140T / NPU / OpenVINO 2026.5.0.dev / ffmpeg 9.0.1 / Windows. Timeline 2026-09-05 → 09-13.

Act 1: freezedetect vs. sensor noise

Version one was pure common sense: use ffmpeg's freezedetect to find 'frozen' windows and cut them. The demo worked — 180s shrank to 66s — and I thought we were done. Then the real night footage went in and it fell apart:

  • night footage is all noise: sensor jitter makes 'static' look active, freezedetect lets everything through
  • the n-sweep showed -48dB at a 26% valley while neighbors sat at 40–78% — hypersensitive and non-monotonic
  • it can't tell 'still' from 'has a person' — a still human and an empty room look identical to frame diff

At first I tried smarter thresholds and wider windows for hours, until one sentence from the user nailed the direction: 'the rule is keep-it-if-there-is-a-person.' It was never a threshold problem — it was semantic. Motion detection got its death sentence.

Act 2: hand-written OpenVINO pre/post-processing, wiped out

Semantic means object detection. The NPU was sitting there, so I exported yolov8n.pt to OpenVINO IR and then — hand-wrote letterbox, hand-wrote BGR, hand-wrote NMS coordinate decode. Not one variant worked: bounding boxes everywhere, confidence garbage, FCOS decode broken too.

After nearly two days I surrendered completely: inference goes through the official ultralytics path model.predict(device="intel:NPU"), all pre/post-processing owned by it. Every 'DIY parser' hour was wasted — the most expensive lesson in this story, and the one I most want you to skip.

Act 3: 'the GPU is slow' was fake news

Once the official path worked I measured throughput: NPU 32 FPS, GPU 65.6 — the iGPU felt mediocre. Then I swapped the feeding from cv2 full-decode to ffmpeg frames into an in-memory pipe… and the story flipped again.

The truth: cv2's hwdownload readback saturated the CPU while the GPU starved. After switching to ffmpeg sampling, single-process GPU held 65.6, 4-process hit 147.8, and the hybrid iGPU+NPU pool reached 240 FPS. This 'underpowered' box turned out to be 7× stronger than I'd been tricked into believing by my own test method.

Act 4: from bottleneck to an afterthought

Detection was faster yet still 40s per hour (~99× realtime), and slicing was still slow re-encoding. Three changes took the pipeline to its final form:

  1. stream-copy cutting replaces re-encoding: 44 slices in 2.8s vs 87.2s, 24× faster
  2. rawvideo pipe + 640x360: nothing to disk, 4× fewer bytes, detect 32.6s→23.2s
  3. gpu_ratio 0.6 + 3s sampling: capability-split kills idle-wait, detection at 8s per hour (~440×)

The magic isn't that AI is brilliant — it's that 'how much each chip does' got calculated exactly right. Detection ended up faster than decoding itself, shrinking from bottleneck to the least interesting step in the whole flow.

Final act: one night, 502GB → 235GB

The final battle was the full D: drive: 1,677 directories, ~80k files, 502.5GB, read-only, nothing deleted. A scheduled task spawned a self-contained Python launcher, 23:51 → 06:26:

ItemValue
Source502.5GB / 1,677 目录 / 79,027 文件
Output235.7GB / 1,554 个(123 个无人目录无成片)
Shrink−53%
Duration~6.5 小时
Errors0

Checking the log at 6am: 1,677/1,677 done, zero errors. That moment felt — honestly — just 'sweet'. Hundreds of GB of disk-hogging surveillance became one manageable overnight watch.

Looking back: was it worth the detours

PhaseOutcomeLesson
freezedetect180s→66s demomotion ≠ presence; no threshold solves semantic
DIY OpenVINO全部失败official path or bust
cv2 bench假 'GPU慢'wrong method, wrong verdict
hybrid + tuning240 张/smulti-process + capability split
full-disk batch502→235GB,0 错误task scheduler + resume for safety
For the copycats:Every stage's flags and numbers live in its own article: getting started → NPU + YOLOv8n tutorial; the traps → NPU OpenVINO pitfalls; throughput curves → three-lane ladder; full pipeline → person-cut in production. Local measurements for reference.
返回文章列表