FFmpeg Filtergraph 打印系统文档
概述
FFmpeg 的 filtergraph 打印系统(graphprint)是一个调试和诊断工具,用于将 ffmpeg 运行时的 filtergraph 拓扑结构输出为结构化文本或可视化图表。它能够展示从输入文件经过解码器、过滤器链、编码器到输出文件的完整数据流路径。
该系统由以下文件组成:
| 文件 | 说明 |
|---|---|
fftools/graph/graphprint.h |
头文件,声明公共 API |
fftools/graph/graphprint.c |
实现文件,包含所有打印逻辑 |
fftools/resources/graph.css |
Mermaid HTML 输出的 CSS 样式 |
fftools/resources/graph.html |
Mermaid HTML 输出的 HTML 模板 |
公共 API
print_filtergraph()
c
int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph);
功能 :打印单个 filtergraph 的详细信息到内部缓冲区 fg->graph_print_buf。
参数:
fg--- 指向FilterGraph结构体的指针,包含 filtergraph 的配置信息graph--- 指向AVFilterGraph结构体的指针,包含 libavfilter 层面的 filter 图信息
返回值:成功返回 0,失败返回负的 AVERROR 错误码
调用时机 :在每个 filtergraph 配置完成后调用(见 ffmpeg_filter.c:3417)
输出内容:
- graph 索引、名称、描述
- graph 的输入端信息(输入索引、链接标签、关联 filter、媒体类型)
- graph 的输出端信息(输出索引、名称、链接标签、关联 filter、媒体类型)
- 每个 filter 的详细信息(名称、类型、参数、输入/输出 pad 的媒体参数)
线程模型:由于 FFmpeg 的多线程架构,每个 filtergraph 在各自的线程中将自身序列化到缓冲区,后续由主线程统一组装。
print_filtergraphs()
c
int print_filtergraphs(FilterGraph **graphs, int nb_graphs,
InputFile **ifiles, int nb_ifiles,
OutputFile **ofiles, int nb_ofiles);
功能:汇总所有 filtergraph 的缓冲数据,补充输入/输出文件流信息,统一输出到目标位置。
参数:
graphs---FilterGraph指针数组nb_graphs--- filtergraph 数量ifiles---InputFile指针数组nb_ifiles--- 输入文件数量ofiles---OutputFile指针数组nb_ofiles--- 输出文件数量
返回值:成功返回 0,失败返回负的 AVERROR 错误码
调用时机 :在 ffmpeg 退出前的清理阶段调用(见 ffmpeg.c:316)
输出内容(除各 filtergraph 的信息外,还包括):
- 输入文件及其流信息
- 输出文件及其流信息
- 解码器信息
- 编码器信息
- 流链接关系(stream links)
命令行选项
这三个选项定义在 ffmpeg_opt.c:1847-1854:
-print_graphs
将 filtergraph 数据打印到 stderr(通过 av_log 输出)。
ffmpeg -i input.mp4 -vf "scale=640:360" -c:v libx264 -y output.mp4 -print_graphs
-print_graphs_file <filename>
将 filtergraph 数据写入指定文件。使用 - 表示输出到 stdout。
ffmpeg -i input.mp4 -vf "scale=640:360" -c:v libx264 -y output.mp4 \
-print_graphs_file /tmp/graph.json
-print_graphs_format <format>
设置输出格式。默认为 json。可选格式包括:
| 格式 | 说明 |
|---|---|
json |
JSON 格式(默认) |
compact |
紧凑文本格式 |
csv |
CSV 格式 |
flat |
扁平键值对格式 |
ini |
INI 风格格式 |
xml |
XML 格式 |
default |
默认文本格式 |
mermaid |
Mermaid 流程图文本格式 |
mermaidhtml |
Mermaid 流程图嵌入 HTML(可用浏览器查看可视化结果) |
ffmpeg -i input.mp4 -vf "scale=640:360" -c:v libx264 -y output.mp4 \
-print_graphs_file /tmp/graph.html -print_graphs_format mermaidhtml
输出数据结构
输出数据按以下层级组织(对应 graphprint.c:78-121 中定义的 section):
root
├── graphs # 所有 filtergraph
│ └── graph # 单个 filtergraph
│ ├── graph_index # graph 索引
│ ├── name # 名称(如 "Graph 0.0")
│ ├── id # 唯一标识符(如 "Graph_0_0")
│ ├── description # filtergraph 描述字符串
│ ├── graph_inputs # graph 输入端
│ │ └── graph_input # 单个输入
│ ├── graph_outputs # graph 输出端
│ │ └── graph_output # 单个输出
│ └── filters # 所有 filter 节点
│ └── filter # 单个 filter
│ ├── filter_inputs # filter 输入 pad
│ │ └── filter_input
│ │ └── hw_frames_context # 硬件帧上下文
│ └── filter_outputs # filter 输出 pad
│ └── filter_output
│ └── hw_frames_context
├── inputfiles # 输入文件
│ └── inputfile
│ └── inputstreams
│ └── inputstream
├── outputfiles # 输出文件
│ └── outputfile
│ └── outputstreams
│ └── outputstream
├── decoders # 解码器
│ └── decoder
├── encoders # 编码器
│ └── encoder
└── streamlinks # 流链接关系
└── streamlink
使用示例
示例 1:简单视频缩放 --- JSON 输出
bash
ffmpeg -i input.mp4 \
-vf "scale=1280:720" \
-c:v libx264 -y output.mp4 \
-print_graphs_file /tmp/graph.json \
-print_graphs_format json
输出 JSON 文件包含完整的 filtergraph 拓扑,包括每个 filter 的名称、类型、输入/输出 pad 上的媒体参数(分辨率、像素格式、帧率等)。
示例 2:复杂 filtergraph --- Mermaid HTML 可视化
bash
ffmpeg -i video.mp4 -i audio.mp4 \
-filter_complex "[0:v]split=2[v1][v2]; \
[v1]scale=1280:720,format=yuv420p[vout1]; \
[v2]scale=640:360,format=yuv420p[vout2]" \
-map "[vout1]" -c:v libx264 -y out1.mp4 \
-map "[vout2]" -c:v libx264 -y out2.mp4 \
-print_graphs_file /tmp/graph.html \
-print_graphs_format mermaidhtml
用浏览器打开 /tmp/graph.html,可以看到完整的 filtergraph 流程图,直观展示数据从输入文件分流、分别缩放、最终输出的完整路径。
示例 3:直接打印到 stderr
bash
ffmpeg -i input.mp4 -vf "hqdn3d=4:3:6:4.5" -c:v libx264 -y output.mp4 -print_graphs
filtergraph 信息会随其他日志信息一起输出到 stderr。
示例 4:输出到 stdout
bash
ffmpeg -i input.mp4 -vf "scale=320:240" -c:v libx264 -y output.mp4 \
-print_graphs_file - -print_graphs_format json
使用 - 作为文件名表示输出到 stdout。
内部工作流程
┌──────────────────────────────────────────────────────────────┐
│ ffmpeg 启动 │
└──────────────────────┬───────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ 解析命令行选项,记录 print_graphs / print_graphs_file 等值 │
│ (ffmpeg_opt.c:80-82) │
└──────────────────────┬───────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ 配置阶段:每个 filtergraph 在各自线程中完成配置 │
│ │
│ if (print_graphs || print_graphs_file) │
│ print_filtergraph(fg, fgt.graph); │
│ → 将单个 graph 信息序列化到 fg->graph_print_buf │
│ (ffmpeg_filter.c:3417-3418) │
└──────────────────────┬───────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ 退出清理阶段:主线程汇总所有数据 │
│ │
│ if (print_graphs || print_graphs_file) │
│ print_filtergraphs(graphs, ..., ifiles, ..., ofiles, ...)│
│ → 合并所有 fg->graph_print_buf │
│ → 补充输入/输出文件流、解码器、编码器、流链接信息 │
│ → 根据格式(json/mermaid/...)输出到文件或 stderr │
│ → 释放资源管理器 (ff_resman_uninit) │
│ (ffmpeg.c:316-317) │
└──────────────────────────────────────────────────────────────┘
实现细节
格式化系统
打印系统基于 FFmpeg 的 AVTextFormat 框架(位于 fftools/textformat/),这是一个通用的结构化文本输出框架,支持多种输出格式。
格式选择逻辑在 init_graphprint() 中:
c
const char *w_name = print_graphs_format ? print_graphs_format : "json";
text_formatter = avtext_get_formatter_by_name(w_name);
Mermaid 图表支持
当选择 mermaid 或 mermaidhtml 格式时:
- 从资源管理器加载 CSS 样式和 HTML 模板(
graphprint.c:924-931) - 启用图表模式(
is_diagram = 1),自动包含更多可选字段 - 跳过 buffer filter(如
abuffer/buffer),使图表更简洁 - 生成 Mermaid 语法描述的流程图
线程安全
由于每个 filtergraph 在独立线程中运行,print_filtergraph() 使用原子计数器 atomic_int prefix_num(graphprint.c:159)为每个 graph 分配唯一的前缀编号,确保 ID 不冲突。
适用场景
- 调试复杂 filtergraph:查看 filter 链的实际配置和媒体参数
- 验证 filter 连接:确认 filter 之间的连接关系是否正确
- 分析性能瓶颈:查看每个 filter 的输入/输出参数,了解转换开销
- 文档记录:将 filtergraph 拓扑保存为文件,用于记录或分享
- 可视化展示:使用 Mermaid HTML 格式生成交互式流程图