FFmpeg 快速上手

先把容器、编码和常用命令理顺

Posted by Yvain Zhang on April 27, 2023 主题:技术

很多人刚开始用 FFmpeg,都是先找一条命令跑通再说。应急当然可以,但如果容器、流、编码这些概念没分清,后面很容易反复踩坑:明明只想换个外壳,结果把内容也重新编码了;明明只想提音频,结果连原始参数也一块改掉了。

所以这篇不堆命令大全,先把几件最容易混的事理顺,再看最常见的处理场景。

1. 什么是 FFmpeg

FFmpeg 是音视频处理领域最常用的开源工具链之一,常见用途包括:

  • 音视频格式转换
  • 编码与转码
  • 解复用与复用
  • 截取、合并、抽帧
  • 获取媒体信息
  • 流媒体处理

如果你要系统做播放器、多媒体处理、转码链路或者流媒体相关工作,FFmpeg 基本绕不过去。

最常见的几个名字分别负责不同事情:

  • ffmpeg:转码、抽流、合并、过滤、推流
  • ffprobe:查看媒体信息
  • ffplay:简单播放

2. 先理解几个基本概念

容器不等于编码

MP4、AVI、MKV、TS、WAV 这些首先是容器。它们描述的是文件怎么组织,不等于内容具体怎么压缩。

比如一个 mp4 文件里,视频可能是 H.264,也可能是 H.265;音频可能是 AAC,也可能是 MP3。

一个容器里可能有多条流

一个文件里不一定只有视频和音频两样,常见还有:

  • 视频流
  • 音频流
  • 字幕流
  • 附件流
  • 数据流或元数据

所以“抽音频”“去视频流”“抽字幕”这些说法,本质上都是在重新组织流。

复用 / 解复用

  • 复用(mux):把多条流按容器规则重新打包
  • 解复用(demux):把流从容器里拆出来

比如 MP4 转 MKV、但音视频编码都不改,这其实是重新复用;从视频里提取 AAC,本质上就是把音频流拆出来。

编码格式和编码器不是一回事

H.264、H.265、AAC、MP3 这些是编码格式。libx264libx265aaclibmp3lame 这些是具体编码器实现。

同一种编码格式,可能对应多个编码器实现,它们在速度、压缩率、质量和许可证上都可能不同。

3. 用 FFmpeg 前,先看输入文件

如果你还不熟悉 FFmpeg 本身支持什么,也可以先看它提供的能力范围:

ffmpeg -formats
ffmpeg -codecs
ffmpeg -encoders

很多误操作都不是命令本身有多复杂,而是还没看清输入文件就开始转。

先养成这个习惯:

ffprobe input.mp4

或者:

ffmpeg -i input.mp4

至少先看清这些信息:

  • 容器类型
  • 视频编码格式
  • 音频编码格式
  • 分辨率
  • 帧率
  • 采样率
  • 声道数
  • 码率

输入看清楚了,后面很多判断就自然了:到底只是换容器,还是必须转码;到底需不需要重采样,还是只改输出封装就够。

4. 命令行结构和常见参数

一个典型的 FFmpeg 命令,通常就是这个结构:

ffmpeg [全局参数] [输入参数] -i input [输出参数] output

常见参数可以先记住这些:

  • -i:输入文件
  • -y:覆盖输出文件
  • -c:v:指定视频编码器
  • -c:a:指定音频编码器
  • -c copy:直接拷贝流,不重新编码
  • -vn:去掉视频流
  • -an:去掉音频流
  • -ss:跳转到指定时间点
  • -t:输出指定时长
  • -ar:音频采样率
  • -ac:声道数
  • -b:a:音频码率

这里最值得先记住的是 -c copy。看到它,就要想到这次大概率不是转码,而是在搬运流。

5. 容器转换和转码不要混淆

这是 FFmpeg 初学时最容易搞混的地方。

只换容器

ffmpeg -i input.mp4 -c copy output.mkv

这条命令只是把流重新装进另一个容器,不改视频编码,也不改音频编码。

这种方式的好处很直接:

  • 不损失质量
  • CPU 消耗低

真正的转码

ffmpeg -i input.mp4 -c:v libx265 -c:a aac output.mp4

这时就不是“换外壳”,而是视频和音频都重新编码了。目标平台不支持原编码,或者你需要调整体积、码率、分辨率时,才会走到这一步。

如果你想快速判断一条命令是不是转码,先看两件事:

  • 有没有 -c copy
  • 有没有显式指定新的编码器

6. 最常见的几个处理任务

查看文件信息

ffprobe input.mp4

这是最基本的一步。

只换容器

ffmpeg -i input.mp4 -c copy output.mkv

适合内容不变,只是目标平台更偏好另一个容器的场景。

只提取音频

ffmpeg -i input.mp4 -vn -c:a copy output.aac

如果原始音频本来就是 AAC,这条命令会很高效。

WAV 转 MP3

ffmpeg -i input.wav -c:a libmp3lame -b:a 192k output.mp3

WAV 转 AAC

ffmpeg -i input.wav -c:a aac -b:a 128k output.m4a

截取一段音视频

ffmpeg -ss 00:00:10 -i input.mp4 -t 00:00:20 -c copy output.mp4

如果只是粗剪,并且允许按关键帧切,-c copy 往往就够了。

重采样 PCM

ffmpeg -f s16le -ar 48000 -ac 1 -i in.pcm -f s16le -ar 16000 -ac 1 out.pcm

这类操作在语音算法、AEC、ASR 前处理场景里很常见,因为很多算法要求固定采样率和声道数。

7. 什么时候优先考虑 -c copy

经验上,这几类任务优先考虑直接拷贝流:

  • 换容器
  • 抽流
  • 不要求重新压缩的裁剪
  • 快速验证媒体链路

因为一旦重编码,你就得额外面对编码速度、码率选择、画质 / 音质损失、编码器兼容性这些问题。

能不转码就别转码,这条经验在很多场景里都适用。

8. 什么时候必须转码

下面这些场景通常没法只靠拷贝流完成:

  • 目标设备不支持原编码
  • 需要降低码率或体积
  • 需要改分辨率
  • 需要改音频采样率或声道数
  • 需要做滤镜处理
  • 需要生成特定流媒体输出格式

比如 H.265 视频要兼容旧设备,可能就得转回 H.264;48 kHz 双声道音频要给语音模型使用,也可能得转成 16 kHz 单声道。

9. 使用 FFmpeg 时更实用的几个建议

先明确目标,再写命令

在敲命令前先想清楚:目标平台支持什么容器、支持什么编码、是否允许失真、是批处理还是单次调试。

先确认输入,再决定输出

不要一上来就转。先 ffprobe 看输入,再决定是拷贝、转码、重采样还是分片。

参数尽量显式

处理音频时,建议把这些参数写清楚:

  • -ar
  • -ac
  • -b:a
  • -c:a

否则结果容易依赖默认值,不利于复现和排查。

善用帮助系统

很多时候不用到处搜二手资料,FFmpeg 自带帮助已经够用了:

ffmpeg -h muxer=flv
ffmpeg -h filter=atempo
ffmpeg -h encoder=libx264

10. 总结

FFmpeg 真正的门槛,不是命令长,而是概念容易混在一起。先想清楚这几个问题:

  • 文件外壳是什么
  • 里面有哪些流
  • 每条流用了什么编码
  • 目标输出到底要什么

这几件事想清楚之后,大部分命令其实都能顺着推出去,不需要每次都靠“复制一条网上命令试试看”。