把几个 GB 的监控浓缩成'只有画面在动的片段',是最省钱省心的视频瘦身法。我在这台机器上把 ffmpeg 的每一条剪静止路线都跑了一遍:freezedetect 精确切段、mpdecimate 流式丢帧、select 保帧重排,外加 AV1/H.264 硬编。这篇是整个过程的路线图 + 血泪账。
环境:Core Ultra 5 235H / Arc 140T 核显(QSV 硬编)/ ffmpeg 9.0.1(gyan essentials)/ 测试源 1080p 10fps 监控段、180s 3 段目录。2026-09-11~12 实测。
三条路的定位
| 方案 | 原理 | 音频 | 速度 |
|---|---|---|---|
| freezedetect 检测 + atrim 精确切段 | 先检测冻结区间,再按同边界切 | 完整保留、严格同步 | ~7.6s/目录(三方案最慢) |
| mpdecimate 单命令丢帧 | 流式判重丢帧 + setpts 重排 | 必须 -an 丢弃 | 2.6~3.4s(最快) |
| select 保帧重排 | 按活动帧 select + setpts 重排 | 视频稀疏 vs 音频连续→不同步 | 3.8~4s |
方案一:freezedetect + 精确切段(音画最稳)
逻辑最直白:freezedetect 找出'画面冻结 ≥ 阈值'的时间段,反向得到活动区间(间隙 <5s 合一块),然后视频音频用相同的 atrim 边界切段再拼接。天然同步,因为音视频共享同一个时间轴。
:: 每段:视频音频同边界 -ss/-to,天然同步
ffmpeg -f concat -i list.txt -ss S -to E -c:v libx264 ultrafast -c:a aac seg.mp4
:: 合并后 AV1 硬编(Arc 140T av1_qsv preset7 gq27)
ffmpeg -i joined -filter:a atempo=5 -vf setpts=0.2*PTS -c:v av1_qsv -preset 7 -global_quality 27 out.mp4
实测(A 真实目录):7.6s,压缩 3.4x,V=30.93/A=30.91s 严格同步,音频完整保留。这是'声音有价值必须留'场景下的唯一正解——监控里的家人说话声不能丢。
n 阈值扫描:噪点 vs 静止的分界线
核心参数是 freezedetect=n=-50dB:d=...。n 是判定'变化'的灵敏度,对晚上全是噪点的监控,这个值决定你以为的'静止'是不是真的静止:
| n(dB) | 活动秒 | 占比 | 段数 |
|---|---|---|---|
| -60dB | 140.5s | 78% | 4 |
| -55dB | 75.1s | 42% | 15 |
| -50dB | 68.0s | 38% | 5 |
| -48dB | 46.0s | 26% | 11 |
| -45dB | 82.1s | 46% | 12 |
| -42dB | 79.6s | 44% | 13 |
-48dB 是这一条曲线的'峡谷'(26%),-60dB 和 -45dB 反而更高——在噪点敏感区间 n 不是单调的,跳来跳去。实用的取法是分场景:晚上无人用 -48dB、白天有人用 -50dB(白天画面差异大,不会误剪有人活动,详见核显硬编实测)。
方案二:mpdecimate 单命令丢帧(最快,代价是没音频)
mpdecimate 是流式去重滤镜,边解码边丢'几乎一样的帧',不需要先检测。一条命令同时完成丢帧 + 重排 + 倍速 + 硬编:
ffmpeg -f concat -safe 0 -i list.txt ^
-vf "mpdecimate=lo=768:hi=1536:frac=0.33,setpts=N/FRAME_RATE/TB,setpts=0.2*PTS" ^
-an -c:v av1_qsv -preset 7 -global_quality 27 out.mp4
实测 A(无人夜)2.6s、B(白天有人)3.4s,压缩约 3x——三方案里最快的。但对监控来说音频必须丢(-an):视频丢帧后时间轴缩短,音频却全程保留,两者不可能对账。这条只适合'音频本来就是噪声'的场景。
方案三:select 保帧重排(音画死结)
select 方案按'活动帧'保留再 setpts 重排,但视频是按帧丢的(稀疏)、音频是按时间段留的(连续),粒度根本对不上。实测 A 目录 V=13.65s / A=30.85s 差了一倍多。结论:select 只丢帧不删时间,时长不缩短,音画无法同步,不可用。
高频坑:trim/atrim 混用与 VFR 漂移
坑 A:视频用 trim、音频用 atrim,混用必报 Error linking filters。atrim 是音视频通用滤镜,和 setpts/fps 这类视频滤镜串联时类型协商失败。分家:视频专属 trim,音频专属 atrim,一条 filter_complex 才跑得通。
坑 B:必须先 fps 重采样成 CFR 再 select,否则 VFR 帧数漂移导致音画错位。同样,'逐文件 VFR 直读检测'会误判噪点(A 报 73% vs concat 12%),concat 统一 CFR 才是正确检测。
最终交付形态
| 目录 | 源 | 成片 | 压缩率 | 同步差 |
|---|---|---|---|---|
| A(无人夜) | 13.5MB/180s | 6.4MB | 2.1x | 0.13s |
| B(白天有人) | 20.1MB/180s | 5.7MB | 3.5x | 0s |
| C(晚9点) | ~20MB/180s | 9.5MB | 2.1x | 0.12s |
定码率 700k(≈源码率)是关键:监控源本身才 ~600k,同码率重编码质量不损失,剪静止自然带来压缩。给人看的话,最终我交付的是'剪静止 + 5 倍速 + 单条流 + H264'组合——A 1.4MB、B 1.9MB、C 2.3MB,音画同步 0.06s。但记住:剪静止的前提是'没人没动作',语义级的'有没有人'要用 YOLO 检测(见NPU 人形检测实战)。
av1_qsv p7 gq27(画质/体积/速度平衡,详见 Arc 硬编实测)或 H264 -b:v 700k 全兼容。数据来自本机实测,仅供参考。