视频处理
视频处理
概述
FFmpeg 提供了丰富的视频处理功能,包括裁剪、缩放、旋转、翻转、去噪、稳定等操作。这些功能主要通过视频滤镜(Video Filter)实现。
视频裁剪
基本裁剪
裁剪滤镜语法:
crop=w:h:x:y
| 参数 | 说明 |
|---|
| w | 输出宽度 |
| h | 输出高度 |
| x | 左上角 x 坐标 |
| y | 左上角 y 坐标 |
# 裁剪 640x480 区域(从左上角开始)
ffmpeg -i input.mp4 -vf crop=640:480 output.mp4
# 从指定位置裁剪
ffmpeg -i input.mp4 -vf crop=640:480:100:50 output.mp4
# 裁剪中心区域
ffmpeg -i input.mp4 -vf "crop=in_w-100:in_h-100" output.mp4
智能裁剪
# 保持宽高比裁剪到 16:9
ffmpeg -i input.mp4 -vf "crop=in_w:in_w*9/16" output.mp4
# 保持宽高比裁剪到 4:3
ffmpeg -i input.mp4 -vf "crop=in_h*4/3:in_h" output.mp4
# 自动裁剪黑边
ffmpeg -i input.mp4 -vf "cropdetect=24:16:0" output.mp4
# 使用检测到的参数裁剪
ffmpeg -i input.mp4 -vf "crop=640:480:0:30" output.mp4
裁剪参数表达式
# 使用表达式
ffmpeg -i input.mp4 -vf "crop=in_w/2:in_h/2:in_w/4:in_h/4" output.mp4
# 使用变量
# iw, ih - 输入宽高
# ow, oh - 输出宽高
# n - 帧序号
# t - 时间(秒)
ffmpeg -i input.mp4 -vf "crop=iw/2:ih/2" output.mp4
视频缩放
基本缩放
缩放滤镜语法:
scale=w:h
# 缩放到固定尺寸
ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4
# 缩放到 720p
ffmpeg -i input.mp4 -vf scale=-1:720 output.mp4
# 缩放到 1080p
ffmpeg -i input.mp4 -vf scale=-1:1080 output.mp4
# 缩放到 4K
ffmpeg -i input.mp4 -vf scale=3840:2160 output.mp4
保持宽高比缩放
# 保持宽高比,高度自适应
ffmpeg -i input.mp4 -vf "scale=1280:-1" output.mp4
# 保持宽高比,宽度自适应
ffmpeg -i input.mp4 -vf "scale=-1:720" output.mp4
# 保持宽高比,确保不超过目标尺寸
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease" output.mp4
# 填充黑边保持宽高比
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4
缩放算法
| 算法 | 说明 | 适用场景 |
|---|
| bilinear | 双线性插值 | 快速缩放 |
| bicubic | 双三次插值 | 通用缩放 |
| lanczos | Lanczos 采样 | 高质量缩放 |
| spline | 样条插值 | 高质量缩放 |
| neighbor | 最近邻 | 像素艺术 |
# 使用指定算法
ffmpeg -i input.mp4 -vf "scale=1280:720:flags=lanczos" output.mp4
# 使用 bicubic 算法
ffmpeg -i input.mp4 -vf "scale=1280:720:flags=bicubic" output.mp4
常用分辨率
| 名称 | 分辨率 | 宽高比 |
|---|
| 240p | 426×240 | 16:9 |
| 360p | 640×360 | 16:9 |
| 480p | 854×480 | 16:9 |
| 720p | 1280×720 | 16:9 |
| 1080p | 1920×1080 | 16:9 |
| 1440p | 2560×1440 | 16:9 |
| 4K | 3840×2160 | 16:9 |
| 8K | 7680×4320 | 16:9 |
视频旋转
旋转选项
# 顺时针旋转 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
# 使用 rotate 滤镜
ffmpeg -i input.mp4 -vf "rotate=PI/2" output.mp4
transpose 参数
| 值 | 说明 |
|---|
| 0 | 逆时针旋转 90 度并垂直翻转 |
| 1 | 顺时针旋转 90 度 |
| 2 | 逆时针旋转 90 度 |
| 3 | 顺时针旋转 90 度并垂直翻转 |
自动旋转
# 根据元数据自动旋转
ffmpeg -i input.mp4 -c copy -metadata:s:v:0 rotate=0 output.mp4
# 使用 autorotate
ffmpeg -i input.mp4 -autorotate 1 output.mp4
视频翻转
水平翻转
# 水平翻转(镜像)
ffmpeg -i input.mp4 -vf hflip output.mp4
垂直翻转
# 垂直翻转
ffmpeg -i input.mp4 -vf vflip output.mp4
同时翻转
# 水平和垂直翻转
ffmpeg -i input.mp4 -vf "hflip,vflip" output.mp4
视频去噪
常用去噪滤镜
| 滤镜 | 说明 | 适用场景 |
|---|
| hqdn3d | 高质量 3D 去噪 | 通用去噪 |
| nlmeans | 非局部均值去噪 | 高质量去噪 |
| dctdnoiz | DCT 去噪 | 压缩噪声 |
| removegrain | 去除颗粒 | 胶片颗粒 |
| atadenoise | ATA 去噪 | 实时去噪 |
hqdn3d 去噪
# 基本去噪
ffmpeg -i input.mp4 -vf hqdn3d output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "hqdn3d=4:3:6:4.5" output.mp4
# 参数说明
# luma_spatial: luma 空间强度 (默认 4)
# chroma_spatial: chroma 空间强度 (默认 3)
# luma_tmp: luma 时间强度 (默认 6)
# chroma_tmp: chroma 时间强度 (默认 4.5)
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
# 参数说明
# s: 去噪强度 (默认 7)
# p: 补丁大小 (默认 7)
# r: 搜索区域大小 (默认 15)
dctdnoiz 去噪
# 基本去噪
ffmpeg -i input.mp4 -vf "dctdnoiz=4.5" output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "dctdnoiz=4.5:2:3:all" output.mp4
atadenoise 去噪
# 基本去噪
ffmpeg -i input.mp4 -vf atadenoise output.mp4
# 自定义参数
ffmpeg -i input.mp4 -vf "atadenoise=0.2:0.2:0.2:0.5:0.5:0.5" 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
vidstab 参数
| 参数 | 说明 | 默认值 |
|---|
| shakiness | 抖动程度 (1-10) | 5 |
| accuracy | 检测精度 (1-15) | 15 |
| stepsize | 步长 | 6 |
| mincontrast | 最小对比度 | 0.25 |
| smoothing | 平滑帧数 | 10 |
| zoom | 缩放百分比 | 0 |
| optzoom | 自动缩放 (0-2) | 1 |
| interpol | 插值方法 | bilinear |
完整稳定脚本
#!/bin/bash
# stabilize.sh
INPUT=$1
OUTPUT=$2
SHAKINESS=${3:-5}
SMOOTHING=${30:-30}
# 第一遍分析
ffmpeg -y -i "$INPUT" \
-vf "vidstabdetect=shakiness=$SHAKINESS:accuracy=15:result=transforms.trf" \
-f null -
# 第二遍应用
ffmpeg -y -i "$INPUT" \
-vf "vidstabtransform=input=transforms.trf:smoothing=$SMOOTHING:zoom=5:optzoom=1" \
-c:v libx264 -crf 23 \
-c:a copy \
"$OUTPUT"
# 清理
rm -f transforms.trf
echo "稳定完成: $OUTPUT"
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:edge=mirror" output.mp4
画面增强
亮度对比度调整
# 调整亮度和对比度
ffmpeg -i input.mp4 -vf "eq=brightness=0.1:contrast=1.2" output.mp4
# 参数说明
# brightness: 亮度 (-1.0 到 1.0)
# contrast: 对比度 (0.0 到 2.0)
# saturation: 饱和度 (0.0 到 3.0)
# gamma: 伽马值 (0.1 到 10.0)
色彩调整
# 调整饱和度
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
锐化
# 使用 unsharp 锐化
ffmpeg -i input.mp4 -vf "unsharp=5:5:1.0:5:5:0.0" output.mp4
# 参数说明
# luma_msize_x: luma 水平尺寸 (默认 5)
# luma_msize_y: luma 垂直尺寸 (默认 5)
# luma_amount: luma 锐化强度 (默认 1.0)
# chroma_msize_x: chroma 水平尺寸 (默认 5)
# chroma_msize_y: chroma 垂直尺寸 (默认 5)
# chroma_amount: chroma 锐化强度 (默认 0.0)
# 轻度锐化
ffmpeg -i input.mp4 -vf "unsharp=3:3:0.5" output.mp4
# 强锐化
ffmpeg -i input.mp4 -vf "unsharp=5:5:2.0" output.mp4
色彩校正
# 白平衡调整
ffmpeg -i input.mp4 -vf "colorbalance=rs=0.1:gs=-0.1:bs=-0.1" output.mp4
# 色调调整
ffmpeg -i input.mp4 -vf "hue=h=30:s=1" output.mp4
# 曲线调整
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 "pad=1920:1080:0:0:black" output.mp4
# 居中添加黑边
ffmpeg -i input.mp4 -vf "pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black" output.mp4
# 指定颜色
ffmpeg -i input.mp4 -vf "pad=1920:1080:(ow-iw)/2:(oh-ih)/2:0x333333" output.mp4
裁剪与填充组合
# 缩放并填充到 16:9
ffmpeg -i input.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2" output.mp4
# 缩放并填充到 4:3
ffmpeg -i input.mp4 -vf "scale=1440:1080:force_original_aspect_ratio=decrease,pad=1440:1080:(ow-iw)/2:(oh-ih)/2" output.mp4
画面叠加
水印叠加
# 右下角水印
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=W-w-10:H-h-10" output.mp4
# 左上角水印
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" output.mp4
# 居中水印
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=(W-w)/2:(H-h)/2" output.mp4
# 带透明度的水印
ffmpeg -i input.mp4 -i watermark.png -filter_complex "[1:v]format=rgba,colorchannelmixer=aa=0.5[wm];[0:v][wm]overlay=W-w-10:H-h-10" 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" output.mp4
# 左上角画中画
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=320:240[pip];[0:v][pip]overlay=10:10" output.mp4
# 可切换位置
ffmpeg -i main.mp4 -i pip.mp4 -filter_complex "[1:v]scale=320:240[pip];[0:v][pip]overlay='if(gte(t,2),W-w-10,10)':H-h-10" output.mp4
画面特效
淡入淡出
# 淡入(前 2 秒)
ffmpeg -i input.mp4 -vf "fade=t=in:st=0:d=2" output.mp4
# 淡出(最后 2 秒)
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
模糊效果
# 高斯模糊
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
# 智能模糊(保留边缘)
ffmpeg -i input.mp4 -vf "smartblur=5:1.0:-0.5" output.mp4
边缘检测
# 边缘检测
ffmpeg -i input.mp4 -vf "edgedetect=low=0.1:high=0.4" output.mp4
# Canny 边缘检测
ffmpeg -i input.mp4 -vf "edgedetect=mode=canny" output.mp4
画面合成
拼接视频
# 水平拼接
ffmpeg -i left.mp4 -i right.mp4 -filter_complex "[0:v][1:v]hstack" output.mp4
# 垂直拼接
ffmpeg -i top.mp4 -i bottom.mp4 -filter_complex "[0:v][1:v]vstack" 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" \
output.mp4
画面混合
# 叠加混合
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v][1:v]blend=all_mode=overlay:all_opacity=0.5" output.mp4
# 变暗混合
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v][1:v]blend=all_mode=darken" output.mp4
# 变亮混合
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v][1:v]blend=all_mode=lighten" output.mp4
画面裁剪区域
动态裁剪
# 随时间移动裁剪区域
ffmpeg -i input.mp4 -vf "crop=640:480:n*10:0" output.mp4
# 跟踪移动对象
ffmpeg -i input.mp4 -vf "crop=640:480:'if(gte(t,2),100,0)':0" output.mp4
画面缩放动画
缩放动画
# 缩放动画(从 1x 到 2x)
ffmpeg -i input.mp4 -vf "zoompan=z='min(zoom+0.0015,1.5)':d=125:s=1280x720" output.mp4
# Ken Burns 效果
ffmpeg -i input.mp4 -vf "zoompan=z='min(max(zoom,pzoom)+0.0015,1.5)':d=125:s=1280x720:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)'" output.mp4
批量处理
批量裁剪脚本
#!/bin/bash
# batch_crop.sh
INPUT_DIR=${1:-.}
OUTPUT_DIR=${2:-cropped}
CROP=${3:-640:480:0:0}
mkdir -p "$OUTPUT_DIR"
for file in "$INPUT_DIR"/*.mp4; do
filename=$(basename "$file")
output="$OUTPUT_DIR/$filename"
echo "裁剪: $file"
ffmpeg -y -i "$file" -vf "crop=$CROP" -c:v libx264 -crf 23 -c:a copy "$output"
done
echo "批量裁剪完成"
批量缩放脚本
#!/bin/bash
# batch_scale.sh
INPUT_DIR=${1:-.}
OUTPUT_DIR=${2:-scaled}
RESOLUTION=${3:-1280:720}
mkdir -p "$OUTPUT_DIR"
for file in "$INPUT_DIR"/*.mp4; do
filename=$(basename "$file")
output="$OUTPUT_DIR/$filename"
echo "缩放: $file"
ffmpeg -y -i "$file" -vf "scale=$RESOLUTION" -c:v libx264 -crf 23 -c:a copy "$output"
done
echo "批量缩放完成"
注意事项
- 性能考虑:复杂的滤镜链会增加处理时间
- 内存占用:高分辨率视频处理需要大量内存
- 质量损失:多次处理会导致质量累积损失
- 编解码器选择:处理后建议使用高质量编解码器
- 测试优先:处理前先用短视频测试效果
业务场景
场景 1:视频缩略图
# 提取缩略图
ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 -vf "scale=320:180" thumbnail.jpg
场景 2:社交媒体视频
# 竖屏视频(9:16)
ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" -c:v libx264 -crf 23 output.mp4
# 方形视频(1:1)
ffmpeg -i input.mp4 -vf "scale=1080:1080:force_original_aspect_ratio=decrease,pad=1080:1080:(ow-iw)/2:(oh-ih)/2" -c:v libx264 -crf 23 output.mp4
场景 3:视频监控
# 添加时间戳水印
ffmpeg -i input.mp4 -vf "drawtext=text='%{localtime\:%Y-%m-%d %H\\\:%M\\\:%S}':x=10:y=10:fontsize=24:fontcolor=white:box=1:[email protected]" output.mp4
场景 4:视频画廊
# 创建 2x2 视频画廊
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i 4.mp4 \
-filter_complex \
"[0:v]scale=640:360[v0]; \
[1:v]scale=640:360[v1]; \
[2:v]scale=640:360[v2]; \
[3:v]scale=640:360[v3]; \
[v0][v1]hstack[top]; \
[v2][v3]hstack[bottom]; \
[top][bottom]vstack[out]" \
-map "[out]" -map 0:a? output.mp4
扩展阅读
- FFmpeg 视频滤镜文档
- FFmpeg 滤镜表达式
- vid.stab 稳定库
- FFmpeg 滤镜图
总结
本章介绍了 FFmpeg 的视频处理功能,包括:
- 视频裁剪与缩放
- 旋转与翻转
- 去噪与稳定
- 画面增强与特效
- 画面叠加与合成
掌握这些功能可以帮助您完成各种视频处理任务。