这个系列文章我们来介绍一位海外工程师如何探索安卓音视频基础技术,对于想要开始学习音视频技术的朋友,这些文章是份不错的入门资料,本篇介绍滤镜使用与处理。
——来自公众号“关键帧Keyframe”的分享
1、滤镜架构总览
AVFilterGraph
├─ AVFilterContext① → buffer (源)
├─ AVFilterContext② → scale/overlay/...
└─ AVFilterContext③ → buffersink (汇)
AVFilter:类型(如scale)AVFilterContext:实例(含参数)AVBufferRef:零拷贝帧传递
2、核心 API 速查
| 操作 | 函数 |
|---|---|
| 创建图 | avfilter_graph_alloc() |
| 实例化滤镜 | avfilter_graph_create_filter() |
| 字符串解析 | avfilter_graph_parse_ptr() |
| 验证连接 | avfilter_graph_config() |
| 送帧 | av_buffersrc_add_frame_flags() |
| 取帧 | av_buffersink_get_frame() |
| 释放 | avfilter_graph_free() |
3、三阶段工作流程
3.1、 阶段一:构建 FilterGraph
AVFilterGraph *graph = avfilter_graph_alloc();
/* 1. 源 buffer */
AVFilterContext *src_ctx;
snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d",
width, height, pix_fmt, time_base.num, time_base.den);
avfilter_graph_create_filter(&src_ctx, avfilter_get_by_name("buffer"),
"in_buffer", args, NULL, graph);
/* 2. 汇 buffersink */
AVFilterContext *sink_ctx;
avfilter_graph_create_filter(&sink_ctx, avfilter_get_by_name("buffersink"),
"out_buffersink", NULL, NULL, graph);
/* 3. 解析中间滤镜链 */
constchar *graph_desc = "[in_buffer]scale=iw/2:-1[scaled];[scaled]overlay=10:10[out_buffersink]";
AVFilterInOut *inputs = avfilter_inout_alloc();
inputs->name = av_strdup("out_buffersink");
inputs->filter_ctx = sink_ctx;
AVFilterInOut *outputs = avfilter_inout_alloc();
outputs->name = av_strdup("in_buffer");
outputs->filter_ctx = src_ctx;
avfilter_graph_parse_ptr(graph, graph_desc, &inputs, &outputs, NULL);
avfilter_graph_config(graph, NULL); // 验证连通性
3.2、 阶段二:数据泵送
/* 输入:解码帧 → filter */
av_buffersrc_add_frame_flags(src_ctx, decoded_frame, AV_BUFFERSRC_FLAG_KEEP_REF);
/* 输出:拉取已处理帧 */
AVFrame *filt_frame = av_frame_alloc();
int ret = av_buffersink_get_frame(sink_ctx, filt_frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
// 需要更多输入或已结束
}
3.3、 阶段三:资源清理
av_frame_free(&filt_frame);
avfilter_graph_free(&graph); // 递归释放所有节点
4、命令行滤镜速用
4.1、描述格式
[input_stream]filter=params[label];[label]next_filter[out]
4.2、常用滤镜示例
| 效果 | 命令 |
|---|---|
| 文字水印 | -vf "drawtext=fontfile=/System/Fonts/Helvetica.ttc:text='Hello':fontcolor=yellow:fontsize=48:x=20:y=20" |
| 图片水印 | -filter_complex "[1:v]scale=176:144[logo];[0:v][logo]overlay=x=0:y=0" |
| 画中画 | -filter_complex "[1:v]scale=480x320[pip];[0:v][pip]overlay=W-w-10:H-h-10" |
| 色度键 | -filter_complex "[0:v]chromakey=0x00FF00:0.1:0.2[ck];[ck]overlay=10:10" |
| 倍速 | 视频:-vf setpts=PTS/2 音频:-af atempo=2.0 |
| 测试图 | -f lavfi -i testsrc=duration=5:size=qcif:rate=25 |
5、高级组合案例
5.1、四宫格拼接
ffmpeg -i p1.mp4 -i p2.mp4 -i p3.mp4 -i p4.mp4 -filter_complex "
nullsrc=size=1280x720[bg];
[0:v]scale=640x360,setpts=PTS-STARTPTS[p1];
[1:v]scale=640x360,setpts=PTS-STARTPTS[p2];
[2:v]scale=640x360,setpts=PTS-PTS_STARTPTS[p3];
[3:v]scale=640x360,setpts=PTS-STARTPTS[p4];
[bg][p1]overlay=shortest=1[x];
[x][p2]overlay=shortest=1:x=640[y];
[y][p3]overlay=shortest=1:y=360[z];
[z][p4]overlay=shortest=1:x=640:y=360
" -c:v libx264 -preset fast out.mp4
5.2、音频频谱可视化
ffmpeg -i music.mp3 -filter_complex \
"[0:a]showspectrum=s=1280x480:mode=combined:slide=scroll:color=intensity[spectrum];
[spectrum]format=yuv420p[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy spectrum.mp4
6、音频滤镜精选
| 功能 | Filter | 示例 |
|---|---|---|
| 音量调整 | volume | -af volume=0.8 |
| 通道合并 | amerge | -af amerge=inputs=2 |
| 降噪 | arnndn | -af arnndn=model=rnnoise-2018-09-01.rnnn |
| 变速不变调 | atempo | -af atempo=1.25 |
| 静音检测 | silencedetect | -af silencedetect=noise=-30dB:d=0.5 |
7、性能与最佳实践
- 零拷贝:
AV_BUFFERSRC_FLAG_KEEP_REF避免帧复制 - 格式减少转换:
尽量在 graph 内保持相同像素格式与采样率 - 线程安全:
每个线程独立 graph,不共享上下文 - 错误处理:
检查EAGAIN/AVERROR_EOF控制流 - 验证连通性:
调用avfilter_graph_config()捕获连接错误
8、错误码速查
| 返回值 | 含义 | 处理 |
|---|---|---|
0 | 成功 | 继续 |
EAGAIN | 需更多输入 | 继续送帧 |
AVERROR_EOF | 无更多输出 | 发送 NULL 刷新 |
AVERROR(EINVAL) | 参数非法 | 检查 graph 描述 |
9、一行命令记忆
ffmpeg -i in.mp4 -filter_complex \
"[0:v]scale=iw/2:-1,setsar=1[scaled];[scaled]drawtext=text='Hi':fontcolor=white:fontsize=48:x=(w-text_w)/2:y=(h-text_h)/2" \
-c:v libx264 -preset fast -c:a copy out.mp4
效果:缩放一半 + 居中文字,全程 GPU 零拷贝 可在 60 fps 下实时完成。
10、后续拓展
- 实时滤镜链:结合 硬件加速 实现 直播美颜/贴纸
- 自定义滤镜:编写
avfilter插件接入 AI 分割/超分 - 动态图合成:将 Audio Spectrum、Face Detection 实时叠加
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。