高级技巧
本文档介绍 FFMPEG 的高级使用技巧,包括视频速度调整、合并、滤镜、水印、字幕处理等。
视频速度调整
调整播放速度(音调不变)
bash
# 2 倍速
ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" -filter:a "atempo=2.0" output.mp4
# 0.5 倍速(慢动作)
ffmpeg -i input.mp4 -filter:v "setpts=2.0*PTS" -filter:a "atempo=0.5" output.mp4
# 1.5 倍速
ffmpeg -i input.mp4 -filter:v "setpts=0.666*PTS" -filter:a "atempo=1.5" output.mp4参数说明
setpts: 视频时间戳调整(PTS = Presentation Time Stamp)atempo: 音频速度调整(范围:0.5 - 2.0)- 超过 2 倍速需要多次应用
atempo
变速示例
bash
# 4 倍速(需要两次 atempo)
ffmpeg -i input.mp4 \
-filter:v "setpts=0.25*PTS" \
-filter:a "atempo=2.0,atempo=2.0" \
output.mp4视频合并
合并多个视频文件
方法一:使用 concat demuxer(推荐)
bash
# 创建文件列表
echo "file 'video1.mp4'" > filelist.txt
echo "file 'video2.mp4'" >> filelist.txt
echo "file 'video3.mp4'" >> filelist.txt
# 合并(不重新编码,速度快)
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4方法二:使用 concat filter(需要重新编码)
bash
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 \
-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]" output.mp4合并不同格式的视频
bash
# 先统一格式,再合并
ffmpeg -i video1.mov -i video2.avi \
-c:v libx264 -c:a aac \
-f concat -safe 0 -i filelist.txt \
output.mp4视频水印
添加图片水印
bash
# 左上角
ffmpeg -i input.mp4 -i watermark.png \
-filter_complex "[0:v][1:v]overlay=10:10" \
output.mp4
# 右下角
ffmpeg -i input.mp4 -i watermark.png \
-filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10" \
output.mp4
# 居中
ffmpeg -i input.mp4 -i watermark.png \
-filter_complex "[0:v][1:v]overlay=(W-w)/2:(H-h)/2" \
output.mp4添加文字水印
bash
# 使用 drawtext 滤镜
ffmpeg -i input.mp4 \
-vf "drawtext=text='Watermark Text':fontfile=/path/to/font.ttf:fontsize=24:fontcolor=white:x=10:y=10" \
output.mp4半透明水印
bash
# 调整水印透明度
ffmpeg -i input.mp4 -i watermark.png \
-filter_complex "[1:v]format=rgba,colorchannelmixer=aa=0.5[watermark];[0:v][watermark]overlay=10:10" \
output.mp4字幕处理
添加字幕文件
bash
# 硬编码字幕(字幕成为视频的一部分)
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt" output.mp4
# 软字幕(字幕作为独立轨道)
ffmpeg -i input.mp4 -i subtitle.srt \
-c:v copy -c:a copy \
-c:s mov_text \
-metadata:s:s:0 language=chi \
output.mp4提取字幕
bash
# 从视频中提取字幕
ffmpeg -i input.mp4 -map 0:s:0 subtitle.srt字幕格式转换
bash
# ASS 转 SRT
ffmpeg -i subtitle.ass subtitle.srt视频滤镜
亮度调整
bash
# 增加亮度
ffmpeg -i input.mp4 -vf "eq=brightness=0.1" output.mp4
# 减少亮度
ffmpeg -i input.mp4 -vf "eq=brightness=-0.1" output.mp4对比度调整
bash
# 增加对比度
ffmpeg -i input.mp4 -vf "eq=contrast=1.2" output.mp4饱和度调整
bash
# 增加饱和度
ffmpeg -i input.mp4 -vf "eq=saturation=1.5" output.mp4旋转视频
bash
# 顺时针旋转 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镜像翻转
bash
# 水平翻转
ffmpeg -i input.mp4 -vf "hflip" output.mp4
# 垂直翻转
ffmpeg -i input.mp4 -vf "vflip" output.mp4画中画效果
添加小窗口视频
bash
# 在右下角添加小窗口
ffmpeg -i main_video.mp4 -i small_video.mp4 \
-filter_complex "[1:v]scale=320:240[small];[0:v][small]overlay=W-w-10:H-h-10" \
output.mp4分屏显示
bash
# 左右分屏
ffmpeg -i left.mp4 -i right.mp4 \
-filter_complex "[0:v]scale=960:540[left];[1:v]scale=960:540[right];[left][right]hstack" \
output.mp4
# 上下分屏
ffmpeg -i top.mp4 -i bottom.mp4 \
-filter_complex "[0:v]scale=1920:540[top];[1:v]scale=1920:540[bottom];[top][bottom]vstack" \
output.mp4批量处理脚本
批量转码脚本
bash
#!/bin/bash
# 批量转码脚本
INPUT_DIR="./videos"
OUTPUT_DIR="./output"
CRF=23
PRESET="slow"
mkdir -p "$OUTPUT_DIR"
for file in "$INPUT_DIR"/*.mp4; do
if [ -f "$file" ]; then
filename=$(basename "$file")
output="$OUTPUT_DIR/${filename%.mp4}_compressed.mp4"
echo "处理: $filename"
ffmpeg -i "$file" \
-vcodec libx264 \
-crf "$CRF" \
-preset "$PRESET" \
-acodec aac \
-b:a 128k \
"$output" 2>&1 | grep -E "(error|Error|ERROR)" && echo "错误: $filename" || echo "完成: $output"
fi
done批量添加水印
bash
#!/bin/bash
# 批量添加水印
INPUT_DIR="./videos"
OUTPUT_DIR="./output"
WATERMARK="./watermark.png"
mkdir -p "$OUTPUT_DIR"
for file in "$INPUT_DIR"/*.mp4; do
filename=$(basename "$file")
output="$OUTPUT_DIR/${filename%.mp4}_watermarked.mp4"
echo "添加水印: $filename"
ffmpeg -i "$file" -i "$WATERMARK" \
-filter_complex "[0:v][1:v]overlay=W-w-10:H-h-10" \
-c:a copy \
"$output"
done批量提取帧
bash
#!/bin/bash
# 批量提取帧
INPUT_DIR="./videos"
OUTPUT_BASE="./frames"
for file in "$INPUT_DIR"/*.mp4; do
filename=$(basename "$file")
output_dir="$OUTPUT_BASE/${filename%.mp4}"
mkdir -p "$output_dir"
echo "提取帧: $filename"
ffmpeg -i "$file" -vf fps=1 "$output_dir/%08d.png"
done性能优化技巧
多线程处理
bash
# 使用多线程编码
ffmpeg -i input.mp4 -threads 4 -c:v libx264 output.mp4硬件加速
bash
# NVIDIA GPU 加速
ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_nvenc output.mp4
# Intel Quick Sync
ffmpeg -hwaccel qsv -i input.mp4 -c:v h264_qsv output.mp4内存优化
bash
# 限制内存使用
ffmpeg -i input.mp4 -threads 2 -c:v libx264 output.mp4常见问题解决
1. 视频无法播放
问题:转码后的视频在某些设备上无法播放
解决方案:
- 使用
-profile:v high和-level 4.0 - 确保像素格式为
yuv420p - 使用 H.264 编码
2. 处理速度慢
问题:转码速度太慢
解决方案:
- 使用硬件加速
- 调整 preset 为 faster
- 使用多线程
- 考虑使用
-c copy避免重新编码
3. 文件过大
问题:输出文件太大
解决方案:
- 调整 CRF 值(增大)
- 降低分辨率
- 降低音频比特率
- 使用更高效的编码格式(如 H.265)
返回:FFMPEG 专题首页
