首发地址:https://h89.cn/archives/244.html

FFmpeg 项目通常提供三个命令行工具,它们共享同一套编解码器和解析逻辑,但定位不同:

工具 定位 典型用途
ffmpeg 多媒体处理 转码、剪切、封装、推流、截图
ffplay 播放器 快速预览、验证解码、播放裸流/RTSP
ffprobe 媒体分析 查看 codec、时长、码率、帧率等元数据

简单关系:

  • ffmpeg 是“生产车间”,负责输入 → 处理 → 输出。
  • ffplay 是“试播厅”,让你直接看到或听到结果,不做文件输出。
  • ffprobe 是“体检仪”,只读取不修改,输出结构化信息。

三件套命令都遵循类似参数风格,但作用域不同:

ffmpeg [全局/输入选项] -i 输入 [输出选项] 输出
ffplay [选项] 输入
ffprobe [选项] 输入

FFmpeg 命令的参数顺序有讲究,但一般记忆方式如下:

ffmpeg [全局选项] [输入选项] -i 输入 [输出选项] 输出

核心原则:-i 之前的是影响输入读取或全局行为的选项,-i 之后的是影响输出的选项。某些选项(如 -ss-t)放在输入或输出位置语义不同,放在 -i 前通常更快。

跨平台与构建差异

  • 本文的 FFmpeg 参数适用于 Windows、macOS 和 Linux;多行命令中的 \ 是 Bash/zsh 续行符,Windows PowerShell 应改用反引号,CMD 则使用 ^
  • ffplay 依赖 SDL,部分 Linux 发行版的精简包或自编译版本不包含它;用 ffplay -version 确认是否可用。
  • libx264libx265 等第三方编码器及 NVENC、AMF、VideoToolbox 等硬件编码器取决于 FFmpeg 编译选项、驱动和硬件。先执行 ffmpeg -encoders 确认编码器存在。
  • 文中使用的 grephead 是 POSIX Shell 工具;Windows 中可用 PowerShell 的 Select-StringSelect-Object -First 1 替代,或直接使用 ffprobe 的 JSON 输出交给程序解析。

参数位置:-i 前后语义不同

FFmpeg 的选项按 -i 划分作用域:

位置 作用对象 典型选项
-i 之前 输入(解封装/解码)或全局 -ss-t-re-thread_queue_size
-i 之后 输出(编码/封装) -c:v-c:a-b:v-s-r-f

1. -ss 的位置差异

# 快但不精确:先 seek 到 30s,再开始解码
ffmpeg -ss 00:00:30 -i input.mp4 -c copy output.mp4

# 慢但精确:从头解码,到 30s 才开始输出
ffmpeg -i input.mp4 -ss 00:00:30 -c:v libx264 output.mp4
  • -i 前:FFmpeg 直接跳转到最近关键帧,速度快,但 -c copy 时剪切点会偏移到关键帧。
  • -i 后:FFmpeg 必须逐帧解码到目标位置,速度慢,但帧级精确。

2. -t 的位置差异

# 只读取输入前 10 秒
ffmpeg -t 10 -i input.mp4 -c copy out.mp4

# 从输出起点算,只输出 10 秒(常与 -ss 后位置配合)
ffmpeg -i input.mp4 -ss 30 -t 10 -c copy out.mp4

3. 为什么 -i 前通常更快

-i 前的选项作用于 demuxer 阶段,可以跳过部分输入数据;-i 后的选项作用于输出阶段,通常要等解码器完整跑过对应片段。

4. 常见组合示例

ffmpeg -ss 00:01:30 -i input.mp4 -t 20 -c copy output.mp4

这里 -ss 00:01:30-i 前快速定位,‑t 20-i 后控制输出 20 秒,是“快切 + 控长”的典型写法。

1. 媒体流分离与封装

分离视频、音频流

# 只保留视频,去掉音频
ffmpeg -i input.mp4 -vcodec copy -an output_video.mp4

# 只保留音频,去掉视频
ffmpeg -i input.mp4 -acodec copy -vn output_audio.aac
  • -an:不输出音频(audio none)
  • -vn:不输出视频(video none)
  • -c copy / -vcodec copy / -acodec copy:直接复制流,不重新编码,速度快且无损

视频解复用为原始码流

