广告

FFmpeg 是怎么干活的?原理图解(小白版)

2026-08-20

很多人第一次用 ffmpeg,是敲下这样一行:

ffmpeg -i input.mp4 output.mkv

然后感叹:"哇,一行命令就把 mp4 变成 mkv 了。"

但我们做 tools.beer 最深的体会是:ffmpeg 根本不是个"格式转换器",它是一条多媒体加工厂流水线。 理解这条线,你就能看懂我们前面重编码与流复制的区别里"为什么流复制快、重编码慢"——因为那条线里,它们走的是完全不同的路段。

1. 一句话定义

FFmpeg 是一套开源的多媒体框架。ffmpeg 这个命令行,只是它的一个"操作台":你给一个输入,指定想要的输出,它就把背后的一组零件拼成一条流水线,把原料加工成成品。

真正干活的零件是这些库:

  • libavformat:负责拆箱和装箱(解封装 / 封装);
  • libavcodec:负责解码和编码(视频/音频的压缩与解压);
  • libavfilter:负责加工(裁剪、调音量、加水印等);
  • libswscale / libswresample:负责图像缩放和音频重采样。

对小白来说,你不用背库名。只要记住:ffmpeg 把五道工序串成一条线,原料从一头进、成品从另一头出。

2. 核心类比:多媒体加工厂流水线

把一次转换想象成一座工厂处理一批货:

  1. 解封装(demux)=拆箱:收到一个快递箱(容器文件),拆开,把里面的视频包、音频包分门别类拿出来。
  2. 解码(decode)=解压:把压缩过的视频/音频数据,解压回"原始素材"(一帧帧未压缩的画面、一串串原始音频采样)。
  3. 滤镜(filter)=加工(可选):对原始素材做处理——裁掉黑边、调音量、加水印、缩放分辨率。
  4. 编码(encode)=压缩:把加工好的原始素材,用目标编码重新压成小数据流。
  5. 封装(mux)=装箱:把新的视频流、音频流,按目标容器打包好、贴上索引,成为一个新文件。
FFmpeg 流水线:源文件从一头进,成品从另一头出流复制 -c copy:跳过中间三段,直接搬源文件容器+编码解封装demux拆箱解码decode解压(CPU 重)滤镜filter加工(可选)编码encode压缩(CPU 重)封装mux装箱目标文件新容器+编码解码 → 编码 是 CPU 最重的两段:这一段慢,整体就慢蓝=容器相关(拆/装箱);红=编码相关(解压/压缩);绿=可选加工流复制(-c copy)只走「解封装 → 封装」一段,所以秒级、零损失

3. 五个环节逐个看

  • 解封装(demux):读取容器文件,把交织在一起的视频包、音频包、字幕包分开。就像拆开快递箱,把衣服、书、零食分堆。
  • 解码(decode):把每一路压缩数据解压回原始形式。视频变成一帧帧像素,音频变成一串串采样。这一步很吃 CPU。
  • 滤镜(filter):可选项。比如 -vf "crop=..." 裁掉黑边、-af "volume=2" 调音量、scale 改分辨率。不写滤镜就直接跳过。
  • 编码(encode):把原始素材用目标编码重新压小。视频压成 H.264/H.265,音频压成 AAC/MP3。同样很吃 CPU,而且有损编码会损失画质。
  • 封装(mux):把新的视频流、音频流按目标容器(mp4/mkv/webm)打包,写入索引,成为可播放的文件。

4. 把前一篇串起来:流复制到底跳过了什么

回头看重编码 vs 流复制:所谓流复制(-c copy,就是在这条流水线里跳过了"解码 → 滤镜 → 编码"三段,在"解封装"之后,把数据包原封不动地直接送进"封装"。

因为根本没动音视频数据,所以:

  • 它快(CPU 几乎不参与);
  • 它零质量损失(数据一个字节没变);
  • 它只能换容器、提取流、不能改编码或分辨率。

重编码走的是完整流水线,尤其"解码→编码"这两段 CPU 最重,所以慢、且可能变糊。一张图看懂两件事的区别,正是我们这篇的目的。

5. 我们踩过的真实坑

这些不是抽象理论,是 tools.beer 在浏览器和桌面端跑 ffmpeg 时真真切切遇到的。

坑 1:浏览器里的 ffmpeg,起不来是因为少了两个 HTTP 头。 我们在 tools.beer 网页端用 FFmpeg.wasm(把 ffmpeg 编译成 WebAssembly 在浏览器跑)。它依赖 SharedArrayBuffer,而浏览器只在页面 crossOriginIsolated 时才提供这个能力——这又要求服务器同时返回 Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corp 两个响应头。缺一个,crossOriginIsolated 就是 false,ffmpeg core 一加载就报错。我们当时排查了很久才定位到是这两个头。

坑 2:浏览器 ffmpeg 比桌面原生慢,是有物理原因的。 流水线里"解码→编码"是 CPU 密集段。桌面端(我们用 Tauri 调原生 ffmpeg 二进制)能吃到多核和硬件加速;而浏览器里的 WebAssembly 版本没有这些优势,跑同一条流水线明显更慢。这解释了为什么桌面端"转成 mp4"(走 libx264 真重编码)耗时是实打实的,而网页端纯换容器的场景几秒就完——后者本质是流复制。

坑 3:ffmpeg 不是"转换器",它可能在你不知道时偷偷重编码。 ffmpeg -i in.mp4 out.mkv 看起来只是换格式。但如果目标容器不支持原编码,ffmpeg 会自动触发重编码,你未必察觉——直到发现"怎么转完变慢变糊了"。理解流水线,你才知道那一瞬间它其实跑完整条线、并重压了一遍。

6. 小结

  • FFmpeg 不是"格式转换器",而是一条解封装 → 解码 → 滤镜 → 编码 → 封装的流水线;
  • 蓝块管容器(拆/装箱),红块管编码(解压/压缩),绿块是可选加工;
  • 解码→编码是 CPU 最重的两段,整体快慢由它决定;
  • 流复制(-c copy)跳过中间三段,所以快且无损——这是前一篇"流复制快"的真正原因;
  • 同样一条线,浏览器 wasm 比桌面原生慢,是硬件加速差距,不是玄学。

延伸阅读

想立刻上手,可以直接在浏览器里把 MP4 转成 MP3

参考资料(权威来源)

FFmpeg 官网与文档
Wikipedia: FFmpeg

本文由 tools.beer 团队撰写,基于我们在浏览器端 FFmpeg.wasm 与桌面端原生 ffmpeg 转码中的真实踩坑经验整理。最后更新于 2026-08-20。

广告

阿里云 AI Agent 零代码部署 · 68 元起

轻量服务器 + Token Plan 组合购,分钟级部署 OpenClaw/Hermes AI 助手,7×24 小时在线、不限流量、数据自主可控,支持 11 款主流大模型

立即查看