4. FFmpeg 滤镜系统:视频滤镜、音频滤镜、滤镜图构建、复杂滤镜链
滤镜系统,说白了就是FFmpeg的灵魂所在。我刚开始接触FFmpeg时,觉得它就是个转码工具。后来才发现,真正让它强大的,是这套灵活到变态的滤镜机制。
你想想看,视频处理无非就是:裁剪、缩放、加水印、调色、变速、去噪……这些操作,在FFmpeg里全都可以通过滤镜组合实现。而且,你可以把多个滤镜串起来,形成一个处理流水线。这就是所谓的滤镜图(Filter Graph)。
4.1 视频滤镜:从简单到复杂
视频滤镜,就是对每一帧画面做处理。我习惯把它们分成三类:几何变换类、色彩调整类、特效类。
4.1.1 常用视频滤镜一览
| 滤镜名称 | 功能 | 典型参数 |
|---|---|---|
| scale | 缩放视频尺寸 | width:height,如 1280:720 |
| crop | 裁剪画面区域 | out_w:out_h:x:y |
| rotate | 旋转画面 | 角度(弧度),如 PI/6 |
| hflip/vflip | 水平/垂直翻转 | 无参数 |
| drawtext | 叠加文字水印 | fontfile, text, x, y |
| fps | 改变帧率 | 目标帧率,如 30 |
举个例子,把视频缩放到720p,同时加上文字水印:
ffmpeg -i input.mp4 -vf "scale=1280:720,drawtext=fontfile=/usr/share/fonts/truetype/arial.ttf:text='Hello World':x=10:y=10" output.mp4
这里有个坑,我踩过好几次。drawtext的fontfile路径,在Windows和Linux下写法完全不同。Windows要用双反斜杠或者正斜杠,Linux直接写路径就行。我曾经在Windows上折腾了半小时,就为了这个路径问题。
4.1.2 视频滤镜的链式调用
多个滤镜用逗号分隔,就是链式调用。数据从左到右依次流过每个滤镜。比如:
ffmpeg -i input.mp4 -vf "crop=640:480:0:0,scale=320:240,hflip" output.mp4
这个命令做了三件事:先裁剪左上角640x480区域,再缩放到320x240,最后水平翻转。顺序很重要,你想想看,如果先翻转再裁剪,结果完全不一样。
4.2 音频滤镜:不只是调音量
很多人觉得音频滤镜就是调调音量、加个回声。其实音频滤镜能做的事情多着呢。我做过一个项目,需要把直播中的环境噪音去掉,用的就是音频滤镜组合。
4.2.1 常用音频滤镜
| 滤镜名称 | 功能 | 典型参数 |
|---|---|---|
| volume | 调整音量 | 倍数或dB值,如 2.0 或 6dB |
| atempo | 改变播放速度 | 0.5~2.0,如 1.5 |
| aecho | 添加回声效果 | 延迟时间:衰减系数 |
| anull | 静音处理 | 无参数 |
| lowpass/highpass | 低通/高通滤波 | 频率,如 3000Hz |
音频滤镜的调用方式和视频类似,只是参数名从 -vf 变成了 -af:
ffmpeg -i input.mp3 -af "volume=1.5,atempo=1.2,aecho=0.8:0.9:1000:0.3" output.mp3
这个命令把音量放大1.5倍,速度加快到1.2倍,再加个回声效果。嗯,这里要注意,atempo的取值范围是0.5到2.0,超出这个范围会报错。我当初做变速处理时,想加速到3倍,结果直接崩了。后来才知道,需要串联两个atempo滤镜才能实现更大范围的变速。
4.3 滤镜图(Filter Graph)构建
单个滤镜链只能处理一路输入。但实际项目中,经常需要处理多路视频,或者把视频和音频分开处理再合并。这时候就需要滤镜图了。
滤镜图,说白了就是多个滤镜链的组合。用分号分隔不同的链,用方括号标记输入输出标签。
4.3.1 滤镜图的基本语法
[输入标签] 滤镜链 [输出标签]
看个例子,把视频和音频分开处理:
ffmpeg -i input.mp4 -filter_complex "[0:v]scale=640:480[v_out];[0:a]volume=2.0[a_out]" -map "[v_out]" -map "[a_out]" output.mp4
这里 [0:v] 表示第一个输入文件的视频流,[0:a] 表示第一个输入文件的音频流。处理完后,分别输出到 [v_out] 和 [a_out],再用 -map 映射到输出文件。
核心要点:滤镜图用 -filter_complex 参数,而不是 -vf 或 -af。这是很多人容易搞混的地方。
4.3.2 多路输入的处理
我做过一个视频会议项目,需要把两个摄像头画面拼在一起。用overlay滤镜就能实现:
ffmpeg -i main.mp4 -i logo.png -filter_complex "[0:v][1:v]overlay=10:10" output.mp4
这个命令把logo.png叠加到main.mp4的左上角(坐标10,10)。overlay滤镜接受两个输入,第一个是背景,第二个是前景。
更复杂的场景,比如画中画效果:
ffmpeg -i big.mp4 -i small.mp4 -filter_complex "[0:v]scale=1280:720[bg];[1:v]scale=320:240[fg];[bg][fg]overlay=900:500" output.mp4
先把大视频缩放到720p作为背景,小视频缩放到240p作为前景,然后叠加到右下角。这种多步处理,用滤镜图就特别清晰。
4.4 复杂滤镜链实战
理论知识讲完了,咱们来点实战。我挑几个典型的复杂场景,带你走一遍。
4.4.1 场景一:视频加水印+调色+变速
ffmpeg -i input.mp4 -filter_complex "[0:v]scale=1920:1080,drawtext=fontfile=font.ttf:text='Watermark':x=100:y=100:fontsize=24:fontcolor=white,colorbalance=rs=0.1:gs=0.05:bs=-0.05,setpts=0.8*PTS[v_out];[0:a]atempo=1.25[a_out]" -map "[v_out]" -map "[a_out]" output.mp4
这个命令做了四件事:缩放、加水印、调色、变速。注意视频变速用setpts,音频变速用atempo,两者要匹配。我刚开始做时,只改了视频没改音频,结果画面和声音对不上,那叫一个尴尬。
4.4.2 场景二:视频拼接+过渡效果
视频拼接用concat滤镜。但要注意,concat要求所有输入视频的分辨率、帧率、编码格式完全一致。我曾经在这个坑里摔过好几次。
ffmpeg -i part1.mp4 -i part2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1" output.mp4
n=2表示两段视频,v=1表示输出视频流,a=1表示输出音频流。如果视频参数不一致,先统一处理:
ffmpeg -i part1.mp4 -i part2.mp4 -filter_complex "[0:v]scale=1280:720,fps=30[v0];[1:v]scale=1280:720,fps=30[v1];[v0][0:a][v1][1:a]concat=n=2:v=1:a=1" output.mp4
小技巧:用ffprobe查看视频信息,确保参数一致。命令:ffprobe -v error -show_entries stream=width,height,r_frame_rate input.mp4
4.4.3 场景三:画中画+音频混合
这个场景在直播中很常见,比如主播画面+游戏画面:
ffmpeg -i host.mp4 -i game.mp4 -filter_complex "[0:v]scale=320:240[host_scaled];[1:v]scale=1280:720[game_scaled];[game_scaled][host_scaled]overlay=10:10[final_v];[0:a][1:a]amix=inputs=2:duration=first[final_a]" -map "[final_v]" -map "[final_a]" output.mp4
这里用了amix滤镜混合两路音频。duration=first表示以第一个音频的时长为准。如果你想两个音频同时播放完,可以用duration=longest。
4.5 避坑指南
做滤镜开发这几年,我踩过的坑能写一本书。挑几个最常见的分享给你:
- 滤镜顺序搞反:先缩放再裁剪,和先裁剪再缩放,结果完全不同。画个流程图再动手,能省很多时间。
- 标签名写错:方括号里的标签名必须完全匹配,大小写敏感。我经常因为 [v_out] 和 [V_out] 这种低级错误浪费半小时。
- 内存溢出:处理4K视频时,滤镜链太长会导致内存暴涨。建议分段处理,或者用硬件加速。
- 音频视频不同步:变速处理时,setpts和atempo的系数要对应。比如视频加速到0.8倍,音频就要加速到1.25倍(1/0.8)。
重要提醒:滤镜图调试时,先用短片段测试。我曾经直接拿2小时的视频跑复杂滤镜,跑了半小时发现参数错了,那种感觉……嗯,你懂的。
滤镜系统就讲到这里。说白了,它就是FFmpeg最核心的武器。掌握了滤镜图,你就能随心所欲地处理音视频。下一章,咱们聊聊硬件加速,那又是另一个世界了。