# H.264 裸流(Annex B)
ffmpeg -i test.mp4 -c:v copy -an -f h264 test.h264
ffmpeg -i test.avi -c:v copy -an -f h264 test.h264

视频封装(音视频合并)

ffmpeg -i video.mp4 -i audio.aac -c copy output.mp4
ffmpeg -i video.mp4 -i audio.aac -vcodec copy -acodec copy output.mp4

如果合并后音画不同步,通常是因为两个文件的时间基不一致,需要重新编码至少其中一路,或者显式指定时间戳:

ffmpeg -i video.mp4 -i audio.aac -c:v copy -c:a aac -shortest output.mp4
  • -shortest:在较短流结束时停止输出,避免一路流结束后出现静音/黑屏

2. 转码与压缩

常见转码

# 转码为 H.264 裸流
ffmpeg -i test.mp4 -c:v libx264 -s 352x278 -an -f h264 test.h264

# 禁用 B 帧、指定 GOP 长度
ffmpeg -i test.mp4 -c:v libx264 -bf 0 -g 25 -s 352x278 -an -f h264 test.h264

# 转码为 Xvid 封装
ffmpeg -i test.avi -vcodec mpeg4 -vtag xvid -qscale:v 0 test_xvid.avi

# 转码为 H.265/HEVC,通常能以更低码率达到相近画质
ffmpeg -i input.mp4 -c:v libx265 -crf 28 -tag:v hvc1 -c:a aac output.mp4
  • -crf:libx265 默认 28,范围 051,越小质量越高;同画质下比 libx264 的 crf 值通常高 46
  • -tag:v hvc1:在 MP4 容器中标记为 hvc1,确保 macOS/iOS 播放器兼容(默认 hev1 在 QuickTime 中可能无法硬解)
  • 硬件加速编码可用 hevc_nvenc(NVIDIA)、hevc_amf(AMD)或 hevc_videotoolbox(macOS)

常用视频参数:

参数 含义 说明
-b:v 视频码率 -b:v 1000k;不指定时由编码器、码率控制模式和输入决定
-r 帧率 -r 30;不指定时通常保留输入时间戳节奏
-s 分辨率 1920x1080,注意用 x 而非 *
-aspect 画面比例 16:94:3
-g GOP 大小 关键帧间隔,影响 seek 精度和码率
-bf B 帧数量 设为 0 可降低编码/解码延迟
-vcodec / -c:v 视频编码器 libx264hevc_nvenccopy
-vn 不输出视频 提取音频时常用

常用音频参数:

参数 含义 说明
-ar 采样率 4410048000
-ac 声道数 1(单声道)、2(立体声)
-b:a 音频码率 128k
-acodec / -c:a 音频编码器 aaclibmp3lamecopy
-an 不输出音频 提取视频时常用

3. 视频剪切与拼接

按时间剪切

ffmpeg -ss 00:01:30 -i input.mp4 -t 20 -c copy output.mp4
  • -ss 00:01:30:从 1 分 30 秒开始
  • -t 20:持续 20 秒

快速但不精确copy 模式下剪切点会就近对齐到关键帧,可能导致前后多几帧。需要精确到帧时改用重新编码:

ffmpeg -ss 00:01:30 -t 20 -i input.mp4 -c:v libx264 -c:a aac output.mp4

新版 FFmpeg 也支持在 -i 后写 -ss,这样语义上是“先读取到该位置再处理”,精度更高但速度较慢:

ffmpeg -i input.mp4 -ss 00:01:30 -t 20 -c:v libx264 -c:a aac output.mp4

拼接多个视频

推荐用 concat demuxer,先准备列表文件 list.txt

file 'part1.mp4'
file 'part2.mp4'
file 'part3.mp4'
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4
  • -safe 0:允许使用绝对路径或特殊字符路径
  • 拼接文件格式、分辨率、编码参数必须一致;不一致时先统一转码

4. 提取帧、生成 GIF、截图

提取视频帧为图片

# 每秒 1 帧
ffmpeg -i input.mp4 -r 1 -f image2 image-%03d.jpeg

# 按固定帧率 30.5 fps 提取
ffmpeg -i input.mp4 -vf fps=30.5 %3d.jpg

# 每 2 秒一帧
ffmpeg -i input.mp4 -vf fps=1/2 output_%03d.jpg

