FFmpeg 实战手册:截图、GIF、剪辑、合并、加字幕——20 个高频场景一行命令搞定
FFmpeg 是视频处理领域的"瑞士军刀",但它的命令行参数实在太复杂了——每次都要去 Stack Overflow 复制粘贴。本文整理了20 个最高频的视频处理场景,每个场景都给出可直接复制使用的命令,并解释每个参数的含义,让你从"复制粘贴工程师"升级为"知道自己在干什么的 FFmpeg 用户"。涵盖:精准截图、高质量 GIF、无损剪辑、TS 合并、视频拼接、加水印、加字幕、音频提取、倍速播放、格式转换、横竖屏旋转、视频压缩等。
TL;DR:FFmpeg 核心语法:
ffmpeg -i 输入 [选项] 输出。关键参数速查:-ss起始时间、-t持续时长、-to结束时间、-vf视频滤镜、-c:v视频编码、-c:a音频编码、-preset编码速度。两个最重要的时间参数规则:-ss放-i前是快速 seek(关键帧精度),放-i后是精确 seek(逐帧解码)。
目录
- 一、FFmpeg 基础:你必须知道的 5 个核心概念
- 二、截图与缩略图
- 三、GIF 制作与优化
- 四、视频剪辑与截取
- 五、视频合并与拼接
- 六、音频处理
- 七、字幕处理
- 八、格式转换与压缩
- 九、滤镜与特效
- 十、信息查看与调试
一、FFmpeg 基础:你必须知道的 5 个核心概念
1.1 命令结构
ffmpeg [输入选项] -i 输入文件 [编码选项] [滤镜选项] 输出文件
1.2 时间参数:-ss、-t、-to
| 参数 | 含义 | 示例 |
|---|---|---|
-ss |
开始时间 | -ss 00:01:30 或 -ss 90(秒) |
-t |
持续时长 | -t 30 截取 30 秒 |
-to |
结束时间 | -to 00:02:00 截到第 2 分钟 |
关键技巧:-ss 的位置决定精度和速度
# 快速但不够精确(跳到最近的关键帧)
ffmpeg -ss 00:01:30 -i input.mp4 -t 30 output.mp4
# 精确但慢(逐帧解码到指定位置)
ffmpeg -i input.mp4 -ss 00:01:30 -t 30 output.mp4
# 最佳实践:先用关键帧快速跳,再精确截取
ffmpeg -ss 00:01:25 -i input.mp4 -ss 5 -t 30 output.mp4
1.3 编码参数
| 参数 | 含义 | 常用值 |
|---|---|---|
-c:v / -vcodec |
视频编码器 | libx264, libx265, copy(不重新编码) |
-c:a / -acodec |
音频编码器 | aac, libmp3lame, copy |
-preset |
编码速度 | ultrafast → fast → medium → slow → veryslow |
-crf |
质量控制(H.264) | 0(无损) ~ 51(最差),默认 23,推荐 18-28 |
-b:v |
视频码率 | 2M, 5000k |
1.4 流映射(-map)
FFmpeg 默认只选一个视频流和一个音频流。多流文件需要手动指定:
# 选择第 2 个视频流和第 1 个音频流
ffmpeg -i input.mkv -map 0:v:1 -map 0:a:0 output.mp4
# 选择所有视频流
ffmpeg -i input.mkv -map 0:v output.mp4
1.5 copy 模式——无损处理的秘诀
# 不重新编码,直接复制流(几乎零损耗)
ffmpeg -i input.mp4 -c copy output.mp4
# 截取时也用 copy(注意:必须从关键帧开始)
ffmpeg -ss 00:01:00 -i input.mp4 -t 30 -c copy output.mp4
二、截图与缩略图
2.1 单帧截图
# 截取第 10 秒的画面
ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 output.jpg
# 指定分辨率
ffmpeg -i input.mp4 -ss 00:00:10 -vframes 1 -s 1920x1080 output.jpg
2.2 定时截图(每秒一张)
# 每秒截一张图,命名 output_001.jpg, output_002.jpg ...
ffmpeg -i input.mp4 -vf fps=1 output_%03d.jpg
# 每 5 秒截一张
ffmpeg -i input.mp4 -vf fps=1/5 output_%03d.jpg
2.3 生成视频缩略图网格(联系表)
# 生成 4x4 网格的缩略图(共 16 张)
ffmpeg -i input.mp4 \
-vf "fps=1/$(echo $(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 input.mp4) / 16 | bc), \
scale=320:-1,tile=4x4" \
-frames:v 1 contact_sheet.jpg
2.4 用 Python 批量生成
import subprocess
import os
def generate_thumbnails(video_path, output_dir, interval=10):
"""每隔 interval 秒截取一张缩略图"""
os.makedirs(output_dir, exist_ok=True)
output_pattern = os.path.join(output_dir, 'thumb_%04d.jpg')
cmd = [
'ffmpeg', '-i', video_path,
'-vf', f'fps=1/{interval}',
'-q:v', '2', # 高质量(1-31,越小越好)
output_pattern
]
subprocess.run(cmd, check=True)
三、GIF 制作与优化
3.1 基础 GIF 制作
# 将 5 秒视频转为 GIF(10fps)
ffmpeg -i input.mp4 -ss 00:00:10 -t 5 \
-vf "fps=10,scale=480:-1:flags=lanczos" \
output.gif
3.2 高质量 GIF(调色板优化)
# 两步法:先生成调色板,再编码(颜色更准确,体积更小)
ffmpeg -i input.mp4 -ss 00:00:10 -t 5 \
-vf "fps=10,scale=480:-1:flags=lanczos,palettegen" \
palette.png
ffmpeg -i input.mp4 -ss 00:00:10 -t 5 \
-i palette.png \
-filter_complex "fps=10,scale=480:-1:flags=lanczos[x];[x][1:v]paletteuse" \
output.gif
3.3 体积与质量平衡
| 参数 | 小体积 | 平衡 | 高质量 |
|---|---|---|---|
| fps | 8 | 12 | 15 |
| scale | 320 | 480 | 640 |
| dither | bayer |
floyd_steinberg |
none |
# 小体积版(适合聊天表情)
ffmpeg -i input.mp4 -t 3 \
-vf "fps=8,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse=dither=bayer" \
small.gif
# 高质量版(适合展示)
ffmpeg -i input.mp4 -t 5 \
-vf "fps=15,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen=stats_mode=diff[p];[s1][p]paletteuse=dither=bayer:bayer_scale=5" \
high_quality.gif
四、视频剪辑与截取
4.1 精确截取一段
# 从第 1 分 30 秒开始,截取 30 秒
ffmpeg -ss 00:01:30 -i input.mp4 -t 30 -c copy output.mp4
# 截取 01:30 到 02:00
ffmpeg -ss 00:01:30 -to 00:02:00 -i input.mp4 -c copy output.mp4
4.2 删除片头片尾
# 删除前 10 秒和后 20 秒
# 先获取总时长
DURATION=$(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 input.mp4)
# 截取中间部分
ffmpeg -ss 10 -i input.mp4 -t $(echo "$DURATION - 30" | bc) -c copy output.mp4
4.3 多段截取并合并
# 创建截取列表文件 cut_list.txt
# file 'input.mp4'
# inpoint 30
# outpoint 60
# file 'input.mp4'
# inpoint 120
# outpoint 180
ffmpeg -f concat -safe 0 -i cut_list.txt -c copy output.mp4
4.4 裁剪画面(Crop)
# 从 1920x1080 的视频中裁剪中央 640x480 区域
# crop=宽:高:左上角x:左上角y
ffmpeg -i input.mp4 -vf "crop=640:480:(in_w-640)/2:(in_h-480)/2" output.mp4
# 去掉上下黑边(自动检测)
ffmpeg -i input.mp4 -vf "cropdetect=limit=0:round=2" -t 10 -f null -
# 输出示例:crop=1920:816:0:132
ffmpeg -i input.mp4 -vf "crop=1920:816:0:132" output.mp4
五、视频合并与拼接
5.1 同格式合并(无损,最快)
# 创建文件列表 concat_list.txt
# file 'part1.ts'
# file 'part2.ts'
# file 'part3.ts'
ffmpeg -f concat -safe 0 -i concat_list.txt -c copy output.ts
5.2 不同格式拼接
# 需要重新编码,统一格式
ffmpeg -i part1.mp4 -i part2.avi -i part3.mkv \
-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
5.3 M3U8 TS 分片合并
# 方法 1:concat 协议(TS 格式兼容)
ffmpeg -i "concat:seg1.ts|seg2.ts|seg3.ts" -c copy output.ts
# 方法 2:用 concat demuxer(通过文件列表)
# 先读取 m3u8 生成列表
grep -v '^#' playlist.m3u8 | sed 's/^/file /' > ts_list.txt
ffmpeg -f concat -safe 0 -i ts_list.txt -c copy output.mp4
# 方法 3:直接下载 m3u8(推荐)
ffmpeg -i "https://example.com/playlist.m3u8" -c copy output.mp4
5.4 视频横向/纵向拼接
# 左右拼接(hstack)
ffmpeg -i left.mp4 -i right.mp4 \
-filter_complex hstack output.mp4
# 上下拼接(vstack)
ffmpeg -i top.mp4 -i bottom.mp4 \
-filter_complex vstack output.mp4
# 画中画(覆盖)
ffmpeg -i main.mp4 -i pip.mp4 \
-filter_complex "[1:v]scale=320:-1[pip];[0:v][pip]overlay=W-w-10:H-h-10" \
output.mp4
六、音频处理
6.1 提取音频
# 提取为 AAC
ffmpeg -i input.mp4 -vn -c:a aac -b:a 192k output.aac
# 提取为 MP3
ffmpeg -i input.mp4 -vn -c:a libmp3lame -b:a 192k output.mp3
# 无损提取(不重新编码)
ffmpeg -i input.mp4 -vn -c:a copy output.aac
6.2 替换音频
# 保留视频流,替换音频
ffmpeg -i video.mp4 -i audio.mp3 \
-c:v copy -c:a aac -map 0:v:0 -map 1:a:0 \
-shortest output.mp4
6.3 音量调节
# 音量增大 2 倍
ffmpeg -i input.mp4 -af "volume=2.0" output.mp4
# 音量减小一半
ffmpeg -i input.mp4 -af "volume=0.5" output.mp4
# 标准化音量(EBU R128 响度标准)
ffmpeg -i input.mp4 -af "loudnorm=I=-16:LRA=11:TP=-1.5" output.mp4
6.4 去除/添加背景音乐
# 混合背景音乐(背景音乐音量 30%)
ffmpeg -i video.mp4 -i bgm.mp3 \
-filter_complex "[1:a]volume=0.3[bgm];[0:a][bgm]amix=inputs=2:duration=first" \
-c:v copy output.mp4
七、字幕处理
7.1 内嵌字幕(烧录到画面)
# 烧录 SRT 字幕
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt" output.mp4
# 指定字体和样式
ffmpeg -i input.mp4 \
-vf "subtitles=subtitle.srt:force_style='FontName=Arial,FontSize=24,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,BorderStyle=3,Outline=2,Shadow=1'" \
output.mp4
# 烧录 ASS 字幕(支持更丰富的样式)
ffmpeg -i input.mp4 -vf "ass=subtitle.ass" output.mp4
7.2 提取内封字幕
# 查看有哪些字幕轨
ffprobe -v error -show_entries stream=index,codec_type,codec_name:stream_tags=language \
-of default=noprint_wrappers=1 input.mkv
# 提取第 2 条字幕轨(索引从 0 开始)
ffmpeg -i input.mkv -map 0:s:1 -c copy subtitle.srt
7.3 添加软字幕(可开关,不重编码)
# 添加 SRT 为软字幕
ffmpeg -i input.mp4 -i subtitle.srt \
-c copy -c:s mov_text \
-map 0 -map 1 \
-metadata:s:s:0 language=zh \
output.mp4
八、格式转换与压缩
8.1 常用格式转换
# MKV → MP4(copy 模式,无损快转)
ffmpeg -i input.mkv -c copy output.mp4
# 注意:MKV 的某些编码 MP4 不支持,需要重编码
ffmpeg -i input.mkv -c:v libx264 -c:a aac output.mp4
# 任意格式 → MP4 (H.264 + AAC)
ffmpeg -i input.xxx -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k output.mp4
8.2 视频压缩
# CRF 控制质量(推荐)
# CRF 18 → 接近无损,文件大
# CRF 23 → 默认,质量好
# CRF 28 → 明显压缩,适合分享
# CRF 35 → 高度压缩,适合预览
ffmpeg -i input.mp4 -c:v libx264 -preset slow -crf 28 -c:a aac -b:a 96k output.mp4
# 指定目标体积(2-Pass)
# 假设目标 50MB,视频 600 秒
# 视频码率 = (50 * 8 * 1024) / 600 - 音频码率 ≈ 640kbps
ffmpeg -i input.mp4 -c:v libx264 -b:v 640k -pass 1 -f mp4 /dev/null
ffmpeg -i input.mp4 -c:v libx264 -b:v 640k -pass 2 output.mp4
8.3 批量格式转换(Python)
import os
import subprocess
from pathlib import Path
def batch_convert(input_dir, output_dir, target_format='mp4'):
"""批量转换视频格式"""
os.makedirs(output_dir, exist_ok=True)
for file in Path(input_dir).glob('*'):
if file.suffix.lower() in ['.mkv', '.avi', '.flv', '.mov', '.webm']:
output = Path(output_dir) / f'{file.stem}.{target_format}'
print(f'转换: {file.name} → {output.name}')
subprocess.run([
'ffmpeg', '-i', str(file),
'-c:v', 'libx264', '-preset', 'medium', '-crf', '23',
'-c:a', 'aac', '-b:a', '128k',
str(output)
], check=True)
九、滤镜与特效
9.1 视频水印
# 右下角添加图片水印(留 10px 边距)
ffmpeg -i input.mp4 -i watermark.png \
-filter_complex "overlay=W-w-10:H-h-10" \
output.mp4
# 添加文字水印
ffmpeg -i input.mp4 \
-vf "drawtext=text='VidDown':fontsize=24:fontcolor=white@0.5:\
x=W-tw-10:y=H-th-10:shadowcolor=black:shadowx=2:shadowy=2" \
output.mp4
9.2 倍速播放
# 2 倍速(视频 + 音频同步加速)
ffmpeg -i input.mp4 \
-filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
-map "[v]" -map "[a]" output.mp4
# 视频 2 倍速,音频正常
ffmpeg -i input.mp4 \
-filter_complex "[0:v]setpts=0.5*PTS[v]" \
-map "[v]" -map 0:a output.mp4
# 慢放 0.5 倍速
ffmpeg -i input.mp4 \
-filter_complex "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]" \
-map "[v]" -map "[a]" output.mp4
9.3 旋转与翻转
# 顺时针旋转 90 度
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4
# transpose=0: 逆时针 90 度 + 垂直翻转
# transpose=1: 顺时针 90 度
# transpose=2: 逆时针 90 度
# transpose=3: 顺时针 90 度 + 垂直翻转
# 水平翻转(镜像)
ffmpeg -i input.mp4 -vf "hflip" output.mp4
# 垂直翻转
ffmpeg -i input.mp4 -vf "vflip" output.mp4
9.4 模糊与马赛克
# 全画面高斯模糊
ffmpeg -i input.mp4 -vf "gblur=sigma=10" output.mp4
# 指定区域马赛克(覆盖 100x100 区域)
ffmpeg -i input.mp4 \
-vf "delogo=x=100:y=200:w=150:h=150:show=0" \
output.mp4
十、信息查看与调试
10.1 查看文件信息
# 基本信息
ffprobe input.mp4
# JSON 格式(方便程序解析)
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
# 仅查看关键字段
ffprobe -v error -show_entries format=duration,size,bit_rate \
-of default=noprint_wrappers=1 input.mp4
10.2 Python 解析视频信息
import json
import subprocess
def get_video_info(filepath):
"""获取视频元信息"""
cmd = [
'ffprobe', '-v', 'quiet', '-print_format', 'json',
'-show_format', '-show_streams', filepath
]
result = subprocess.run(cmd, capture_output=True, text=True)
info = json.loads(result.stdout)
format_info = info.get('format', {})
video_stream = next(
(s for s in info.get('streams', []) if s['codec_type'] == 'video'),
{}
)
return {
'duration': float(format_info.get('duration', 0)),
'size': int(format_info.get('size', 0)),
'bitrate': int(format_info.get('bit_rate', 0)),
'width': video_stream.get('width'),
'height': video_stream.get('height'),
'codec': video_stream.get('codec_name'),
'fps': eval(video_stream.get('r_frame_rate', '0/1')),
}
10.3 生成进度条(管道解析)
# FFmpeg 输出到 stderr,通过管道解析进度
ffmpeg -i input.mp4 -c:v libx264 output.mp4 2>&1 | \
grep -oP "time=\K[\d:.]+"
10.4 静默运行
# 完全静默(不显示进度)
ffmpeg -hide_banner -loglevel error -i input.mp4 output.mp4
# 只显示错误
ffmpeg -loglevel error -i input.mp4 output.mp4
# 显示进度条(默认)
ffmpeg -loglevel info -stats -i input.mp4 output.mp4
速查表
| 场景 | 命令模板 |
|---|---|
| 截图 | ffmpeg -i in.mp4 -ss 10 -vframes 1 out.jpg |
| GIF | ffmpeg -i in.mp4 -t 5 -vf "fps=10,scale=480:-1" out.gif |
| 截取 | ffmpeg -ss 01:30 -i in.mp4 -t 30 -c copy out.mp4 |
| 合并 | ffmpeg -f concat -i list.txt -c copy out.mp4 |
| 转格式 | ffmpeg -i in.mkv -c:v libx264 -c:a aac out.mp4 |
| 压缩 | ffmpeg -i in.mp4 -c:v libx264 -crf 28 out.mp4 |
| 提取音频 | ffmpeg -i in.mp4 -vn -c:a aac out.aac |
| 烧录字幕 | ffmpeg -i in.mp4 -vf "subtitles=sub.srt" out.mp4 |
| 加水印 | ffmpeg -i in.mp4 -i logo.png -filter_complex "overlay=W-w-10:H-h-10" out.mp4 |
| 倍速 | ffmpeg -i in.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" out.mp4 |