FFMPEG视频压缩

ffmpeg [全局参数] -i [输入文件] [视频参数] [音频参数] [输出文件]

参数作用常用值 / 说明
-i指定输入文件例:-i input.mp4
-crf恒定质量因子(最推荐的压缩方式)0-51,值越小画质越好,23 为默认,28-32 是常用压缩值
-preset压缩速度 / 效率ultrafast (最快) < fast < medium < slow < veryslow (质量最好)
-c:v视频编码器h264 (通用)、h265 (HEVC,压缩率更高)
-c:a音频编码器aac (通用)、mp3
-b:a音频码率128k (常用)、192k、64k
-vf scale调整分辨率scale=1280:720 (固定分辨率)、scale=-2:720 (保持比例,高度 720)
-r调整帧率30、24、15(降低帧率减小体积)
-b:v视频码率(替代 crf 的方式)1M、2M(固定码率,不如 crf 灵活)
-y覆盖输出文件无需确认,直接覆盖已有文件
ffmpeg -i input.mp4 -crf 28 -preset medium -c:v h264 -c:a aac -b:a 128k -y output.mp4

复用原视频的音视频编码

核心参数:-c:v copy-c:a copy

  • -c:v copy:复用原视频的视频编码器(直接拷贝视频流,不重新编码)
  • -c:a copy:复用原音频的音频编码器(直接拷贝音频流,不重新编码)

关键注意事项

  • 仅用 copy 模式无法压缩体积(只是拷贝流),必须配合分辨率、码率等参数;
  • 如果调整了分辨率 / 帧率 / 码率,copy 模式会失效(FFmpeg 会自动重新编码),但仍会优先使用原编码格式;
  • 若原编码格式不支持调整的参数(比如原编码是 mpeg4,调整 h264 专属参数),FFmpeg 会报错,需先确认原视频编码格式。

copy 模式与 crf/preset 冲突

-c:v copy(视频流拷贝)的核心逻辑是:直接复制原视频的编码数据,不做任何重新编码操作;而 -crf(质量因子)和 -preset(压缩速度)是仅针对视频重新编码的参数 —— 这两组参数是互斥的,具体表现为:

  1. 当使用 -c:v copy 时,FFmpeg 会忽略 -crf-preset 参数,因为不需要重新编码,自然无需调整编码质量 / 速度;
  2. 只有去掉 -c:v copy,让 FFmpeg 重新编码视频流时,-crf-preset 才会生效;
  3. -c:a copy 本身和 -crf/-preset 无冲突(因为这两个参数只作用于视频),但音频流拷贝也无法通过这两个参数压缩。

使用硬编码器

先确认设备支持的硬解码方案

首先执行以下命令,查看 FFmpeg 编译时支持的硬解码器(不同编译版本支持的方案不同):

ffmpeg -hwaccels

常见输出(不同平台差异):

  • Android/Linux:vaapidrmmediacodec(Android 专属)
  • Windows:d3d11vacuda
  • macOS:videotoolbox

硬解码的通用命令结构

ffmpeg -hwaccel [硬解方案] -hwaccel_device [设备] -i [输入文件] [编码参数] [输出文件]

关键参数:

  • -hwaccel:指定硬解方案(如mediacodecd3d11va);
  • -hwaccel_device:指定硬解设备(可选,多数场景无需手动指定);
  • 视频编码器需匹配硬解方案(如h264_mediacodec表示 Android 硬编 h264)。
# Android硬解+硬编压缩视频(复用原编码格式,crf压缩)
ffmpeg -hwaccel mediacodec -i input.mp4 -c:v h264_mediacodec -crf 28 -preset medium -c:a copy -y output.mp4

# Windows硬解+软编(兼顾兼容性)
ffmpeg -hwaccel d3d11va -i input.mp4 -c:v h264 -crf 28 -preset medium -c:a copy -y output.mp4

# Windows硬解+CUDA硬编(NVIDIA显卡)
ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_cuvid -crf 28 -preset medium -c:a copy -y output.mp4

# macOS 平台(VideoToolbox 硬解)
ffmpeg -hwaccel videotoolbox -i input.mp4 -c:v h264_videotoolbox -crf 28 -preset medium -c:a copy -y output.mp4

# Linux 平台(VAAPI 硬解)
ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -i input.mp4 -c:v h264_vaapi -crf 28 -preset medium -c:a copy -y output.mp4

硬编码器与 crf/preset 冲突

硬编方案-crf 生效情况-preset 生效情况替代方案
Android MediaCodec完全无效完全无效-b:v(码率)控制质量
Windows CUDA部分生效(仅 h265)完全无效-preset的硬编等效参数
macOS VideoToolbox部分生效(h264/h265)完全无效-b:v-crf(有限)
Linux VAAPI部分生效部分生效(仅部分预设)结合-quality参数
  1. 核心结论:硬件编码下,-crf-preset多数场景失效(尤其是 Android MediaCodec),仅少数硬编方案(如 macOS VideoToolbox、CUDA h265)部分支持 crf;
  2. 替代方案:硬编优先用-b:v(视频码率)控制压缩质量,这是所有硬编方案都支持的参数;
  3. 实践建议:Android 端硬编直接放弃crf/preset,用-b:v+ 分辨率调整体积;macOS/Windows 可尝试crf+-b:v 0,无效则改用码率。

-b:v 需要先读取码率

ffprobe -v error -select_streams v:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 input.mp4
# 输出:
#540083

命令说明:

  • ffprobe – ffmpeg 的媒体分析工具
  • -v error – 只显示错误信息,隐藏其他输出
  • -select_streams v:0 – 选择第一个视频流
  • -show_entries stream=bit_rate – 只显示码率信息
  • -of default=noprint_wrappers=1:nokey=1 – 格式化输出(不显示包装器和键名)
  • input.mp4 – 你的视频文件名

输出结果: 会直接显示比特率数值,单位是 bps (比特每秒),例如 5000000 表示 5 Mbps。

ffmpeg 本身不是专门用来查看信息的工具,需要用一些”技巧”来获取码率信息:

# 重定向错误输出并提取
ffmpeg -i input.mp4 2>&1 | grep "Video:"
#输出:
#  Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, bt709, progressive), 640x368, 540 kb/s, 30 fps, 30 tbr, 600 tbn (default)

# 不转码只复制(会显示统计信息)
ffmpeg -i input.mp4 -c copy -f null - 2>&1 | grep bitrate
# 输出:
#  Duration: 00:04:17.10, start: 0.000000, bitrate: 592 kb/s
#frame= 7713 fps=0.0 q=-1.0 Lsize=N/A time=00:04:17.06 bitrate=N/A speed=2.13e+03x   

读取原码率后,按以下策略设置 -b:v,兼顾体积和画质:

场景目标码率设置策略示例(原码率 5000k)
轻度压缩(保画质)原码率 × 70% ~ 80%3500k ~ 4000k
中度压缩(平衡)原码率 × 50% ~ 60%2500k ~ 3000k
重度压缩(保体积)原码率 × 30% ~ 40%(需降分辨率)1500k ~ 2000k + 720P

结论

优先使用硬编,硬编优先用-b:v(视频码率)控制压缩质量,可配合-vf scale=-2:720控制比例不变时的目标分辨率

Share

You may also like...

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注