# 缩放为原尺寸一半,指定画质
ffmpeg -i input.mp4 -vf "scale=iw/2:ih/2" -qscale:v 2 -r 1 output_%03d.jpg
  • -qscale:v / -q:v:JPEG 质量,范围 2~31,越小质量越高。视频编码时推荐用 -crf 替代,能更好平衡质量与码率
  • -f image2:强制输出为图片序列,通常可省略,FFmpeg 会根据扩展名自动推断

生成 GIF

ffmpeg -i input.mp4 \
  -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=128[p];[s1][p]paletteuse" \
  output.gif
  • fps=10:GIF 帧率
  • scale=320:-1:宽度 320,高度按比例
  • lanczos:缩放算法,质量较好
  • palettegen / paletteuse:生成并应用调色板,减少颜色断层

5. 录制与推流

录制 RTSP 流

ffmpeg -rtsp_transport tcp -i rtsp://192.168.3.205:5555/test -c copy out.mkv
  • -rtsp_transport tcp 可降低复杂网络环境下 UDP 丢包造成的花屏;低延迟场景可按实际网络改回 UDP。

  • 选用 MKV 是因为它更适合流复制和进程意外中断;若必须交付 MP4,建议按时间分段输出,避免异常中断时索引未写完整。

  • HTTP/HTTPS 流可使用协议层重连选项;它们必须放在对应的 -i 前:

    ffmpeg -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5 \
      -i https://example.com/live.ts -c copy out.ts
    

    -reconnect-reconnect_streamed-reconnect_delay_max 是 HTTP 协议选项,不能用于 RTSP;RTSP 断流自动重连应由调用脚本或进程守护实现。

循环 RTMP 推流

ffmpeg -stream_loop -1 -i zyhc.mp4 \
  -c:a aac -ar 44100 -b:a 48k \
  -c:v libx264 -b:v 1024k \
  -f flv rtmp://192.168.100.240:8020/live/1234
  • -stream_loop -1:无限循环输入文件
  • -f flv:RTMP 通常要求 FLV 封装格式

6. ffplay 播放与预览

ffplay 是 FFmpeg 自带的简单播放器,基于 SDL。它不做文件输出,只用于快速验证媒体文件能否正常解码、画面是否正确、音频是否同步。

基础播放

ffplay input.mp4
ffplay input.mp3
ffplay input.wav

常用播放选项

# 静音播放
ffplay -an input.mp4

# 只播放音频
ffplay -vn input.mp4

# 循环播放
ffplay -loop 0 input.mp4

# 从指定时间开始播放
ffplay -ss 00:01:30 input.mp4

# 限制播放时长
ffplay -t 20 input.mp4

# 指定窗口大小
ffplay -x 1280 -y 720 input.mp4

# 指定视频滤镜(实时预览效果)
ffplay -vf "scale=640:360,eq=contrast=1.2" input.mp4

# 播放时显示更多信息
ffplay -showmode 1 input.mp4
参数 含义
-an 不播放音频
-vn 不播放视频
-loop 0 无限循环
-ss 起始播放时间
-t 播放时长
-x / -y 窗口宽高
-vf 视频滤镜
-af 音频滤镜
-showmode 显示模式(0=视频,1=波形,2=频谱)

播放网络流与裸数据

# 播放 RTSP 流
ffplay -rtsp_transport tcp rtsp://192.168.3.205:5555/test

# 播放 RTMP 流
ffplay rtmp://192.168.100.240:8020/live/1234

# 播放 YUV 裸数据
ffplay -f rawvideo -video_size 1920x1080 -pix_fmt yuv420p input.yuv

# 播放 PCM 裸音频
ffplay -f s16le -ar 44100 -ac 2 input.pcm
  • -rtsp_transport tcp:强制使用 TCP 传输 RTSP,避免 UDP 在复杂网络下丢包花屏
  • 裸数据(YUV/PCM)没有文件头,必须手动指定格式、分辨率、采样率等参数

7. ffprobe 媒体信息分析

ffprobe 用于探测媒体文件的元数据,不修改文件。它的输出格式灵活,可默认文本、JSON、XML、CSV 等,适合脚本化分析。

常用输出格式

# 默认文本输出
ffprobe input.mp4

