如何用 FFmpeg 转换视频格式
FFmpeg 视频转格式实操:MP4、MOV、AVI、WebM、MKV 互转,编码器选择、画质控制、批量脚本。

视频转格式是日常处理中最常见的活——网页要 MP4、Apple 工作流要 MOV、开源项目要 WebM。FFmpeg 一条命令搞定。这篇文章从最简单的命令讲起,到编码器选择和批量脚本。
最简单的转格式
只换容器格式时,FFmpeg 会根据输出文件后缀自动决定目标格式:
# Convert MKV to MP4
ffmpeg -i input.mkv output.mp4
# Convert AVI to MOV
ffmpeg -i input.avi output.mov
# Convert MP4 to WebM
ffmpeg -i input.mp4 output.webm
不指定编码器时,FFmpeg 会按目标容器选默认值。能跑通,但画质和兼容性都不在你手里。
容器和编码器是两回事
往下看之前先把这两个概念分清楚:
- 容器(container):MP4、MKV、MOV、AVI、WebM——装视频、音频、元数据的"盒子"
- 视频编码器(codec):H.264、H.265、VP9、AV1——视频数据怎么压
- 音频编码器:AAC、Opus、MP3、FLAC——音频数据怎么压
容器是盒子,编码器是装在里面的东西。同一个编码器可以放进不同容器。
| 容器 | 常见视频编码器 | 常见音频编码器 | 适合场景 |
|---|---|---|---|
| MP4 | H.264、H.265、AV1 | AAC、MP3 | 网页、移动端、通用 |
| MKV | 任意 | 任意 | 存档、多轨 |
| MOV | H.264、H.265、ProRes | AAC、PCM | Apple、剪辑 |
| WebM | VP8、VP9、AV1 | Vorbis、Opus | 网页(开源) |
| AVI | H.264、MPEG-4 | MP3、PCM | 老设备兼容 |
怎么选编码器
H.264:兼容性最好
H.264(libx264)几乎所有设备和浏览器都能播。要保证别人都能打开,选它。
ffmpeg -i input.avi -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4
H.265 (HEVC):体积更小
同画质下文件体积大约减一半。代价是支持还没普及。
ffmpeg -i input.avi -c:v libx265 -crf 28 -preset medium -c:a aac -b:a 128k output.mp4
注意 H.265 的 CRF 刻度和 H.264 不一样。H.265 的 CRF 28 大致等价于 H.264 的 CRF 23。
VP9:免版税,网页友好
VP9 是 Google 的免版税编码器,配 WebM 容器,所有现代浏览器都支持。
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k output.webm
-b:v 0 是告诉 FFmpeg 走纯 CRF 模式(不限码率上限)。
AV1:下一代,但很慢
压缩率最强,编码速度也最慢。不赶时间、文件越小越好时再用。
ffmpeg -i input.mp4 -c:v libaom-av1 -crf 30 -cpu-used 4 -c:a libopus -b:a 128k output.mkv
-cpu-used 4 是个加速档位(0-8,越大越快但画质会降)。
编码器横向对比
| 编码器 | 压缩率 | 速度 | 浏览器支持 | 授权 |
|---|---|---|---|---|
| H.264 | 一般 | 快 | 全平台 | 需授权 |
| H.265 | 较好 | 中 | 在普及 | 需授权 |
| VP9 | 较好 | 慢 | 现代浏览器 | 免版税 |
| AV1 | 最好 | 很慢 | 在普及 | 免版税 |
音频编码器怎么配
不同容器有自己适合的音频编码器:
# MP4 + AAC(最常见)
ffmpeg -i input.mkv -c:v libx264 -crf 23 -c:a aac -b:a 192k output.mp4
# WebM + Opus(同码率下音质最好)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k output.webm
# MKV + FLAC(无损音频)
ffmpeg -i input.mov -c:v libx264 -crf 18 -c:a flac output.mkv
# MOV + PCM(未压缩,剪辑用)
ffmpeg -i input.mp4 -c:v copy -c:a pcm_s16le output.mov
| 音频编码器 | 音质 | 体积 | 适配容器 |
|---|---|---|---|
| AAC | 一般 | 小 | MP4、MOV |
| Opus | 优秀 | 最小 | WebM、MKV |
| MP3 | 一般 | 小 | MP4、AVI、MKV |
| FLAC | 无损 | 大 | MKV |
| PCM | 无损 | 很大 | MOV、WAV |
流复制:秒转
源文件的编码器和目标容器兼容时,直接复制流不重新编码。瞬时完成、无损:
# MKV 重新封装成 MP4,不重编码
ffmpeg -i input.mkv -c copy output.mp4
# 视频流直接复制,只重编音频
ffmpeg -i input.mkv -c:v copy -c:a aac -b:a 128k output.mp4
只有目标容器支持该编码器时才能流复制。比如 VP9 装不进 AVI。
画质和体积怎么平衡
CRF 模式:本地文件首选
CRF(Constant Rate Factor,恒定质量因子)画质和体积比最划算,编码器会按场景动态调码率。压缩相关的细节可以看视频压缩教程。
# 高画质(文件大)
ffmpeg -i input.avi -c:v libx264 -crf 18 -c:a aac -b:a 192k output.mp4
# 平衡
ffmpeg -i input.avi -c:v libx264 -crf 23 -c:a aac -b:a 128k output.mp4
# 小文件(画质降)
ffmpeg -i input.avi -c:v libx264 -crf 28 -c:a aac -b:a 96k output.mp4
双 pass 编码:要精确控大小
需要把文件压到指定大小时用 two-pass:
# Pass 1:分析
ffmpeg -i input.avi -c:v libx264 -b:v 2M -pass 1 -an -f null /dev/null
# Pass 2:编码
ffmpeg -i input.avi -c:v libx264 -b:v 2M -pass 2 -c:a aac -b:a 128k output.mp4
preset:速度换体积
同画质下,preset 越慢文件越小:
# 编码快,文件大
ffmpeg -i input.avi -c:v libx264 -crf 23 -preset fast -c:a aac output.mp4
# 编码慢,文件小
ffmpeg -i input.avi -c:v libx264 -crf 23 -preset slow -c:a aac output.mp4
转格式时顺手改分辨率
格式和缩放可以一起做:
# 转成 720p MP4
ffmpeg -i input.mkv -c:v libx264 -crf 23 -vf "scale=-2:720" -c:a aac -b:a 128k output.mp4
# 转成 1080p WebM
ffmpeg -i input.avi -c:v libvpx-vp9 -crf 30 -b:v 0 -vf "scale=-2:1080" -c:a libopus output.webm
批量脚本
转换整个目录
# 所有 AVI 转 MP4
for f in *.avi; do
ffmpeg -i "$f" -c:v libx264 -crf 23 -c:a aac -b:a 128k "${f%.avi}.mp4"
done
# 所有 MKV 流复制成 MP4
for f in *.mkv; do
ffmpeg -i "$f" -c copy "${f%.mkv}.mp4"
done
一份源文件输出多种格式
#!/bin/bash
# 一个源文件批量输出多种格式
INPUT="input.mp4"
# 网页用 MP4
ffmpeg -i "$INPUT" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k -movflags +faststart web.mp4
# 高质量 MKV 存档
ffmpeg -i "$INPUT" -c:v libx265 -crf 22 -preset slow -c:a flac archive.mkv
# WebM 走开源托管
ffmpeg -i "$INPUT" -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k web.webm
递归转换
# 递归找所有 AVI 转 MP4
find . -name "*.avi" -exec sh -c '
ffmpeg -i "$1" -c:v libx264 -crf 23 -c:a aac "${1%.avi}.mp4"
' _ {} \;
网页 MP4 必加 faststart
MP4 给网页播时一定要加 -movflags +faststart,把元数据挪到文件头,这样还没下完就能开始播:
ffmpeg -i input.mkv -c:v libx264 -crf 23 -c:a aac -movflags +faststart output.mp4
常用场景速查
# iPhone 的 MOV 转 MP4 用于分享
ffmpeg -i input.mov -c:v libx264 -crf 23 -c:a aac -b:a 128k -movflags +faststart output.mp4
# AVI 转 MP4(重编码)
ffmpeg -i input.avi -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4
# MP4 转 WebM 用于网页嵌入
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus -b:a 128k output.webm
# MKV 流复制成 MP4(无损)
ffmpeg -i input.mkv -c copy -movflags +faststart output.mp4
# 任意视频转 GIF(短片段)
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1" -t 5 output.gif
# MP4 切成 HLS
ffmpeg -i input.mp4 -c copy -hls_time 10 -hls_list_size 0 output.m3u8
常见坑
"Discarding packet" 警告:源容器有点问题。加 -err_detect ignore_err 跳过坏包。
"Non-monotonous DTS" 报错:时间戳乱了。加 -fflags +genpts 重建:
ffmpeg -i input.mkv -fflags +genpts -c:v libx264 -crf 23 -c:a aac output.mp4
容器不接受这个编码器:典型例子,VP9 塞不进 AVI。要么换容器,要么重编成兼容的编码器。
输出比输入还大:从高效编码器转回低效编码器,或者源已经被压得很狠。降 CRF 或者换更高效的编码器。
想跑在云上:FFHub
本地转单个文件没问题,但批量任务能把机器锁住几个小时。FFHub 让你通过 API 把同样的 FFmpeg 命令丢到云端跑——语法一样,不占本地 CPU。
适合的场景:批量转换、Web 应用集成、机器上没装 FFmpeg。
小结
- 编码器兼容时用流复制(
-c copy)——秒转 - 通用兼容选 H.264 + AAC + MP4
- 网页免版税选 VP9 + Opus + WebM
- 看重画质走 CRF 模式
- 网页 MP4 别忘了
-movflags +faststart - 整目录处理写个批量脚本
延伸阅读
- 如何用 FFmpeg 压缩视频 - 用 CRF、preset、缩放控制体积
- 如何用 FFmpeg 提取音频 - 从任意视频抽出音轨
- FFmpeg 视频压缩最佳实践 - 进一步压榨画质和体积