FFmpeg 多媒体处理教程 / 滤镜系统
滤镜系统
概述
FFmpeg 的滤镜系统(Filter System)是其最强大的功能之一,允许对音视频进行各种处理和转换。滤镜通过滤镜图(Filtergraph)连接,支持复杂的处理流程。
滤镜基础
滤镜语法
[input]filter1=param1:param2,filter2=param1,filter3[output]
基本概念
| 概念 | 说明 |
|---|---|
| 滤镜(Filter) | 处理单元,对音视频进行转换 |
| 滤镜图(Filtergraph) | 滤镜的连接图 |
| 滤镜链(Filterchain) | 用逗号分隔的滤镜序列 |
| 滤镜图链接(Filtergraph link) | 用分号分隔的滤镜链 |
| 输入(Input) | 滤镜的输入流 |
| 输出(Output) | 滤镜的输出流 |
滤镜选项
# 使用 -vf 指定视频滤镜
ffmpeg -i input.mp4 -vf "scale=1280:720" output.mp4
# 使用 -af 指定音频滤镜
ffmpeg -i input.mp4 -af "volume=2.0" output.mp4
# 使用 -filter_complex 指定复杂滤镜图
ffmpeg -i input.mp4 -filter_complex "[0:v]scale=1280:720[v]" -map "[v]" output.mp4
视频滤镜
几何变换滤镜
scale(缩放)
# 基本缩放
ffmpeg -i input.mp4 -vf "scale=1280:720" output.mp4
# 保持宽高比
ffmpeg -i input.mp4 -vf "scale=1280:-1" output.mp4
# 使用表达式
ffmpeg -i input.mp4 -vf "scale=iw/2:ih/2" output.mp4
# 指定算法
ffmpeg -i input.mp4 -vf "scale=1280:720:flags=lanczos" output.mp4
crop(裁剪)
# 基本裁剪
ffmpeg -i input.mp4 -vf "crop=640:480:0:0" output.mp4
# 裁剪中心区域
ffmpeg -i input.mp4 -vf "crop=in_w-100:in_h-100" output.mp4
# 保持宽高比裁剪
ffmpeg -i input.mp4 -vf "crop=in_w:in_w*9/16" output.mp4
rotate(旋转)
# 旋转 45 度
ffmpeg -i input.mp4 -vf "rotate=PI/4" output.mp4
# 旋转 90 度
ffmpeg -i input.mp4 -vf "rotate=PI/2" output.mp4
# 填充黑色背景
ffmpeg -i input.mp4 -vf "rotate=PI/4:fillcolor=black" output.mp4
transpose(转置)
# 顺时针旋转 90 度
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4
# 逆时针旋转 90 度
ffmpeg -i input.mp4 -vf "transpose=2" output.mp4
# 旋转 180 度
ffmpeg -i input.mp4 -vf "transpose=1,transpose=1" output.mp4
hflip/vflip(翻转)
# 水平翻转
ffmpeg -i input.mp4 -vf "hflip" output.mp4
# 垂直翻转
ffmpeg -i input.mp4 -vf "vflip" output.mp4
pad(填充)
# 添加黑边
ffmpeg -i input.mp4 -vf "pad=1920:1080:(ow-iw)/2:(oh-ih)/2" output.mp4
# 指定填充颜色
ffmpeg -i input.mp4 -vf "pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=blue" output.mp4
颜色调整滤镜
eq(均衡器)
# 调整亮度
ffmpeg -i input.mp4 -vf "eq=brightness=0.1" output.mp4
# 调整对比度
ffmpeg -i input.mp4 -vf "eq=contrast=1.2" output.mp4
# 调整饱和度
ffmpeg -i input.mp4 -vf "eq=saturation=1.5" output.mp4
# 调整伽马
ffmpeg -i input.mp4 -vf "eq=gamma=1.2" output.mp4
# 组合调整
ffmpeg -i input.mp4 -vf "eq=brightness=0.05:contrast=1.1:saturation=1.2:gamma=1.1" output.mp4
hue(色调)
# 调整色调
ffmpeg -i input.mp4 -vf "hue=h=30" output.mp4
# 调整饱和度
ffmpeg -i input.mp4 -vf "hue=s=0.5" output.mp4
# 调整亮度
ffmpeg -i input.mp4 -vf "hue=b=0.1" output.mp4
colorbalance(色彩平衡)
# 调整阴影色调
ffmpeg -i input.mp4 -vf "colorbalance=rs=0.1:gs=-0.1:bs=-0.1" output.mp4
# 调整中间色调
ffmpeg -i input.mp4 -vf "colorbalance=rm=0.1:gm=-0.1:bm=-0.1" output.mp4
# 调整高光色调
ffmpeg -i input.mp4 -vf "colorbalance=rh=0.1:gh=-0.1:bh=-0.1" output.mp4
curves(曲线)
# 轻度提亮
ffmpeg -i input.mp4 -vf "curves=lighter" output.mp4
# 轻度变暗
ffmpeg -i input.mp4 -vf "curves=darker" output.mp4
# 增强对比度
ffmpeg -i input.mp4 -vf "curves=stronger" output.mp4
# 自定义曲线
ffmpeg -i input.mp4 -vf "curves=r='0/0 0.5/0.6 1/1'" output.mp4
colorchannelmixer(颜色通道混合)
# 转换为灰度图
ffmpeg -i input.mp4 -vf "colorchannelmixer=rr=0.3:gg=0.4:bb=0.3" output.mp4
# 增强红色
ffmpeg -i input.mp4 -vf "colorchannelmixer=rr=1.5" output.mp4
# 色调偏移
ffmpeg -i input.mp4 -vf "colorchannelmixer=rr=0.5:rg=0.5:rb=0:gr=0:gg=1:gb=0:br=0:bg=0:bb=1" output.mp4
模糊和锐化滤镜
boxblur(盒式模糊)
# 基本模糊
ffmpeg -i input.mp4 -vf "boxblur=5:5" output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "boxblur=luma_radius=5:luma_power=2:chroma_radius=3:chroma_power=1" output.mp4
gblur(高斯模糊)
# 基本高斯模糊
ffmpeg -i input.mp4 -vf "gblur=sigma=5" output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "gblur=sigma=5:steps=3" output.mp4
unsharp(锐化)
# 基本锐化
ffmpeg -i input.mp4 -vf "unsharp=5:5:1.0:5:5:0.0" output.mp4
# 轻度锐化
ffmpeg -i input.mp4 -vf "unsharp=3:3:0.5" output.mp4
# 强锐化
ffmpeg -i input.mp4 -vf "unsharp=5:5:2.0" output.mp4
去噪滤镜
hqdn3d
# 基本去噪
ffmpeg -i input.mp4 -vf "hqdn3d" output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "hqdn3d=4:3:6:4.5" output.mp4
nlmeans
# 基本去噪
ffmpeg -i input.mp4 -vf "nlmeans=s=7" output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "nlmeans=s=10:p=7:r=15" output.mp4
文字和绘制滤镜
drawtext(文字绘制)
# 基本文字
ffmpeg -i input.mp4 -vf "drawtext=text='Hello World':x=10:y=10:fontsize=24:fontcolor=white" output.mp4
# 带背景的文字
ffmpeg -i input.mp4 -vf "drawtext=text='Hello':x=10:y=10:fontsize=24:fontcolor=white:box=1:[email protected]" output.mp4
# 时间戳文字
ffmpeg -i input.mp4 -vf "drawtext=text='%{localtime\:%Y-%m-%d %H\\\:%M\\\:%S}':x=10:y=10:fontsize=24:fontcolor=white" output.mp4
# 帧计数
ffmpeg -i input.mp4 -vf "drawtext=text='%{frame_num}':x=10:y=10:fontsize=24:fontcolor=white" output.mp4
# 动态位置
ffmpeg -i input.mp4 -vf "drawtext=text='Scroll':x='mod(n, width)':y=10:fontsize=24:fontcolor=white" output.mp4
drawbox(绘制矩形)
# 基本矩形
ffmpeg -i input.mp4 -vf "drawbox=x=10:y=10:w=200:h=100:[email protected]:t=fill" output.mp4
# 边框矩形
ffmpeg -i input.mp4 -vf "drawbox=x=10:y=10:w=200:h=100:color=red:t=3" output.mp4
drawgrid(绘制网格)
# 基本网格
ffmpeg -i input.mp4 -vf "drawgrid=w=100:h=100:t=1:[email protected]" output.mp4
特效滤镜
fade(淡入淡出)
# 淡入
ffmpeg -i input.mp4 -vf "fade=t=in:st=0:d=2" output.mp4
# 淡出
ffmpeg -i input.mp4 -vf "fade=t=out:st=58:d=2" output.mp4
# 组合
ffmpeg -i input.mp4 -vf "fade=t=in:st=0:d=2,fade=t=out:st=58:d=2" output.mp4
overlay(叠加)
# 右下角叠加
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=320:240[pip];[0:v][pip]overlay=W-w-10:H-h-10" output.mp4
# 居中叠加
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[0:v][1:v]overlay=(W-w)/2:(H-h)/2" output.mp4
# 动态位置
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[0:v][1:v]overlay='mod(n, W)':10" output.mp4
concat(拼接)
# 视频拼接
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][1:v]concat=n=2:v=1:a=0" output.mp4
# 带音频拼接
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4
稳定滤镜
vidstab(视频稳定)
# 第一遍:分析
ffmpeg -i input.mp4 -vf "vidstabdetect=shakiness=5:accuracy=15:result=transforms.trf" -f null -
# 第二遍:应用
ffmpeg -i input.mp4 -vf "vidstabtransform=input=transforms.trf:smoothing=30:zoom=5" output.mp4
deshake
# 基本稳定
ffmpeg -i input.mp4 -vf "deshake" output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "deshake=x=-1:y=-1:w=-1:h=-1:rx=16:ry=16" output.mp4
音频滤镜
音量控制滤镜
volume
# 音量加倍
ffmpeg -i input.mp4 -af "volume=2.0" output.mp4
# 使用分贝
ffmpeg -i input.mp4 -af "volume=10dB" output.mp4
# 动态音量
ffmpeg -i input.mp4 -af "volume='if(lt(t,10),1,0.5)'" output.mp4
loudnorm
# 响度归一化
ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11" output.mp4
淡入淡出滤镜
afade
# 淡入
ffmpeg -i input.mp4 -af "afade=t=in:st=0:d=3" output.mp4
# 淡出
ffmpeg -i input.mp4 -af "afade=t=out:st=57:d=3" output.mp4
# 使用曲线
ffmpeg -i input.mp4 -af "afade=t=in:st=0:d=3:curve=exp" output.mp4
均衡器滤镜
equalizer
# 调整特定频率
ffmpeg -i input.mp4 -af "equalizer=f=1000:t=q:w=2:g=5" output.mp4
# 多频段均衡
ffmpeg -i input.mp4 -af "equalizer=f=100:t=q:w=1:g=3,equalizer=f=1000:t=q:w=1:g=2,equalizer=f=10000:t=q:w=1:g=1" output.mp4
bass/treble
# 低音增强
ffmpeg -i input.mp4 -af "bass=g=10" output.mp4
# 高音增强
ffmpeg -i input.mp4 -af "treble=g=10" output.mp4
滤波器滤镜
highpass/lowpass
# 高通滤波
ffmpeg -i input.mp4 -af "highpass=f=80" output.mp4
# 低通滤波
ffmpeg -i input.mp4 -af "lowpass=f=8000" output.mp4
# 带通滤波
ffmpeg -i input.mp4 -af "highpass=f=200,lowpass=f=3000" output.mp4
bandpass/bandreject
# 带通滤波
ffmpeg -i input.mp4 -af "bandpass=f=1000:w=500" output.mp4
# 带阻滤波
ffmpeg -i input.mp4 -af "bandreject=f=1000:w=100" output.mp4
降噪滤镜
afftdn
# 基本降噪
ffmpeg -i input.mp4 -af "afftdn=nf=-25" output.mp4
# 自适应降噪
ffmpeg -i input.mp4 -af "afftdn=nf=-25:nt=w" output.mp4
anlmdn
# 基本降噪
ffmpeg -i input.mp4 -af "anlmdn=s=7" output.mp4
混音滤镜
amix
# 混合两个音频
ffmpeg -i audio1.mp3 -i audio2.mp3 -filter_complex "[0:a][1:a]amix=inputs=2:duration=longest" output.mp3
# 设置权重
ffmpeg -i audio1.mp3 -i audio2.mp3 -filter_complex "[0:a][1:a]amix=inputs=2:weights=1 0.5" output.mp3
速度调整滤镜
atempo
# 加速
ffmpeg -i input.mp4 -af "atempo=2.0" output.mp4
# 减速
ffmpeg -i input.mp4 -af "atempo=0.5" output.mp4
# 多级调整
ffmpeg -i input.mp4 -af "atempo=2.0,atempo=2.0" output.mp4 # 4倍速
特效滤镜
aecho(回声)
# 基本回声
ffmpeg -i input.mp4 -af "aecho=0.8:0.88:60:0.4" output.mp4
# 多重回声
ffmpeg -i input.mp4 -af "aecho=0.8:0.9:1000|1500|2000:0.3|0.2|0.1" output.mp4
chorus(合唱)
# 基本合唱
ffmpeg -i input.mp4 -af "chorus=0.5:0.9:50|60|40:0.4|0.32|0.3:0.25|0.4|0.3:2|2.3|1.3" output.mp4
vibrato(颤音)
# 基本颤音
ffmpeg -i input.mp4 -af "vibrato=f=5:d=0.2" output.mp4
复合滤镜
滤镜图语法
# 基本滤镜图
ffmpeg -i input.mp4 -filter_complex "[0:v]scale=1280:720[v]" -map "[v]" output.mp4
# 多输入滤镜图
ffmpeg -i video.mp4 -i watermark.png -filter_complex "[0:v][1:v]overlay=10:10[v]" -map "[v]" output.mp4
# 多输出滤镜图
ffmpeg -i input.mp4 -filter_complex "[0:v]split=2[v1][v2]" -map "[v1]" output1.mp4 -map "[v2]" output2.mp4
滤镜链
# 使用逗号连接多个滤镜
ffmpeg -i input.mp4 -vf "scale=1280:720,hflip,volume=2.0" output.mp4
# 使用分号连接多个滤镜链
ffmpeg -i input.mp4 -filter_complex "[0:v]scale=1280:720[v];[0:a]volume=2.0[a]" -map "[v]" -map "[a]" output.mp4
常用复合操作
画中画
# 基本画中画
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex \
"[1:v]scale=320:240[pip]; \
[0:v][pip]overlay=W-w-10:H-h-10[outv]" \
-map "[outv]" -map 0:a output.mp4
# 带边框的画中画
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex \
"[1:v]scale=320:240,pad=324:244:2:2:black[pip]; \
[0:v][pip]overlay=W-w-10:H-h-10[outv]" \
-map "[outv]" -map 0:a output.mp4
画中画动画
# 移动的画中画
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex \
"[1:v]scale=320:240[pip]; \
[0:v][pip]overlay='mod(n*2, W)':10[outv]" \
-map "[outv]" -map 0:a output.mp4
视频拼接
# 水平拼接
ffmpeg -i left.mp4 -i right.mp4 -filter_complex \
"[0:v][1:v]hstack[outv]" \
-map "[outv]" output.mp4
# 垂直拼接
ffmpeg -i top.mp4 -i bottom.mp4 -filter_complex \
"[0:v][1:v]vstack[outv]" \
-map "[outv]" output.mp4
# 2x2 网格
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 -filter_complex \
"[0:v][1:v]hstack[top]; \
[2:v][3:v]hstack[bottom]; \
[top][bottom]vstack[outv]" \
-map "[outv]" output.mp4
视频混合
# 叠加混合
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
"[0:v][1:v]blend=all_mode=overlay:all_opacity=0.5[outv]" \
-map "[outv]" output.mp4
# 变暗混合
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
"[0:v][1:v]blend=all_mode=darken[outv]" \
-map "[outv]" output.mp4
音频混合
# 基本混合
ffmpeg -i audio1.mp3 -i audio2.mp3 -filter_complex \
"[0:a][1:a]amix=inputs=2:duration=longest[outa]" \
-map "[outa]" output.mp3
# 带音量调整的混合
ffmpeg -i music.mp3 -i voice.mp3 -filter_complex \
"[0:a]volume=0.3[music]; \
[music][1:a]amix=inputs=2:duration=longest[outa]" \
-map "[outa]" output.mp3
滤镜图高级用法
条件滤镜
# 根据时间应用滤镜
ffmpeg -i input.mp4 -vf "drawtext=text='Intro':x=10:y=10:fontsize=24:fontcolor=white:enable='lt(t,5)'" output.mp4
# 根据帧号应用滤镜
ffmpeg -i input.mp4 -vf "drawtext=text='%{frame_num}':x=10:y=10:fontsize=24:fontcolor=white:enable='lt(n,100)'" output.mp4
帧选择
# 选择特定帧
ffmpeg -i input.mp4 -vf "select='eq(n,0)+eq(n,10)+eq(n,20)'" -vsync vfr output.mp4
# 选择关键帧
ffmpeg -i input.mp4 -vf "select='eq(pict_type,I)'" -vsync vfr output.mp4
# 每 10 帧选择 1 帧
ffmpeg -i input.mp4 -vf "select='not(mod(n,10))'" -vsync vfr output.mp4
帧率处理
# 改变帧率
ffmpeg -i input.mp4 -vf "fps=30" output.mp4
# 去除重复帧
ffmpeg -i input.mp4 -vf "fps=fps=source_fps:round=near" output.mp4
# 插帧
ffmpeg -i input.mp4 -vf "minterpolate=fps=60:mi_mode=mci" output.mp4
自定义滤镜
使用滤镜脚本
# 创建滤镜脚本文件
cat > filter_script.txt << 'EOF'
[0:v]scale=1280:720,hflip[v];
[0:a]volume=2.0[a]
EOF
# 使用滤镜脚本
ffmpeg -i input.mp4 -filter_complex_script filter_script.txt -map "[v]" -map "[a]" output.mp4
滤镜图复用
# 定义常用滤镜图
FILTER_GRAPH="[0:v]scale=1280:720:flags=lanczos,eq=brightness=0.05:contrast=1.1[v]"
# 使用
ffmpeg -i input.mp4 -filter_complex "$FILTER_GRAPH" -map "[v]" output.mp4
滤镜性能优化
滤镜线程
# 设置滤镜线程数
ffmpeg -i input.mp4 -filter_complex_threads 4 -vf "scale=1280:720" output.mp4
滤镜格式
# 指定中间格式(提高性能)
ffmpeg -i input.mp4 -vf "format=yuv420p,scale=1280:720" output.mp4
滤镜链优化
# 将缩放放在前面(减少后续处理数据量)
ffmpeg -i input.mp4 -vf "scale=640:360,hqdn3d,eq=brightness=0.05" output.mp4
# 避免不必要的格式转换
ffmpeg -i input.mp4 -vf "scale=1280:720:flags=lanczos" -c:v libx264 output.mp4
常用滤镜组合
视频增强组合
# 轻度增强
ffmpeg -i input.mp4 -vf "unsharp=3:3:0.5,eq=brightness=0.03:contrast=1.05:saturation=1.1" output.mp4
# 强增强
ffmpeg -i input.mp4 -vf "unsharp=5:5:1.0,eq=brightness=0.05:contrast=1.2:saturation=1.3,hqdn3d" output.mp4
电影效果组合
# 胶片效果
ffmpeg -i input.mp4 -vf "curves=vintage,unsharp=3:3:0.5,eq=contrast=1.1:saturation=0.9" output.mp4
# 黑白效果
ffmpeg -i input.mp4 -vf "colorchannelmixer=rr=0.3:rg=0.4:rb=0.3:gr=0.3:gg=0.4:gb=0.3:br=0.3:bg=0.4:bb=0.3" output.mp4
社交媒体组合
# Instagram 风格
ffmpeg -i input.mp4 -vf "scale=1080:1080:force_original_aspect_ratio=decrease,pad=1080:1080:(ow-iw)/2:(oh-ih)/2,curves=vintage" output.mp4
# TikTok 风格
ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" output.mp4
注意事项
- 性能影响:复杂滤镜链会显著增加处理时间
- 内存占用:高分辨率视频处理需要大量内存
- 滤镜顺序:滤镜按顺序执行,顺序不同结果可能不同
- 格式兼容:某些滤镜对输入格式有要求
- 质量损失:多次处理会导致质量累积损失
业务场景
场景 1:视频水印批量添加
#!/bin/bash
# batch_watermark.sh
INPUT_DIR=$1
WATERMARK=$2
OUTPUT_DIR=${3:-output}
mkdir -p "$OUTPUT_DIR"
for file in "$INPUT_DIR"/*.mp4; do
filename=$(basename "$file")
output="$OUTPUT_DIR/$filename"
ffmpeg -y -i "$file" -i "$WATERMARK" -filter_complex \
"[1:v]scale=100:-1[wm]; \
[0:v][wm]overlay=W-w-10:H-h-10[v]" \
-map "[v]" -map 0:a -c:v libx264 -crf 23 -c:a copy "$output"
done
场景 2:视频片头片尾添加
#!/bin/bash
# add_intro_outro.sh
INPUT=$1
INTRO=$2
OUTRO=$3
OUTPUT=$4
ffmpeg -y -i "$INTRO" -i "$INPUT" -i "$OUTRO" -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -c:v libx264 -crf 23 "$OUTPUT"
场景 3:视频转 GIF
# 高质量 GIF
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gif
# 低质量 GIF
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1" output.gif
扩展阅读
总结
本章介绍了 FFmpeg 的滤镜系统,包括:
- 视频滤镜(几何变换、颜色调整、模糊锐化、特效等)
- 音频滤镜(音量、均衡、滤波、特效等)
- 复合滤镜(画中画、拼接、混合等)
- 滤镜图语法和高级用法
掌握滤镜系统可以帮助您实现各种复杂的音视频处理需求。