FFMPEG 常用命令

发布于 2020-07-09  299 次阅读


前言

FFMPEG 是特别强大的专门用于处理音视频的开源库。你既可以使用它的 API 对音视频进行处理,也可以使用它提供的工具,如 ffmpeg, ffplay, ffprobe,来编辑你的音视频文件。

本文将简要介绍一下 FFMPEG 库的基本目录结构及其功能,然后详细介绍一下我们在日常工作中,如何使用 ffmpeg 提供的工具来处理音视频文件。

FFMPEG 目录及作用

  • libavcodec: 提供了一系列编码器的实现。
  • libavformat: 实现在流协议,容器格式及其本 IO 访问。
  • libavutil: 包括了 hash 器,解码器和各利工具函数。
  • libavfilter: 提供了各种音视频过滤器。
  • libavdevice: 提供了访问捕获设备和回放设备的接口。
  • libswresample: 实现了混音和重采样。
  • libswscale: 实现了色彩转换和缩放工能。

FFMPEG 基本概念

在讲解 FFMPEG 命令之前,我们先要介绍一些音视频格式的基要概念。

  • 音/视频流

在音视频领域,我们把一路音/视频称为一路流。如我们小时候经常使用 VCD 看港片,在里边可以选择粤语或国语声音,其实就是 CD 视频文件中存放了两路音频流,用户可以选择其中一路进行播放。

  • 容器

我们一般把 MP4、 FLV、MOV 等文件格式称之为容器。也就是在这些常用格式文件中,可以存放多路音视频文件。以 MP4 为例,就可以存放一路视频流,多路音频流,多路字幕流。

  • channel

channel 是音频中的概念,称之为声道。在一路音频流中,可以有单声道,双声道或立体声。

FFMPEG 命令

我们按使用目的可以将 FFMPEG 命令分成以下几类:

  • 基本信息查询命令
  • 录制
  • 分解 / 复用
  • 处理原始数据
  • 滤镜
  • 切割与合并
  • 图/视互转
  • 直播相关

除了 FFMPEG 的基本信息查询命令外,其它命令都按下图所示的流程处理音视频。

 _______              ______________
|       |            |              |
| input |  demuxer   | encoded data |   decoder
| file  | ---------> | packets      | -----+
|_______|            |______________|      |
                                           v
                                       _________
                                      |         |
                                      | decoded |
                                      | frames  |
                                      |_________|
 ________             ______________       |
|        |           |              |      |
| output | <-------- | encoded data | <----+
| file   |   muxer   | packets      |   encoder
|________|           |______________|

ffmpeg 调用 libavformat 库(包含 demuxers)来读取输入文件并获取包含编码数据的数据包。 当有多个输入文件时,ffmpeg 会尝试通过跟踪任何活动输入流上的最低时间戳来使其保持同步。

然后将编码的数据包传送给解码器(除非为数据流选择了流拷贝,请参阅进一步描述)。 解码器产生未压缩的帧(原始视频 / PCM 音频 / …),可以通过滤波进一步处理(见下一节)。 在过滤之后,帧被传递到编码器,编码器并输出编码的数据包。 最后,这些传递给复用器,将编码的数据包写入输出文件。

默认情况下,ffmpeg 只包含输入文件中每种类型(视频,音频,字幕)的一个流,并将其添加到每个输出文件中。 它根据以下标准挑选每一个的 “最佳”:对于视频,它是具有最高分辨率的流,对于音频,它是具有最多 channel 的流,对于字幕,是第一个字幕流。 在相同类型的几个流相等的情况下,选择具有最低索引的流。

您可以通过使用 - vn / -an / -sn / -dn 选项来禁用某些默认设置。 要进行全面的手动控制,请使用 - map 选项,该选项禁用刚描述的默认设置。

下面我们就来详细介绍一下这些命令。

基本信息查询命令

FFMPEG 可以使用下面的参数进行基本信息查询。例如,想查询一下现在使用的 FFMPEG 都支持哪些 filter,就可以用 ffmpeg -filters 来查询。详细参数说明如下:

接下来介绍的是 FFMPEG 处理音视频时使用的命令格式与参数。

命令基本格式及参数

下面是 FFMPEG 的基本命令格式:

ffmpeg [global_options] {[input_file_options] -i input_url} ...
                         {[output_file_options] output_url} ...

