目录
[1.1 起源与发展](#1.1 起源与发展)
[1.2 设计原则](#1.2 设计原则)
[2.1 应用层(命令行工具)](#2.1 应用层(命令行工具))
[2.2 中间层(功能模块)](#2.2 中间层(功能模块))
[2.3 基础层(核心处理)](#2.3 基础层(核心处理))
[2.4 硬件加速层](#2.4 硬件加速层)
[2.5 模块交互示例](#2.5 模块交互示例)
[3.1 libavutil ------ 基础工具库(所有模块的基石)](#3.1 libavutil —— 基础工具库(所有模块的基石))
[3.1.1 职责](#3.1.1 职责)
[3.1.2 关键结构体](#3.1.2 关键结构体)
[3.1.3 技术实现要点](#3.1.3 技术实现要点)
[3.2 libavformat ------ 容器处理(Demuxer/Muxer)](#3.2 libavformat —— 容器处理(Demuxer/Muxer))
[3.2.1 职责](#3.2.1 职责)
[3.2.2 核心结构体](#3.2.2 核心结构体)
[3.3 libavcodec ------ 编解码核心](#3.3 libavcodec —— 编解码核心)
[3.3.1 职责](#3.3.1 职责)
[3.3.2 核心结构体](#3.3.2 核心结构体)
[3.3.3 解码流程(典型)](#3.3.3 解码流程(典型))
[3.3.4 模块交互](#3.3.4 模块交互)
[3.4 libavfilter ------ 音视频滤镜框架](#3.4 libavfilter —— 音视频滤镜框架)
[3.4.1 职责](#3.4.1 职责)
[3.4.2 核心概念:](#3.4.2 核心概念:)
[3.4.3 关键结构体](#3.4.3 关键结构体)
[3.4.4 工作流程](#3.4.4 工作流程)
[3.4.5 模块交互:](#3.4.5 模块交互:)
[3.5 libswscale 与 libswresample ------ 格式转换专用库](#3.5 libswscale 与 libswresample —— 格式转换专用库)
[3.5.1 libswscale(视频)](#3.5.1 libswscale(视频))
[3.5.2 libswresample(音频)](#3.5.2 libswresample(音频))
[3.6 libavdevice ------ 设备输入/输出](#3.6 libavdevice —— 设备输入/输出)
[3.6.1 职责](#3.6.1 职责)
[3.6.2 使用方式:](#3.6.2 使用方式:)
[四、FFmpeg 构建](#四、FFmpeg 构建)
[4.1 获取源代码](#4.1 获取源代码)
[4.2 安装依赖](#4.2 安装依赖)
[4.3 配置构建选项](#4.3 配置构建选项)
[4.4 编译与安装](#4.4 编译与安装)
[五、FFmpeg 使用方式](#五、FFmpeg 使用方式)
[方式 1:命令行工具(快速处理音视频)](#方式 1:命令行工具(快速处理音视频))
[方式 2:C/C++ 程序中集成 FFmpeg 库(开发级使用)](#方式 2:C/C++ 程序中集成 FFmpeg 库(开发级使用))
一、FFmpeg技术背景
1.1 起源与发展
FFmpeg项目诞生于2000年,由法国程序员Fabrice Bellard主导开发。其最初目标是创建一个开源的MPEG-4视频编码器,以解决当时商业编码器价格昂贵的问题。项目名称"FFmpeg"中的"FF"不仅代表"Fast Forward"(快速前进),还隐含了对MPEG标准组织的调侃 - 将"MPEG"的首字母"M"替换为"FF"。
经过20多年的发展,FFmpeg已从一个简单的编码器成长为完整的音视频处理解决方案。目前由全球开发者社区共同维护,采用LGPL/GPL开源协议。其核心组件包括:
- libavcodec:编解码库(支持350+编码格式)
- libavformat:多媒体容器处理
- libavfilter:滤镜处理框架
- libswscale:图像缩放/色彩空间转换
典型应用场景:
- YouTube使用FFmpeg处理用户上传视频
- VLC媒体播放器依赖其解码能力
- HandBrake视频转换工具基于FFmpeg核心
- OBS直播软件利用其实时编码功能
1.2 设计原则
-
模块化架构:
- 将音视频处理流程分解为独立的功能模块
- 例如可单独使用libswresample进行音频重采样
- 支持最小化编译(仅包含所需组件)
-
零拷贝优先:
- 采用AVBufferRef引用计数机制
- 示例:多个滤镜处理同一帧时共享内存
- 通过av_frame_ref()实现帧数据共享
-
统一API设计:
- 硬件加速(Vulkan/VAAPI)与软件处理使用相同接口
- 文件输入(avformat_open_input)与网络流(RTMP)调用方式一致
- 编码(avcodec_send_frame)与解码(avcodec_receive_packet)对称API
-
可扩展性:
- 运行时注册机制(av_register_all)
- 支持动态加载第三方编解码器
- 滤镜系统允许自定义处理链(如添加水印滤镜)
- 协议层可扩展(支持新增流媒体协议)
二、整体架构
FFmpeg 由 8 个核心库 + 3 个命令行工具组成,采用分层架构设计:
2.1 应用层(命令行工具)
- ffmpeg:多媒体处理工具(转码/剪辑/流处理)
- ffplay:基于 SDL 的简易播放器
- ffprobe:媒体文件分析工具 示例:
ffmpeg -i input.mp4 -c:v libx264 output.mp4
2.2 中间层(功能模块)
- libavfilter:滤镜处理框架(支持 200+ 滤镜) ▶ 示例:添加水印、画面旋转、音频混音
- libavformat:封装/解封装(支持 100+ 格式)
- libavdevice:设备采集/输出(摄像头/屏幕捕获)
2.3 基础层(核心处理)
- libavcodec:编解码器(含 1000+ 编解码器) ▶ 硬件加速接口:支持 CUDA/QSV/VAAPI 等
- libswscale:图像缩放/色彩空间转换
- libswresample:音频重采样/格式转换
- libavutil:基础工具(数学运算/内存管理/日志)
2.4 硬件加速层
- 通过 libavcodec 对接各平台加速接口
- 典型应用:4K视频转码时启用 NVIDIA NVENC
2.5 模块交互示例
视频转码流程:avformat(解封装) → avcodec(解码) → avfilter(处理) → swscale(分辨率调整) → avcodec(编码) → avformat(封装)
三、核心模块详解(含职责、流程、结构体)
3.1 libavutil ------ 基础工具库(所有模块的基石)
3.1.1 职责
- 提供通用数据结构、内存管理、日志、数学运算、时间戳处理等。
3.1.2 关键结构体
| 结构体 | 说明 | 字段重点 |
|---|---|---|
AVFrame |
存储原始音视频帧(解码后或编码前) | data[8], linesize[8], width/height, sample_rate, nb_samples, format, pts |
AVPacket |
存储压缩数据包(编码后或解码前) | data, size, pts, dts, stream_index, flags |
AVBufferRef |
引用计数内存管理(用于 AVFrame.data 和 AVPacket.data) |
buffer(指向实际内存), size, refcount |
AVRational |
有理数,用于表示时间基(time base) | num(分子), den(分母),如 {1, 1000} 表示毫秒 |
3.1.3 技术实现要点
- 内存安全 :
av_frame_alloc()/av_frame_unref()/av_frame_free()成对使用。 - 时间戳转换 :
av_rescale_q()用于在不同 time base 间转换 PTS/DTS。 - 日志系统 :
av_log()支持多级别(ERROR/WARNING/INFO/DEBUG)。
3.2 libavformat ------ 容器处理(Demuxer/Muxer)
3.2.1 职责
- Demuxing :从文件/网络流中分离出音视频流(如 MP4 → H.264 + AAC)。
- Muxing :将多个流封装成目标容器(如 H.264 + AAC → MP4)。
- 支持 200+ 容器格式(MP4、MKV、FLV、TS、RTMP、HLS 等)。
3.2.2 核心结构体
| 结构体 | 说明 |
|---|---|
AVFormatContext |
整个媒体文件/流的上下文,包含所有流、元数据、IO 上下文 |
AVStream |
单个流(音频/视频/字幕),包含 codecpar(编解码参数)、time_base、index |
AVInputFormat / AVOutputFormat |
Demuxer/Muxer 描述符(如 ff_mov_demuxer) |
AVIOContext |
I/O 抽象层(文件/HTTP/RTMP 统一接口) |
3.2.3工作流程(Demuxing)
cpp
AVFormatContext *fmt_ctx = NULL;
avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL); // 1. 打开输入
avformat_find_stream_info(fmt_ctx, NULL); // 2. 探测流信息
for (int i = 0; i < fmt_ctx->nb_streams; i++) {
AVStream *st = fmt_ctx->streams[i];
// st->codecpar->codec_id == AV_CODEC_ID_H264 ?
}
AVPacket pkt;
while (av_read_frame(fmt_ctx, &pkt) >= 0) { // 3. 循环读取 packet
// pkt.stream_index 指明属于哪个流
// 处理解码...
av_packet_unref(&pkt);
}
avformat_close_input(&fmt_ctx);
3.2.4模块交互
- 输出
AVPacket→ 交给libavcodec解码。 - 从
libavcodec接收AVPacket→ 封装写入文件(muxing)。
3.3 libavcodec ------ 编解码核心
3.3.1 职责
- 提供数百种音视频编解码器的实现(软解/软编)。
- 支持硬件加速(通过
AVHWDeviceContext)。
3.3.2 核心结构体
| 结构体 | 说明 |
|---|---|
AVCodec |
编解码器描述符(如 ff_h264_decoder) |
AVCodecContext |
编解码器运行时上下文(宽高、比特率、profile、线程数等) |
AVCodecParameters |
只读 的编解码参数(用于 AVStream.codecpar,避免修改原始信息) |
3.3.3 解码流程(典型)
cpp
// 1. 查找解码器
AVCodec *dec = avcodec_find_decoder(AV_CODEC_ID_H264);
AVCodecContext *dec_ctx = avcodec_alloc_context3(dec);
// 2. 从 AVStream 复制参数
avcodec_parameters_to_context(dec_ctx, stream->codecpar);
// 3. 打开解码器
avcodec_open2(dec_ctx, dec, NULL);
// 4. 解码循环
AVPacket *pkt = ...; // 来自 av_read_frame
AVFrame *frame = av_frame_alloc();
avcodec_send_packet(dec_ctx, pkt); // 输入压缩包
while (avcodec_receive_frame(dec_ctx, frame) == 0) { // 输出原始帧
// 处理 frame(送滤镜 or 显示)
av_frame_unref(frame);
}
3.3.4 模块交互
- 输入:
AVPacket(来自libavformat或用户) - 输出:
AVFrame(送给libavfilter或显示) - 反之亦然(编码时)
3.4 libavfilter ------ 音视频滤镜框架
3.4.1 职责
- 对
AVFrame进行实时处理:缩放、裁剪、水印、降噪、变速、色彩校正等。
3.4.2 核心概念:
- Filter Graph:由多个 filter 节点组成的有向图。
- Buffer Source/Sink:图的输入/输出端口。
3.4.3 关键结构体
| 结构体 | 说明 |
|---|---|
AVFilterGraph |
滤镜图上下文 |
AVFilterContext |
单个滤镜实例(如 scale, overlay) |
AVBuffersrcParameters |
输入源参数(宽高、格式、time_base) |
3.4.4 工作流程
cpp
// 1. 创建图
AVFilterGraph *graph = avfilter_graph_alloc();
// 2. 创建输入/输出
AVFilterContext *buffersrc, *buffersink;
avfilter_graph_create_filter(&buffersrc, avfilter_get_by_name("buffer"), "in", args, NULL, graph);
avfilter_graph_create_filter(&buffersink, avfilter_get_by_name("buffersink"), "out", NULL, NULL, graph);
// 3. 连接滤镜(例如:缩放)
AVFilterContext *scale = ...
avfilter_link(buffersrc, 0, scale, 0);
avfilter_link(scale, 0, buffersink, 0);
// 4. 配置图
avfilter_graph_config(graph, NULL);
// 5. 处理帧
av_buffersrc_add_frame(buffersrc, input_frame);
AVFrame *output_frame = av_frame_alloc();
av_buffersink_get_frame(buffersink, output_frame);
3.4.5 模块交互:
- 输入:
AVFrame(来自libavcodec解码) - 输出:
AVFrame(送给libavcodec编码或显示)
3.5 libswscale 与 libswresample ------ 格式转换专用库
3.5.1 libswscale(视频)
- 功能:图像缩放、颜色空间转换(YUV ↔ RGB)、像素格式转换。
- 核心函数:
sws_getContext(),sws_scale() - 结构体:
SwsContext
3.5.2 libswresample(音频)
- 功能:重采样(44.1kHz → 48kHz)、声道布局转换(立体声 → 5.1)、格式转换(float → s16)。
- 核心函数:
swr_init(),swr_convert() - 结构体:
SwrContext
3.6 libavdevice ------ 设备输入/输出
3.6.1 职责
- 抽象摄像头、麦克风、屏幕捕获、采集卡等硬件设备。
- 在 Linux 上基于 V4L2,在 Windows 上基于 dshow,在 macOS 上基于 AVFoundation。
3.6.2 使用方式:
cpp
// 打开摄像头(Linux)
AVFormatContext *dev;
avformat_open_input(&dev, "/dev/video0", av_find_input_format("v4l2"), NULL);
四、FFmpeg 构建
4.1 获取源代码
4.1.1 官方下载方式:
- 生产环境推荐使用稳定版(标记为 release 的版本)
- 开发测试可使用 git master 分支获取最新功能
4.1.2 版本选择建议:
- 通过 git 克隆最新版本:
git clone https://git.ffmpeg.org/ffmpeg.git - 或下载稳定版压缩包:
wget https://ffmpeg.org/releases/ffmpeg-x.x.x.tar.gz - 解压命令:
tar -xzvf ffmpeg-x.x.x.tar.gz
4.2 安装依赖
4.2.1 基础编译工具:
- GCC/G++ 编译器
- make 工具
- pkg-config
- 安装命令(Ubuntu示例):
sudo apt install build-essential pkg-config
4.2.2 常用编解码器依赖:
-
libx264(H.264编码)
-
libx265(HEVC编码)
-
libvpx(VP8/VP9编码)
-
libfdk-aac(AAC音频编码)
-
安装示例:
sudo apt install libx264-dev libx265-dev libvpx-dev libfdk-aac-devbash# 基础编译工具 sudo apt update sudo apt install build-essential pkg-config # 可选但推荐的第三方库(按需安装) sudo apt install \ yasm nasm \ # 汇编优化 libx264-dev libx265-dev \ # H.264/H.265 编码 libvpx-dev \ # VP8/VP9 libfdk-aac-dev \ # 高质量 AAC libmp3lame-dev \ # MP3 编码 libopus-dev \ # Opus 音频 libvorbis-dev \ # Vorbis libass-dev \ # 字幕渲染 libfreetype6-dev \ # 文字水印 libva-dev libdrm-dev \ # Intel VA-API 硬件加速 libnvcodec-dev \ # NVIDIA NVENC/NVDEC(需额外添加仓库) libsdl2-dev # ffplay 依赖
4.3 配置构建选项
4.3.1 基本配置命令:
./configure \
--prefix=/usr/local/ffmpeg \
--enable-gpl \
--enable-nonfree \
--enable-libx264 \
--enable-libx265 \
--enable-libvpx \
--enable-libfdk-aac
4.3.2 常用配置参数说明:
--prefix:指定安装目录--enable-shared:构建动态链接库--disable-static:禁用静态库构建--extra-cflags/--extra-ldflags:自定义编译/链接选项- --enable-gpl: 启用 GPL 许可代码(如 x264)
- --enable-nonfree:启用非自由许可证代码(如 fdk-aac)
- --enable-debug=3:保留调试符号,便于 GDB 调试
- --disable-programs:若只用于开发,可不编译 ffmpeg/ffplay
4.3.3 平台特定配置:
- Windows:需要安装 MSYS2 或 Cygwin 环境
- macOS:建议使用 Homebrew 安装依赖
- 交叉编译:需指定
--cross-prefix和--arch参数
4.4 编译与安装
4.1 编译过程:
- 执行
make -j$(nproc)进行并行编译 - 可使用
make -j4指定并行任务数 - 完整编译通常需要10-30分钟(取决于硬件配置)
4.2 安装步骤:
-
执行
sudo make install安装到指定目录 -
设置环境变量:
export PATH="/usr/local/ffmpeg/bin:$PATH" export LD_LIBRARY_PATH="/usr/local/ffmpeg/lib:$LD_LIBRARY_PATH"
4.3 验证安装:
- 执行
ffmpeg -version查看版本信息 - 检查编解码器支持:
ffmpeg -codecs - 测试转码功能:
ffmpeg -i input.mp4 -c:v libx264 output.mp4
五、FFmpeg 使用方式
方式 1:命令行工具(快速处理音视频)
这是FFmpeg最常见的使用方式,适合快速完成音视频处理任务。用户可以直接在终端/命令行中执行FFmpeg命令,无需编程即可实现:
-
格式转换(如MP4转AVI)
-
视频裁剪(指定开始和结束时间)
-
调整分辨率(如1080p转720p)
-
提取音频(从视频中分离音轨)
-
添加水印(图片或文字)
-
示例命令:
bash# 将input.mp4转换为output.avi ffmpeg -i input.mp4 output.avi # 裁剪视频从00:01:30到00:02:45 ffmpeg -i input.mp4 -ss 00:01:30 -to 00:02:45 -c copy output.mp4
方式 2:C/C++ 程序中集成 FFmpeg 库(开发级使用)
适用于需要深度定制音视频处理功能的开发者:
- 通过链接FFmpeg静态/动态库(libavcodec, libavformat等)
- 使用FFmpeg API进行编程控制
- 可实现:
- 自定义编解码流程
- 实时流媒体处理
- 复杂滤镜效果
- 硬件加速编解码
典型开发流程:
c
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
int main() {
av_register_all(); // 初始化FFmpeg
// 更多处理代码...
return 0;
}
编译时需要正确链接FFmpeg库
bash
gcc -o program program.c -lavcodec -lavformat -lavutil