FFmpeg 是什么?它在视频转换时做了哪些事?

IT那些事2026-10-02发布 WarpEdit
1,337 0 0

把一段视频交给转换软件,选好 MP4,点击开始,进度条就动了起来。界面下面究竟在忙什么?FFmpeg 是一套开源音视频处理工具与程序库,能够读取媒体、处理画面和声音,再写出文件。转换时,它可能重新编码,也可能直接复制原有音视频数据;换了后缀,不等于画面一定被重新压缩。

清爽手绘视频处理工作台,FFmpeg 接收画面与声音素材并输出视频文件

你看到 MP4,里面装的是什么

FFmpeg 这个名字通常指整个项目,包括开发者可调用的程序库和命令行工具。用户说“用 FFmpeg 转视频”,通常是运行其中的 ffmpeg;同一项目中的 ffprobe 用来查看媒体信息,ffplay 用来播放。某个转换软件是否调用了 FFmpeg,要看该软件的说明,不能仅凭“能转视频”就认定。FFmpeg 官方介绍[1]列出了这些工具与程序库的分工。

理解它做的事,先把一个视频文件拆开看。日常所说的“一段视频”,内部往往有一条视频流和一条音频流,也可能带字幕、多条音轨及其他信息。画面和声音可以采用不同的编码方式,再装进同一个文件。

MP4、MKV 是封装格式,也叫容器;H.264、H.265 是视频编码方式,AAC 是音频编码方式。容器规定这些流和相关信息怎样组织,编码方式规定画面或声音怎样表示。常见视频使用压缩编码,但“容器”和“编码”是两层事情。

可以把容器暂时想成一个有目录的文件夹,里面分别放着画面和声音的记录。这个类比只解释层次关系:真实文件不是几个普通文件随意塞在一起,还要按格式保存索引、时间戳等信息,让播放器知道什么时候显示画面、播放声音。同样是 .mp4,里面的编码也可能不同;一个播放器能读 MP4 容器,不代表它支持其中每一种编码。

MP4 容器内部放着 H.264 视频流和 AAC 音频流,区分文件封装与音视频编码
层次示意:MP4 是容器,H.264 和 AAC 分别是这里的视频、音频编码;实际文件也可能使用其他编码或包含更多流。

需要转码时,画面会经过哪些环节

假设你要把一段视频的画面从 1280×720 缩到 640×360,并输出成 MP4。FFmpeg 处理这条视频流时,可以按下面五个环节理解。官方转换流程文档[2]区分了解封装、解码、滤镜、编码和封装。

解封装:取出要处理的流。先读取输入文件的结构,把选中的视频、音频等流的已编码数据交给后续环节。“解封装”不是把画面解成图片,也没有自动改变编码。

解码:得到可以处理的画面。视频解码器把编码数据还原成一帧帧可供处理的图像。音频如果也需要处理,则会由相应解码器得到音频采样数据。这里的“还原”不表示能找回有损编码时已经丢失的细节。

滤镜处理:按要求修改内容。缩放、裁剪、叠加画面等操作,在解码后的帧上进行。FFmpeg 中的“滤镜”不仅指调色特效,改变分辨率也是滤镜处理;如果没有这类修改,就不需要特意加一个缩放步骤。

编码:重新生成编码数据。处理后的画面交给编码器,例如用 libx264 生成 H.264 视频。即使输入、输出都叫 H.264,只要画面经过解码再编码,这条流仍然发生了转码。编码器和质量、码率等设置,会影响输出体积、耗时和画质;常见的有损转码可能进一步损失细节。

封装:组织成输出文件。最后,封装器把编码好的流和所需信息写成 MP4 等目标格式。每帧画面、每段声音都需要合适的时间信息,不能只把字节拼在一起就指望它们同步播放。

这些环节说明数据怎样流动,并不要求“整部视频先全部解码到硬盘,全部完成后才开始编码”。每条流也可以走不同路线:画面需要缩放,声音不需要变,就可以只转码视频、直接复制音频。

只换容器,可以绕过重新编码

如果原有音视频编码已经适合目标容器和播放器,只想把 MKV 中的流写进 MP4,可以尝试重封装:解封装之后,把选中的已编码数据直接交给新的封装器。

FFmpeg 将这种不经过解码、滤镜和重新编码的方式称为流复制(streamcopy),命令里的 -c copy 就是这个意思。官方流复制说明[3]指出,它适合更换容器、调整流的数量等任务,因为省去了重新编码,通常处理较快,也不会产生重新编码带来的画质损失。

