智能视频压缩 - 画质优先 + 数据驱动
概述
不同于传统"指定目标大小→硬压"的方式,此 skill 采用三步智能流程:
- 源分析 — 用 ffprobe 检测源视频的编码、码率、分辨率、时长,判断源画质等级
- 画质基准测试 — 从视频中间抽取 60 秒样本,用多种编码参数(x265 CRF 22/26/28/30、NVENC CQ 22/26/28/30)分别编码,然后用 PSNR/SSIM 对比源画质,生成数据表
- 数据驱动压缩 — 基于基准测试结果推荐最优方案(平衡画质/大小/速度),批量压缩全部视频
核心理念:PSNR > 40 dB 或 SSIM > 0.99 时人眼几乎无法区分与源的差别。在此前提下选码率最低的方案,实现"画质无损 + 体积最小"。
工作流程
第 1 步:源分析
对目标目录中的每个视频用 ffprobe 检测:
| 检测项 | 命令 | 用途 |
|---|---|---|
| 编码格式 | ffprobe -select_streams v:0 -show_entries stream=codec_name |
判断是否需要重编码 |
| 分辨率 | ...width,height |
确定是否保持原始分辨率 |
| 码率 | ...bit_rate |
判断源画质等级(低/中/高) |
| 时长 | ...duration |
估算全片压缩时间 |
| 音频编码 | ...codec_name (audio stream) |
判断音频是否可直接复制 |
源码率等级判定:
- 低码率(< 1 Mbps / 1080p):源已严重压缩,再编码需谨慎。NVENC CRF 22 会放大码率导致输出比源更大。推荐 x265 CRF 28 或 NVENC CQ 30
- 中码率(1-3 Mbps / 1080p):常规网络视频质量。推荐 x265 CRF 26-28
- 高码率(> 3 Mbps / 1080p):源画质好。可激进压缩,推荐 x265 CRF 24-26
第 2 步:画质基准测试(核心)
运行基准测试脚本,对每个视频抽取 60 秒样本进行多方案编码 + PSNR/SSIM 对比:
python scripts/benchmark_quality.py "<视频文件或目录>" [选项]
关键参数:
- --ffmpeg <路径> — 指定 ffmpeg 可执行文件路径
- --ffprobe <路径> — 指定 ffprobe 路径
- --sample-duration 60 — 样本时长(秒),默认 60
- --codecs x265,nvenc — 测试哪些编码器(默认全测)
- --quality-levels 22,26,28,30 — 测试哪些 CRF/CQ 值
- --skip-nvenc — 跳过 NVENC 测试(无 N 卡时)
- --clean — 测试后清理临时文件
输出:控制台表格 + JSON 结果文件,包含每个方案的码率、预估全片大小、PSNR、SSIM、编码速度。
脚本会自动推荐:在 PSNR ≥ 40 dB 且 SSIM ≥ 0.99 的方案中,选码率最低的作为推荐方案。
第 3 步:确认方案并批量压缩
将基准测试结果展示给用户,确认方案后执行压缩:
# 软件编码(x265,画质最优,较慢)
python scripts/compress_optimal.py "<目录>" --codec libx265 --crf 28 --preset fast --apply
# 硬件编码(NVENC,速度快,画质稍逊)
python scripts/compress_optimal.py "<目录>" --codec hevc_nvenc --cq 30 --preset p5 --apply
# 批量视频质量参差 → 按源码率自动分级 CRF(推荐)
python scripts/compress_optimal.py "<目录>" --tier --apply
# 实测校准过的分级表 + 进度日志(后台可追踪)
python scripts/compress_optimal.py "<目录>" --tier --tier-map "2500:22,1800:26,1000:28" --progress-log compress.log --apply
压缩参数说明:
| 参数 | 软件编码 (x265) | 硬件编码 (NVENC) | 说明 |
|---|---|---|---|
| 编码器 | libx265 |
hevc_nvenc |
x265 画质/码率比最优 |
| 质量 | --crf 28 |
--cq 30 |
CRF/CQ 越低画质越高、文件越大 |
| 分级 | --tier |
— | 按源码率自动分配 CRF(批量质量参差时用) |
| 预设 | --preset fast |
--preset p5 |
影响速度/质量权衡 |
| 音频 | --audio copy |
--audio copy |
直接复制,不重编码 |
| 验证 | --verify(默认开) |
同上 | 压缩后 ffprobe 检查时长/分辨率 |
| 进度 | --progress-log <文件> |
同上 | 进度摘要日志,后台运行时可追踪 |
| 输出标记 | -tag:v hvc1 |
-tag:v hvc1 |
确保 Apple/浏览器兼容 |
| 快速启动 | -movflags +faststart |
-movflags +faststart |
支持流式播放 |
> 分级 CRF 提醒:码率只是内容复杂度的代理指标。实测规律是码率越高 CRF 越要保守(高码率常对应高动态画面)。批量压缩前至少实测 2-4 个代表性视频校准分级表,详见 references/quality_metrics_guide.md。
输出文件:<原名>_压缩版.mp4,保存在原目录,原文件不动。压缩完成后脚本自动 ffprobe 验证完整性,结果写入 compress_results.json。
长任务后台执行
当视频总时长超过 30 分钟或文件数超过 3 个时,用 Start-Process 启动压缩脚本并转入后台运行,避免前台命令 idle 超时被取消:
# 后台启动压缩脚本(隐藏窗口)+ 进度日志
Start-Process python -ArgumentList @("compress_optimal.py","D:\videos","--tier","--apply",
"--progress-log","D:\videos\progress.log","--log-dir","D:\videos\logs") -WindowStyle Hidden
# 随时查看进度(脚本追加写入,含每个视频的开始/完成/大小/耗时)
Get-Content D:\videos\progress.log -Tail 10
- 进度日志记录每个视频的开始/完成/大小/耗时,后台运行时可随时追踪
- 压缩前脚本会按平均 4x 编码速度预估总耗时
- 完成后自动验证输出完整性(
--verify)
> Windows 注意:长任务在前台 execute_command 中执行可能因 idle 超时被取消。务必用 Start-Process + 进度日志模式。Python 脚本内部已规避 ffmpeg 管道阻塞坑(stderr 重定向到文件),详见 references 常见问题排查。
画质指标解读
详细说明见 references/quality_metrics_guide.md。速查:
| PSNR (dB) | SSIM | 画质评价 |
|---|---|---|
| > 48 | > 0.998 | 极高(几乎无损) |
| 43-48 | 0.995-0.998 | 高(人眼难以区分) |
| 40-43 | 0.99-0.995 | 良好(可接受的轻微损失) |
| 35-40 | 0.95-0.99 | 一般(可见画质下降) |
| < 35 | < 0.95 | 差(明显模糊/块效应) |
推荐基准线:PSNR ≥ 40 dB 且 SSIM ≥ 0.99 → 视为"感知无损",可放心采用。
编码器对比
| 维度 | x265(软件) | hevc_nvenc(硬件) |
|---|---|---|
| 画质/码率比 | 最优(省 37-50% 码率) | 较差(需更高码率达同等画质) |
| 速度 | 慢(10-90 fps,1080p) | 极快(300-500 fps) |
| 适用场景 | 画质优先、可等待 | 速度优先、批量处理 |
| 硬件要求 | CPU(多核受益大) | NVIDIA GPU(GTX 10+) |
经验法则:
- 同等画质(PSNR ~43dB):x265 需 ~260 kbps,NVENC 需 ~414 kbps
- x265 preset fast 实测约 83 fps(i5-10600KF,1080p)→ 每集约 35 分钟
- NVENC 实测约 370 fps → 每集约 8 分钟
- NVENC CRF/CQ 22 在低码率源上会放大码率(输出比源更大),慎用
常见场景
| 用户场景 | 推荐流程 |
|---|---|
| "画质优先压缩" | 基准测试 → x265 CRF 28 preset fast |
| "快速压缩,画质别太差" | 基准测试 → NVENC CQ 30 |
| "批量视频质量参差,逐个压太麻烦" | 实测 2-4 个代表性视频 → --tier + --tier-map 分级压缩 |
| "之前压的画质不好,重做" | 基准测试 → 选 PSNR ≥ 43 的方案重压 |
| "源文件很大,想大幅缩小" | 基准测试 → x265 CRF 30-32(更激进) |
| "不确定用哪个参数" | 先跑基准测试,看数据再决策 |
实战经验速查(2026-08,10 视频 9.6GB→1.8GB 批量压缩)
- 码率越高 CRF 越保守:2530k→CRF22、2176k→CRF28、1268k 屏幕内容→CRF30。码率只是内容复杂度的代理指标,务必实测
- ffmpeg 管道阻塞坑:Python 里
stderr=PIPE+ 不读 → 卡死(CPU≈0、输出 0 字节)。stderr 重定向到文件最稳 - 压缩后必须验证:ffprobe 检查输出可解码/分辨率/时长(脚本
--verify已内置) - 长任务后台跑:Start-Process + 进度日志,前台命令会超时
- 压缩比参考:屏幕录制课程 5-8x(CRF 28-30)、高动态内容 3-4x(CRF 22)
Resources
scripts/
benchmark_quality.py— 画质基准测试:抽取样本、多方案编码、PSNR/SSIM 对比、生成推荐(含样本代表性提示)compress_optimal.py— 批量压缩:x265/NVENC、分级 CRF(--tier)、完整性验证(--verify)、进度日志(--progress-log)、总耗时预估
references/
quality_metrics_guide.md— PSNR/SSIM 阈值详解、CRF/CQ 映射、源码率等级判定(含反直觉规律与实测数据)、分级 CRF 策略、编码器对比、Windows 后台执行最佳实践、常见坑排查