ffmpeg 通过 -i 选项读取输任意数量的输入 “文件”(可以是常规文件,管道,网络流,抓取设备等,并写入任意数量的输出 “文件”。

原则上,每个输入 / 输出 “文件” 都可以包含任意数量的不同类型的视频流(视频 / 音频 / 字幕 / 附件 / 数据)。 流的数量和 / 或类型是由容器格式来限制。 选择从哪个输入进入到哪个输出将自动完成或使用 -map 选项。

要引用选项中的输入文件,您必须使用它们的索引(从 0 开始)。 例如。 第一个输入文件是 0,第二个输入文件是 1,等等。类似地,文件内的流被它们的索引引用。 例如。 2:3 是指第三个输入文件中的第四个流。

上面就是 FFMPEG 处理音视频的常用命令,下面是一些常用参数:

主要参数

视频参数

音频参数

了解了这些基本信息后,接下来我们看看 FFMPEG 具体都能干些什么吧。

录制
首先通过下面的命令查看一下 mac 上都有哪些设备。

ffmpeg -f avfoundation -list_devices true -i ""

录屏

ffmpeg -f avfoundation -i 1 -r 30 out.yuv
  • -f 指定使用 avfoundation 采集数据。
  • -i 指定从哪儿采集数据,它是一个文件索引号。在我的 MAC 上,1 代表桌面(可以通过上面的命令查询设备索引号)。
  • -r 指定帧率。按 ffmpeg 官方文档说 - r 与 - framerate 作用相同,但实际测试时发现不同。-framerate 用于限制输入,而 - r 用于限制输出。

注意,桌面的输入对帧率没有要求,所以不用限制桌面的帧率。其实限制了也没用。

录屏 + 声音

ffmpeg  -f avfoundation -i 1:0  -r 29.97 -c:v libx264 -crf 0 -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k  out.flv
  • -i 1:0 冒号前面的 “1” 代表的屏幕索引号。冒号后面的 "0" 代表的声音索相号。
  • -c:v 与参数 -vcodec 一样,表示视频编码器。c 是 codec 的缩写,v 是 video 的缩写。
  • -crf 是 x264 的参数。 0 表式无损压缩。
  • -c:a 与参数 -acodec 一样,表示音频编码器。
  • -profile 是 fdk_aac 的参数。 aac_he_v2 表式使用 AAC_HE v2 压缩数据。
  • -b:a 指定音频码率。 b 是 bitrate 的缩写, a 是 audio 的缩与。

录视频

ffmpeg -framerate 30 -f avfoundation -i 0 out.mp4 
  • -framerate 限制视频的采集帧率。这个必须要根据提示要求进行设置,如果不设置就会报错。
  • -f 指定使用 avfoundation 采集数据。
  • -i 指定视频设备的索引号。

视频 + 音频

ffmpeg -framerate 30 -f avfoundation -i 0:0 out.mp4 

录音

ffmpeg -f avfoundation -i :0 out.wav

录制音频裸数据

ffmpeg  -f avfoundation -i :0 -ar 44100 -f s16le out.pcm

分解与复用

流拷贝是通过将 copy 参数提供给 - codec 选项来选择流的模式。它使得 ffmpeg 省略了指定流的解码和编码步骤,所以它只能进行多路分解和多路复用。 这对于更改容器格式或修改容器级元数据很有用。 在这种情况下,上图将简化为:

 _______              ______________            ________
|       |            |              |          |        |
| input |  demuxer   | encoded data |  muxer   | output |
| file  | ---------> | packets      | -------> | file   |
|_______|            |______________|          |________|

由于没有解码或编码,速度非常快,没有质量损失。 但是,由于许多因素,在某些情况下可能无法正常工作。 应用过滤器显然也是不可能的,因为过滤器处理未压缩的数据。

抽取音频流

ffmpeg -i input.mp4 -acodec copy -vn out.aac
  • acodec: 指定音频编码器,copy 指明只拷贝,不做编解码。
  • vn: v 代表视频,n 代表 no 也就是无视频的意思。

抽取视频流

ffmpeg -i input.mp4 -vcodec copy -an out.h264
  • vcodec: 指定视频编码器,copy 指明只拷贝,不做编解码。
  • an: a 代表视频,n 代表 no 也就是无音频的意思。

转格式

ffmpeg -i out.mp4 -vcodec copy -acodec copy out.flv

上面的命令表式的是音频、视频都直接 copy,只是将 mp4 的封装格式转成了 flv。

音视频合并

ffmpeg -i out.h264 -i out.aac -vcodec copy -acodec copy out.mp4

处理原始数据

提取 YUV 数据

ffmpeg -i input.mp4 -an -c:v rawvideo -pixel_format yuv420p out.yuv
ffplay -s wxh out.yuv
  • -c:v rawvideo 指定将视频转成原始数据
  • -pixel_format yuv420p 指定转换格式为 yuv420p

YUV 转 H264

ffmpeg -f rawvideo -pix_fmt yuv420p -s 320x240 -r 30 -i out.yuv -c:v libx264 -f rawvideo out.h264

提取 PCM 数据

ffmpeg -i out.mp4 -vn -ar 44100 -ac 2 -f s16le out.pcm
ffplay -ar 44100 -ac 2 -f s16le -i out.pcm

PCM 转 WAV

ffmpeg -f s16be -ar 8000 -ac 2 -acodec pcm_s16be -i input.raw output.wav

滤镜

在编码之前,ffmpeg 可以使用 libavfilter 库中的过滤器处理原始音频和视频帧。 几个链式过滤器形成一个过滤器图形。 ffmpeg 区分两种类型的过滤器图形:简单和复杂。

简单滤镜

简单的过滤器图是那些只有一个输入和输出,都是相同的类型。 在上面的图中,它们可以通过在解码和编码之间插入一个额外的步骤来表示:

 _________                        ______________
|         |                      |              |
| decoded |                      | encoded data |
| frames  |\                   _ | packets      |
|_________| \                  /||______________|
             \   __________   /
  simple     _\||          | /  encoder
  filtergraph   | filtered |/
                | frames   |
                |__________|

简单的 filtergraphs 配置了 per-stream-filter 选项(分别为视频和音频使用 - vf 和 - af 别名)。 一个简单的视频 filtergraph 可以看起来像这样的例子:

 _______        _____________        _______        ________
|       |      |             |      |       |      |        |
| input | ---> | deinterlace | ---> | scale | ---> | output |
|_______|      |_____________|      |_______|      |________|

请注意,某些滤镜会更改帧属性,但不会改变帧内容。 例如。 上例中的 fps 过滤器会改变帧数,但不会触及帧内容。 另一个例子是 setpts 过滤器,它只设置时间戳,否则不改变帧。

复杂滤镜

复杂的过滤器图是那些不能简单描述为应用于一个流的线性处理链的过滤器图。 例如,当图形有多个输入和 / 或输出,或者当输出流类型与输入不同时,就是这种情况。 他们可以用下图来表示:

 _________
|         |
| input 0 |\                    __________
|_________| \                  |          |
             \   _________    /| output 0 |
              \ |         |  / |__________|
 _________     \| complex | /
|         |     |         |/
| input 1 |---->| filter  |\
|_________|     |         | \   __________
               /| graph   |  \ |          |
              / |         |   \| output 1 |
 _________   /  |_________|    |__________|
|         | /
| input 2 |/
|_________|

复杂的过滤器图使用 - filter_complex 选项进行配置。 请注意,此选项是全局性的,因为复杂的过滤器图形本质上不能与单个流或文件明确关联。

-lavfi 选项等同于 - filter_complex。

一个复杂的过滤器图的一个简单的例子是覆盖过滤器,它有两个视频输入和一个视频输出,包含一个视频叠加在另一个上面。 它的音频对应是 amix 滤波器。

添加水印

ffmpeg -i out.mp4  -vf "movie=logo.png,scale=64:48[watermask];[in][watermask] overlay=30:10 [out]" water.mp4
  • -vf 中的 movie 指定 logo 位置。scale 指定 logo 大小。overlay 指定 logo 摆放的位置。

删除水印
先通过 ffplay 找到要删除 LOGO 的位置

ffplay -i test.flv -vf delogo=x=806:y=20:w=70:h=80:show=1

使用 delogo 滤镜删除 LOGO

ffmpeg -i test.flv -vf delogo=x=806:y=20:w=70:h=80 output.flv

视频缩小一倍

ffmpeg -i out.mp4 -vf scale=iw/2:-1 scale.mp4
  • -vf scale 指定使用简单过滤器 scale,iw/2:-1 中的 iw 指定按整型取视频的宽度。 -1 表示高度随宽度一起变化。

视频裁剪

ffmpeg -i VR.mov  -vf crop=in_w-200:in_h-200 -c:v libx264 -c:a copy -video_size 1280x720 vr_new.mp4

crop 格式:crop=out_w:out_h: x :y

  • out_w: 输出的宽度。可以使用 in_w 表式输入视频的宽度。
  • out_h: 输出的高度。可以使用 in_h 表式输入视频的高度。
  • x : X 坐标
  • y : Y 坐标

如果 x 和 y 设置为 0, 说明从左上角开始裁剪。如果不写是从中心点裁剪。

倍速播放

ffmpeg -i out.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" speed2.0.mp4
  • -filter_complex 复杂滤镜,[0:v] 表示第一个(文件索引号是 0)文件的视频作为输入。setpts=0.5*PTS 表示每帧视频的 pts 时间戳都乘 0.5 ,也就是差少一半。[v] 表示输出的别名。音频同理就不详述了。
  • map 可用于处理复杂输出,如可以将指定的多路流输出到一个输出文件,也可以指定输出到多个文件。"[v]" 复杂滤镜输出的别名作为输出文件的一路流。上面 map 的用法是将复杂滤镜输出的视频和音频输出到指定文件中。

对称视频

ffmpeg  -i out.mp4 -filter_complex "[0:v]pad=w=2*iw[a];[0:v]hflip[b];[a][b]overlay=x=w" duicheng.mp4
  • hflip 水平翻转

如果要修改为垂直翻转可以用 vflip。

画中画

ffmpeg -i out.mp4 -i out1.mp4 -filter_complex "[1:v]scale=w=176:h=144:force_original_aspect_ratio=decrease[ckout];[0:v][ckout]overlay=x=W-w-10:y=0[out]" -map "[out]" -movflags faststart new.mp4

录制画中画

ffmpeg  -f avfoundation -i "1" -framerate 30 -f avfoundation -i "0:0" 
-r 30 -c:v libx264 -preset ultrafast 
-c:a libfdk_aac -profile:a aac_he_v2 -ar 44100 -ac 2 
-filter_complex "[1:v]scale=w=176:h=144:force_original_aspect_ratio=decrease[a];[0:v][a]overlay=x=W-w-10:y=0[out]" 
-map "[out]" -movflags faststart -map 1:a b.mp4

多路视频拼接

ffmpeg  -f avfoundation -i "1" -framerate 30 -f avfoundation   -i "0:0" -r 30 -c:v libx264 -preset ultrafast -c:a libfdk_aac -profile:a aac_he_v2 -ar 44100 -ac 2 -filter_complex "[0:v]scale=320:240[a];[a]pad=640:240[b];[b][1:v]overlay=320:0[out]" -map "[out]" -movflags faststart  -map 1:a  c.mp4

滤镜加水印

ffmpeg -i killer.mp4 -filter_complex "movie=./logo/daka.png,scale=64:48[w];[0:v]curves=vintage[o];[o][w]overlay=30:10[out]" -map "[out]" -map 0:a test1.mp4

一些比较有意思的滤镜

  • 镜像
    crop=iw/2:ih:0:0,split[left][tmp];[tmp]hflip[right];

  • 复古
    curves=vintage;

  • 光晕
    vignette=PI/4

  • 变暗
    colorlevels=rimin=0.058:gimin=0.058:bimin=0.058

  • 增加对比度
    fftfilt=dc_Y=0:weight_Y='exp(-4 * ((Y+X)/(W+H)))

  • 降噪
    hqdn3d=luma_spatial=15.0

  • 强对比度
    curves=strong_contrast

  • 变亮
    curves=lighter

  • 锐化
    fftfilt=dc_Y=0:weight_Y='1+squish(1-(Y+X)/100)'

  • 低通滤波
    fftfilt=dc_Y=0:weight_Y='squish((Y+X)/100-1)'

  • 高通滤波
    fftfilt=dc_Y=128:weight_Y='squish(1-(Y+X)/100)'

  • 复古
    curves=vintage

  • 边缘检测
    edgedetect

  • 底片
    negate

  • 彩色底片
    curves = ‘none’‘color_negative’

音视频的拼接与裁剪

裁剪

ffmpeg -i out.mp4 -ss 00:00:00 -t 10 out1.mp4
  • -ss 指定裁剪的开始时间,精确到秒
  • -t 被裁剪后的时长。

视频合并

首先创建一个 inputs.txt 文件,文件内容如下:

file '1.flv'
file '2.flv'
file '3.flv'

然后执行下面的命令:

ffmpeg -f concat -i inputs.txt -c copy output.flv

音频合并

ffmpeg -i text.mp3 -i silenceall.mp3 -filter_complex '[0:0] [1:0] concat=n=2:v=0:a=1 [a]' -map [a] test.mp3

音频混音

ffmpeg -i test.mp4 -i test.mp3 -filter_complex "[0:a] [1:a]amerge=inputs=2[aout]" -map "[aout]" -ac 2 mix_amerge.aac

ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex 'amix=inputs=3:duration=first:dropout_transition=3' OUTPUT
  • inputs: The number of inputs. If unspecified, it defaults to 2.// 输入的数量,如果没有指明,默认为 2.
  • duration: How to determine the end-of-stream.// 决定了流的结束
  • longest: The duration of the longest input. (default)// 最长输入的持续时间
  • shortest: The duration of the shortest input.// 最短输入的持续时间
  • first: The duration of the first input.// 第一个输入的持续时间
  • dropout_transition: The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds.// 输入流结束时(音频)容量重整化的转换时间(以秒为单位)。 默认值为 2 秒。

注: amerge 与 amix 的区别
amerge terminates with the shortest input (always) and amix terminates with the longest input, by default. So the former will always truncate when streams are of different length.

hls 切片

ffmpeg -i out.mp4 -c:v libx264 -c:a libfdk_aac -strict -2 -f hls  out.m3u8
  • -strict -2 指明音频使有 AAC。
  • -f hls 转成 m3u8 格式。

视频图片互转

视频转 JPEG

ffmpeg -i test.flv -r 1 -f image2 image-%3d.jpeg

视频转 gif

ffmpeg -i out.mp4 -ss 00:00:00 -t 10 out.gif

图片转视频

ffmpeg  -f image2 -i image-%3d.jpeg images.mp4

直播相关

推流

ffmpeg -re -i out.mp4 -c copy -f flv rtmp://server/live/streamName

拉流保存

ffmpeg -i rtmp://server/live/streamName -c copy dump.flv

转流

ffmpeg -i rtmp://server/live/originalStream -c:a copy -c:v copy -f flv rtmp://server/live/h264Stream

实时推流

ffmpeg -framerate 15 -f avfoundation -i "1" -s 1280x720 -c:v libx264  -f  flv rtmp://localhost:1935/live/room

ffplay

播放 YUV 数据

ffplay -pix_fmt nv12 -s 192x144 1.yuv

播放 YUV 中的 Y 平面

ffplay -pix_fmt nv21 -s 640x480 -vf extractplanes='y' 1.yuv

我的 ffmpeg 视频课地址

课程主页地址

作者:音视频_李超
链接:http://www.imooc.com/article/details/id/254520
来源:慕课网
本文原创发布于慕课网 ,转载请注明出处,谢谢合作

推荐阅读:

暴露真实 IP 真的没关系吗?

30 行 Javascript 代码实现图片懒加载

【前端干货整理】金九银十,offer 拿到手软的秘密都在这儿!

Github 上发布一天 Star 数破 4K 的项目了解一下

多线程并发的使用、学习与测试

为什么程序员应该有一台 Mac 个人电脑

藏在正则表达式里的陷阱

推荐 10 个 Java 方向最热门的开源项目

Git 使用教程, 最详细,最傻瓜,最浅显,真正手把手教

写下你的评论...

新手搭车请教一个问题,想把一段视频,直接分割成两段视频。用提取命令只能先提取出来一段,然后,再重复用这个命令,提取出另一段,才达到分割成两段的目的。这样操作似乎有些太 “弱智”,不大符合 ffmpeg 的强大表现。有没有一个命令就能把视频直接切成两段的呢?

这个问题解决了么

请教一个问题,mp4 格式的视频生成切片时,指定切片时长无效。我是在你的教程上加了参数,命令:ffmpeg -i out.mp4 -c:v libx264 -c:a libfdk_aac -strict -2 -segment_time 3 -f hls out.m3u8。我之前是先将 mp4 转成完整的 ts,再生成切片和 m3u8,参数也是 - segment_time 3,也是无效。谢谢。

使用 音频 1 -i -ar 22050 结果音频 这样的命令,为什么音频转换的不完整呢?


或许明日太阳西下倦鸟已归时