# JSON 输出完整信息
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4

# XML 输出
ffprobe -v quiet -print_format xml -show_format -show_streams input.mp4

# CSV 输出,便于脚本解析
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate,bit_rate -of csv=p=0 input.mp4

查询指定流

# 只看视频流(v:0 表示第一个视频流)
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate,bit_rate -of default input.mp4

# 只看音频流(a:0 表示第一个音频流)
ffprobe -v error -select_streams a:0 -show_entries stream=codec_name,sample_rate,channels,bit_rate -of default input.mp4

# 查看容器格式信息
ffprobe -v error -show_entries format=format_name,duration,bit_rate,size -of default input.mp4

帧与包信息

# 查看所有帧信息(输出量大,建议加 -v quiet 或输出到文件)
ffprobe -v quiet -print_format json -show_frames input.mp4 > frames.json

# 查看所有包信息
ffprobe -v quiet -print_format json -show_packets input.mp4 > packets.json

# 统计视频总帧数(需完整遍历,较慢)
ffprobe -v error -select_streams v:0 -count_frames -show_entries stream=nb_read_frames -of default input.mp4

# 只查看关键帧时间戳
ffprobe -v error -select_streams v:0 -skip_frame nokey -show_frames \
  -show_entries frame=best_effort_timestamp_time -of csv=p=0 input.mp4
参数 含义
-show_format 显示容器格式信息
-show_streams 显示所有流信息
-show_frames 显示每帧信息
-show_packets 显示每个包信息
-select_streams v:0 选择第一个视频流
-select_streams a:0 选择第一个音频流
-count_frames 统计帧数
-print_format 输出格式:default/json/xml/csv/ini
-show_entries 只显示指定字段
-of -print_format

常见脚本用法

# 获取视频时长(秒)
ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4

# 获取视频分辨率
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 input.mp4

# 判断是否为关键帧开头的文件
ffprobe -v error -select_streams v:0 -show_frames \
  -show_entries frame=key_frame -of csv=p=0 input.mp4 | head -1

输出 1 表示首帧是关键帧。不要以 pict_type=I 判断:I 帧不一定是可随机访问的关键帧。

8. YUV 裸数据

YUV 转 AVI

ffmpeg -s 1920x1080 -pix_fmt yuv420p -f rawvideo -i input.yuv -c:v mpeg4 output.avi

YUV 裸数据没有文件头,必须指定 -s(分辨率)、-pix_fmt(像素格式),否则 FFmpeg 无法解析。

常见 YUV 像素格式:

  • yuv420p:最常用,4:2:0 采样
  • yuv422p:4:2:2 采样
  • yuv444p:4:4:4 采样,无压缩色度

9. 日志控制与调试

ffmpeg -hide_banner -v warning -i input.mp4 -r 10 %04d.jpg
  • -hide_banner:隐藏版本和编译配置信息
  • -v / -loglevel:日志级别

级别从多到少:

debug > verbose > info > warning > error > fatal > panic > quiet
  • quiet:完全不输出,配合 -stats 可以只显示进度
  • warning:只显示警告和错误,适合脚本批量处理

10. 常见踩坑

  1. -s 352*278 写法错误:应使用 x,即 -s 352x278,否则部分版本会报错。
  2. copy 模式下无法同时改码率或分辨率-c copy 意味着不解码,所以 -b:v-s 等参数无效。需要改这些参数时必须重新编码。
  3. YUV 文件必须指定格式参数:缺少 -s-pix_fmt 会报 Invalid data found
  4. GIF 调色板数量:默认 256 色,如果颜色断层严重,可提升 max_colors 或改用 split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse=dither=bayer
  5. 拼接失败:先检查各文件编码是否一致;不一致时先用统一参数转码一次再 concat。

本文链接:FFmpeg 三件套常用命令:ffmpeg、ffplay、ffprobe - https://h89.cn/archives/244.html

版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。

标签: ffmpeg, ffprobe, 视频, 音频, 转码, 剪切, ffplay, 编码器, 推流, 拼接

🎓 呈言英语 智能英语学习平台
📚单词学习 🎧听说练习 📖阅读理解 ✏️拼写练习 🌟 AI智能推荐 · 科学记忆曲线
🚀 立即开始免费学习

添加新评论