FFmpeg性能优化:硬件加速对比、preset选择和实测数据
FFmpeg 默认配置偏保守,处理 1080p 视频可能只有 0.5x 实时速度——1 小时的视频要转 2 小时。但调整几个参数就能提到 5x 甚至 20x。这篇文章从硬件加速、编码参数、多线程三个层面讲优化,并给出不同场景的推荐配置。
硬件加速方案对比
四种主流硬件加速,按你的 GPU 选择:
| 方案 | 适用硬件 | 编码器 | 解码参数 | 特点 |
|---|---|---|---|---|
| NVENC/NVDEC | NVIDIA GPU | h264_nvenc, hevc_nvenc | -hwaccel cuda | 生态最成熟,质量接近 x264 medium |
| Intel QSV | Intel 集显/独显 | h264_qsv, hevc_qsv | -hwaccel qsv | 低延迟,适合转码服务器 |
| AMD AMF | AMD GPU | h264_amf, hevc_amf | -hwaccel d3d11va | Windows 为主 |
| VideoToolbox | Apple 芯片/Mac | h264_videotoolbox | -hwaccel videotoolbox | macOS 原生,M 系列芯片性能极强 |
NVIDIA GPU 加速
bash# GPU 解码 + GPU 编码(全程不经过 CPU,最快) ffmpeg -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:v h264_nvenc -preset fast -b:v 5M output.mp4 # GPU 解码 + CPU 编码(质量要求高时) ffmpeg -hwaccel cuda -i input.mp4 -c:v libx264 -preset slow output.mp4 # 指定使用哪块 GPU(多卡服务器) ffmpeg -hwaccel_device 0 -hwaccel cuda -i input.mp4 -c:v h264_nvenc output.mp4
-hwaccel_output_format cuda 让解码后的帧留在 GPU 显存里,避免 GPU→CPU→GPU 的数据搬运。全程 GPU 处理比"GPU 解码 + CPU 编码"快 2-3 倍。
Intel QSV 加速
bashffmpeg -hwaccel qsv -i input.mp4 -c:v h264_qsv -preset fast -b:v 5M output.mp4
QSV 在 Intel 集显上性能不错,低功耗场景(如 NAS 转码)比 NVIDIA 方案更省电。但编码质量不如 NVENC。
Apple VideoToolbox
bashffmpeg -i input.mp4 -c:v h264_videotoolbox -b:v 5M output.mp4
M1/M2/M3 芯片上 VideoToolbox 编码 4K 视频可以跑到实时 10x 以上。但 FFmpeg 对 VideoToolbox 的参数控制不如 NVENC 丰富。
硬件加速的局限
- 硬件编码器的 CRF 控制不如 x264 精细,同码率下质量通常比 x264 slow 低一档
- 硬件编码器的 B 帧策略和参考帧数量受限,某些高级参数不支持
- 如果要用滤镜(如 drawtext、overlay),帧通常需要从 GPU 搬回 CPU,抵消加速效果
- 不同硬件编码器的输出比特率波动大,不适合对码率有严格要求的场景
编码参数优化
x264 preset 选择
bash# 追求速度(实时转码、预览) ffmpeg -i input.mp4 -c:v libx264 -preset veryfast -crf 23 output.mp4 # 平衡速度和质量(通用场景) ffmpeg -i input.mp4 -c:v libx264 -preset medium -crf 23 output.mp4 # 追求质量(离线存档) ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 18 output.mp4
实测数据(1080p 25fps,i7-12700K):
| preset | 编码速度 | 相同 CRF 下的体积 |
|---|---|---|
| ultrafast | 120fps (5x) | +40% |
| veryfast | 80fps (3x) | +20% |
| fast | 55fps (2x) | +10% |
| medium | 35fps (1.4x) | 基准 |
| slow | 12fps (0.5x) | -8% |
从 veryfast 到 slow,速度差 7 倍但体积只省 20%。大多数场景选 veryfast 或 fast 就够了。
CRF 值选择
CRF(Constant Rate Factor)是 x264 的质量控制参数,0 是无损,51 是最差:
| CRF | 质量 | 场景 |
|---|---|---|
| 18 | 视觉无损 | 存档、后期素材 |
| 23 | 默认 | 通用 |
| 28 | 明显压缩痕 | 预览、小体积 |
| 32 | 画质差 | 仅可辨认内容 |
CRF 和 preset 是独立的:CRF 控制质量目标,preset 控制达到该目标的效率。同一 CRF 下,slow preset 的文件更小但质量一样。
线程数
bash# 自动检测(推荐,通常等于 CPU 核心数) ffmpeg -i input.mp4 -threads 0 -c:v libx264 output.mp4 # 手动指定(给其他任务留核心) ffmpeg -i input.mp4 -threads 4 -c:v libx264 output.mp4
x264 的线程数不是越多越好——超过 16 线程后编码效率开始下降(切片并行导致的参考帧问题)。4K 视频推荐 8-16 线程,1080p 推荐 4-8 线程。
批量处理
GNU Parallel 多文件并行
bash# 同时处理 4 个文件,每个占一个 GPU find input/ -name "*.mp4" | parallel -j 4 ffmpeg -i {} -c:v h264_nvenc output/{/.}.mp4
多文件并行比单文件多线程更高效——FFmpeg 单进程的线程扩展性有限,但多个进程各占一个核心/GPU 可以线性扩展。
分段处理大文件
bash# 先分成小段 ffmpeg -i input.mp4 -c copy -f segment -segment_time 60 segment_%03d.mp4 # 并行转码每一段 for f in segment_*.mp4; do ffmpeg -i "$f" -c:v libx264 -preset fast transcoded_"$f" & done wait # 合并 echo "$(for f in transcoded_segment_*.mp4; do echo "file '$PWD/$f'"; done)" | ffmpeg -f concat -safe 0 -i - -c copy output.mp4
分段处理要确保每段都有关键帧开头(-c copy 分段依赖关键帧),否则合并不连续。
内存优化
处理超大文件(4K+ 长视频)时内存可能不够:
bash# 限制缓冲区大小 ffmpeg -i input.mp4 -c:v libx264 -bufsize 2M output.mp4 # 流式处理(不落盘) ffmpeg -i rtmp://source/live -c:v libx264 -f flv rtmp://target/live
推荐配置速查
| 场景 | 命令 |
|---|---|
| 实时转码 | -c:v h264_nvenc -preset fast -b:v 4M |
| 离线高质量 | -c:v libx264 -preset slow -crf 18 |
| 批量转码 | -c:v libx264 -preset veryfast -crf 23 + GNU Parallel |
| 小体积 | -c:v libx264 -preset medium -crf 28 |
| Mac 本地 | -c:v h264_videotoolbox -b:v 5M |