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(压缩速度)是仅针对视频重新编码的参数 —— 这两组参数是互斥的,具体表现为:
- 当使用
-c:v copy时,FFmpeg 会忽略-crf和-preset参数,因为不需要重新编码,自然无需调整编码质量 / 速度; - 只有去掉
-c:v copy,让 FFmpeg 重新编码视频流时,-crf和-preset才会生效; -c:a copy本身和-crf/-preset无冲突(因为这两个参数只作用于视频),但音频流拷贝也无法通过这两个参数压缩。
使用硬编码器
先确认设备支持的硬解码方案
首先执行以下命令,查看 FFmpeg 编译时支持的硬解码器(不同编译版本支持的方案不同):
ffmpeg -hwaccels
常见输出(不同平台差异):
- Android/Linux:
vaapi、drm、mediacodec(Android 专属) - Windows:
d3d11va、cuda - macOS:
videotoolbox
硬解码的通用命令结构
ffmpeg -hwaccel [硬解方案] -hwaccel_device [设备] -i [输入文件] [编码参数] [输出文件]
关键参数:
-hwaccel:指定硬解方案(如mediacodec、d3d11va);-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参数 |
- 核心结论:硬件编码下,
-crf和-preset多数场景失效(尤其是 Android MediaCodec),仅少数硬编方案(如 macOS VideoToolbox、CUDA h265)部分支持 crf; - 替代方案:硬编优先用
-b:v(视频码率)控制压缩质量,这是所有硬编方案都支持的参数; - 实践建议: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控制比例不变时的目标分辨率