但它有适用条件:目标容器必须接得住这些流及所需信息,播放端也要能解码。某些字幕、音频编码或源文件信息不适合目标格式时,直接复制可能失败;保留不兼容的视频编码,也不会让旧设备突然支持它。流复制不能同时完成缩放、裁剪、把字幕烧进画面等需要改动图像的操作。

重封装也不是在资源管理器里把 .mkv 改名为 .mp4。改名只改文件名,原来的内部结构仍然存在;重封装会实际读取源容器,再写出目标容器的结构。音视频数据可以不重新编码,整个文件的字节却会变化。

转码经过解封装、解码、画面处理、编码与封装,流复制则直接传递已编码数据到封装器
按单条视频流简化绘制。上路以缩放为例,下路要求目标容器兼容;同一文件中的声音可以走另一条路线。

拿同一段短片,走两条转换路线

为了看清区别,我们用 FFmpeg 生成了一个 3 秒人工样本:1280×720、每秒 25 帧的测试画面,配上 440 Hz 的测试音,编码为 H.264 视频与 AAC 音频,装进 input.mkv。这不是手机或电影素材,测试环境为 Windows、FFmpeg 8.1.2 的 Gyan 构建。

第一条路线只换容器:

ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -c copy -n output.mp4

第二条路线缩小画面,同时保留已编码的声音:

ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -vf scale=640:360 -c:v libx264 -preset medium -crf 23 -c:a copy -n smaller.mp4

两条命令都明确选择第一条视频流和第一条音频流;-n 表示输出文件已存在就停止,避免覆盖。第二条的 scale 修改画面尺寸,libx264 负责重新编码视频,-c:a copy 则让音频走复制路线。这里的质量参数只是本次样本设置,不是所有视频的最佳值。

输出文件 视频编码与尺寸 音频编码 本次核验结果
output.mp4 H.264,1280×720 AAC 视频和音频的数据包内容均与输入一致
smaller.mp4 H.264,640×360 AAC 视频数据包改变,音频数据包与输入一致

我们用 ffprobe 回读编码、尺寸和流类型,并逐条比较两种输出中已编码音视频数据包的 SHA-256 摘要。表中的“一致”针对数据包内容,不是整个文件,也不是时间戳、字幕和所有元数据都保持原样。这个实验验证了本次两条命令的处理路线,没有测试所有格式的兼容性或转换速度。

两份结果的后缀都叫 MP4,内部经历却不同。是否转码,要看各条流的处理方式,不能只看输入、输出的文件名。

提取声音、缩小体积,要先确定目标

“从视频里提取声音”也不一定需要重新编码。本次样本的 AAC 音频可以直接复制到 M4A 文件中,我们另外做了这一步,并核对了音频数据包内容。如果要求输出 MP3,就需要把 AAC 解码,再用相应编码器生成 MP3;把文件改成 .mp3 不会完成转换。音频原本是什么编码、目标容器支持什么,决定了能否直接复制。

“让文件小一点”则需要另一种判断。只换容器不能保证明显缩小;压低码率、改变质量设置或缩小画面,通常涉及重新编码,结果取决于素材与设置。本站的文件压缩原理文章解释了为什么把视频放进 ZIP 往往省不了多少空间,和这里的音视频转码处理对象不同。

实际转换前,可以用 ffprobe -v error -show_format -show_streams input.mkv 查看容器、各条流的编码、画面尺寸等信息,再确认接收端的要求:它只是要求 MP4 文件,还是还要求特定编码、分辨率或音频格式?多音轨或带字幕的文件还要确认保留哪些流;FFmpeg 没有显式指定 -map 时会自动选择,不能默认所有音轨、字幕都进入输出。

想保留现有画面又能兼容播放,就先判断流复制能否满足要求;想改变尺寸、画面内容或不兼容的编码,就需要相应的转码。转换成功之后,还要检查所需声音和字幕是否保留,以及目标设备能否正常播放。ffprobe 官方文档[4]说明了媒体信息的查看方式。

参考资料

  • [1] FFmpeg 官方介绍:https://ffmpeg.org/about.html
  • [2] 官方转换流程文档:https://ffmpeg.org/ffmpeg.html#Detailed-description
  • [3] 官方流复制说明:https://ffmpeg.org/ffmpeg.html#Streamcopy
  • [4] ffprobe 官方文档:https://ffmpeg.org/ffprobe.html
© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...