FFmpeg视频压缩
FFmpeg 视频压缩进阶:MKV 支持与预设参数对比
一、问题:MP4 压缩命令能否用于 MKV
原始命令
ffmpeg -i zhao2.mp4 -c:v libx264 -crf 32 output_smaller.mp4结论
可以,该命令完全适用于 MKV 格式的视频。
核心概念:容器 vs. 编码格式
| 概念 | 说明 | 示例 |
|---|---|---|
| 容器(Container) | 打包视频流、音频流、字幕等的文件格式 | MP4、MKV、AVI、MOV |
| 编码格式(Codec) | 实际压缩视频画面的算法 | H.264(libx264)、H.265、AV1 |
-c:v libx264 指定的是编码格式(H.264),与输入文件的容器格式无关。FFmpeg 可以读取任何容器中的视频流并重新编码。
具体用法
压缩 MKV 视频并输出为 MP4:
ffmpeg -i input.mkv -c:v libx264 -crf 32 output.mp4保持 MKV 容器格式:
ffmpeg -i input.mkv -c:v libx264 -crf 32 output.mkv注意事项
| 问题 | 解决方案 |
|---|---|
| 音频被重新压缩 | 添加 -c:a copy 直接复制音频流 |
| 字幕被丢弃 | 添加 -c:s copy 复制字幕流(需输出为 MKV) |
| MP4 对字幕支持有限 | 如需保留字幕,建议输出为 MKV 格式 |
二、libx264 编码器的加速参数
问题:是否有类似 -cpu-used 8 -row-mt 1 的参数?
答案:
| 参数 | 在 libx264 中的情况 |
|---|---|
-cpu-used | 不存在,此为 libaom-av1 特有参数 |
-row-mt 1 | 默认已启用,无需额外指定 |
libx264 的核心加速参数:-preset
-preset 参数控制编码速度与压缩效率之间的权衡。
可用预设值(按速度从快到慢排列):
ultrafast > superfast > veryfast > faster > fast > medium > slow > slower > veryslowmedium为默认值- 更快的预设 = 编码时间更短,但文件可能稍大
- 更慢的预设 = 编码时间更长,但文件更小(压缩效率更高)
使用示例:
ffmpeg -i input.mkv -c:v libx264 -preset veryfast -crf 32 output.mp4三、实际测试:-preset veryfast 对比测试
测试环境
- 输入文件:Rec0002.mp4
- 输入大小:约 900 MB
- 视频时长:约 28 分 56 秒
- 帧数:52088 帧
- CPU:未指定(实际测试环境)
测试命令
命令一(默认 preset):
ffmpeg -i Rec0002.mp4 -c:v libx264 -crf 32 Rec00022.mp4命令二(加 preset veryfast):
ffmpeg -i Rec0002.mp4 -c:v libx264 -preset veryfast -crf 32 Rec00022.mp4测试结果对比
| 对比项 | 默认(medium) | -preset veryfast | 差异 |
|---|---|---|---|
| 编码速度 | 12.9x | 22.6x | 速度提升约 75% |
| 总耗时 | 2分14秒 | 1分16秒 | 节省约 58 秒 |
| 视频大小 | 172,945 KiB | 160,235 KiB | 反而减小约 7.3% |
| I 帧平均大小 | 52,712 | 38,112 | 减小 27.7% |
| P 帧 skip 比例 | 72.3% | 73.9% | 略高 |
| B 帧 skip 比例 | 81.3% | 84.6% | 略高 |
| 8x8 transform intra | 70.4% | 24.7% | 大幅降低 |
关键指标解读
1. 编码速度
- 默认预设(medium):speed=12.9x,总耗时 2分14秒
- veryfast 预设:speed=22.6x,总耗时 1分16秒
- 结论:veryfast 速度快约 1.75 倍
2. 文件大小
- veryfast 反而更小(约 7.3%),这与通常预期(更快预设 = 更大文件)不同,可能与视频源的具体内容有关
3. 画质指标
- I 帧大小:veryfast 更小(38112 vs 52712),关键帧分配码率更少
- skip 比例:veryfast 跳过更多宏块,细节保留更少
- 8x8 transform:veryfast 使用率大幅降低(24.7% vs 70.4%),精细变换减少
4. 内部策略变化
- ref B L0/L1 参考帧比例更低
- 运动预测参考范围更小
结论与建议
| 场景 | 推荐预设 | 原因 |
|---|---|---|
| 批量处理、快速预览 | veryfast 或 faster | 时间节省显著 |
| 日常通用转换 | medium(默认) | 速度与画质平衡 |
| 存档或高质量需求 | slow 或 veryslow | 最佳压缩效率 |
| 实时推流 | ultrafast | 编码速度最快 |
四、FFmpeg 日志关键字段解读
编码日志示例
[out#0/mp4 @ ...] video:160235KiB audio:27124KiB ... frame=52088 fps=678 q=-1.0 Lsize=189192KiB time=00:28:56.10 bitrate=892.7kbits/s speed=22.6x elapsed=0:01:16.78关键字段说明
| 字段 | 含义 |
|---|---|
video:160235KiB | 输出视频流大小 |
audio:27124KiB | 输出音频流大小 |
frame=52088 | 处理的帧总数 |
fps=678 | 每秒编码帧数(编码速度) |
time=00:28:56.10 | 输出视频时长 |
bitrate=892.7kbits/s | 输出视频码率 |
speed=22.6x | 相对于实时播放速度的编码倍率 |
elapsed=0:01:16.78 | 编码实际耗时 |
libx264 编码统计字段
| 字段 | 含义 |
|---|---|
frame I | 关键帧(I帧)数量及平均QP |
frame P | 预测帧(P帧)数量及平均QP |
frame B | 双向预测帧(B帧)数量及平均QP |
skip | 跳过编码的宏块比例,越高则细节保留越少 |
8x8 transform | 使用 8x8 变换的比例,越高则压缩精细度越高 |
kb/s | 视频平均码率 |
五、实用命令速查
MKV 压缩为 MP4(保留音频)
ffmpeg -i input.mkv -c:v libx264 -crf 32 -c:a copy output.mp4MKV 压缩为 MKV(保留音频和字幕)
ffmpeg -i input.mkv -c:v libx264 -crf 32 -c:a copy -c:s copy output.mkv使用 faster 预设加速压缩
ffmpeg -i input.mp4 -c:v libx264 -preset faster -crf 32 output.mp4极速压缩(ultrafast)
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast -crf 32 output.mp4高质量压缩(缓慢但文件更小)
ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 28 output.mp4六、使用显卡加速
libx264:使用 CPU 进行编码(软件编码)。h264_nvenc:使用 NVIDIA 显卡 进行编码(硬件编码)。
6.1. 显卡(h264_nvenc)能用吗?
能用,但有前提条件:
- 你必须有一块 NVIDIA 显卡(GTX 600系列及以上,大部分民用卡都支持)。
- 你的 FFmpeg 必须编译时带上了
--enable-nvenc支持(可以通过运行ffmpeg -encoders | findstr nvenc检查)。 - 注意:如果是在虚拟机或 Docker 中使用,可能需要直通显卡或安装额外的驱动,否则会报错。
6.2. 使用显卡的命令写法
如果你要把命令改成显卡压缩,应该这样写:
ffmpeg -i input.mkv -c:v h264_nvenc -preset p1 -cq 32 output.mp4特别注意这里的参数变化(这是新手最容易踩坑的地方):
| 参数 | CPU (libx264) | 显卡 (h264_nvenc) | 说明 |
|---|---|---|---|
| 质量参数 | -crf 32 | -cq 32 | 显卡不用 crf,用 cq(恒定质量)。数值越大,画质越差,文件越小。 |
| 预设 | -preset veryfast | -preset p1 (或 p2, p3) | 显卡预设是 p1(最快)、p2(默认)、p3(画质最好)。不推荐使用 veryfast,会报错。 |
6.3. CPU 和 显卡(硬件编码)的核心区别
既然能用,你应该选哪个?请根据你的需求选择:
- 选
libx264(CPU):画质最好,文件最小。适合最终成片的存储或发布。缺点是速度慢(尤其开了高清预设)。 - 选
h264_nvenc(显卡):速度极快(通常是CPU的3-5倍)。适合直播推流或快速粗剪预览。缺点是同码率下画质不如CPU,且文件体积会比CPU压出来的大(如果追求相同画质)。
6.4. 针对你原命令的修改建议
如果你追求快速压缩且不care体积,用显卡:
ffmpeg -i input.mkv -c:v h264_nvenc -preset p2 -cq 28 output.mp4(注:cq 28 在显卡上的画质约等于CPU的 crf 23,建议别用32,画质损失较大)
如果你追求小体积和高画质,坚持用CPU,但建议把 veryfast 改成 slow 或 medium(压缩率更高):
ffmpeg -i input.mkv -c:v libx264 -preset slow -crf 23 output.mp4三版本综合对比表
| 对比项 | CPU (libx264) crf 32 | 显卡 (NVENC) cq 32 | 显卡 (NVENC) cq 28 |
|---|---|---|---|
| 输出文件大小 | 47.6 MB | 105.5 MB | 156.6 MB |
| 视频码率 | 459 kbps | 1329 kbps | 1973 kbps |
| 压缩用时 | 28.0 秒 | 22.9 秒 | 22.4 秒 |
| 画质(理论) | 较好 | 一般 | 较好(但不如CPU) |
| 体积对比 | 1 倍(基准) | 2.2 倍 | 3.3 倍 |
关键发现
1. 显卡的 cq 值对体积影响巨大
cq 32→ 105 MBcq 28→ 157 MB(增加了 50%)- 虽然
cq 28画质更好,但代价是体积暴涨。
2. CPU 的压缩效率碾压显卡
- CPU 用 459 kbps 的码率,画质已经不错(
crf 32是比较省体积的设置)。 - 显卡要用 1973 kbps 的码率(4.3 倍),才能达到接近的画质水平。
- 结论:同画质下,CPU 压缩出来的文件只有显卡的 1/3 到 1/4。
3. 速度差距几乎可以忽略
- 最快(显卡
cq 28)22.4 秒 vs 最慢(CPU)28.0 秒 - 只差了 5.6 秒,对于 11 分钟的视频来说,这点时间差异没有任何实际意义。
最终结论
| 你的需求 | 推荐方案 | 命令 |
|---|---|---|
| 追求画质 + 小体积(推荐) | CPU libx264 | -c:v libx264 -preset faster -crf 23 |
| 追求极致小体积 | CPU libx264 | -c:v libx264 -preset faster -crf 32(就是你用的) |
| 追求速度(但你已经很快了) | 显卡 h264_nvenc | -c:v h264_nvenc -preset p1 -cq 28 |
| 硬盘很大,不在乎体积 | 显卡 h264_nvenc | -c:v h264_nvenc -preset p1 -cq 23(画质更好) |
给你的最终建议
在这个场景下(低分辨率、11分钟视频),完全没有必要用显卡。
原因很简单:
- CPU 只慢了 5 秒,但文件小了 2/3(从 157MB 降到 48MB)。
- 如果你有大量视频要压缩,节省的硬盘空间非常可观。压 10 个视频,CPU 占 480MB,显卡占 1.5GB。
所以,以后压缩这类视频,直接用 CPU 就行:
ffmpeg -i s1.mp4 -c:v libx264 -preset faster -crf 23 s1_compressed.mp4crf 23是公认的“平衡点”,画质和体积都很好。- 如果你想更小一点,用
crf 28;想更清晰一点,用crf 20。
需要我帮你解释 crf 数值的具体含义吗?或者你想测试一下 crf 23 的实际效果?