ffmpeg 详细描述

在转码过程ffmpeg每个输出可以由以下图描述:

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

ffmpeg调用libavformat库(含分流器)来读取输入文件并获得含有他们编码信息的数据包。当有多个输入文件, ffmpeg将通过跟踪最小的时间戳来试图在所有活跃的输入流间同步。编码的数据包然后被传递到解码器(除非复制音频流被选择用于流,见进一步的说明)。解码器产生的未压缩的帧(原始视频/ PCM音频/ …),它可以进一步通过过滤器进行处理(见下一节)。通过过滤器后,这些帧被传递到编码器,编码器将其编码并输出编码后的数据包。最后,这些将被传输给混合器以将编码数据写入到输出文件。

3.1 过滤器

在编码之前, ffmpeg可以使用libavfilter库中的过滤处理原始的音频和视频帧。几个连接的过滤器可以形成一个过滤器组(filtergraphs)。 ffmpeg有两种filtergraphs:简单和复杂。

3.1.1 简单filtergraphs

简单filtergraphs是那些具有相同的类型且正好一个输入和输出的过滤器组。另外,在上图中,他们可以由简单地在解码和编码之间插入附加步骤来表示:

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

简单filtergraphs配置了每个流的筛选器选项(与视频和音频分别-vf和-af别名)。一个简单的FilterGraph动态视频可以看一下这样的例子:

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

需要注意的是一些过滤改变帧属性而不是画面的内容。例如,在上例中,fps改变帧的数量,但不触及帧的内容。又如setpts过滤,其仅设置时间戳而保持帧不变。

3.1.2 复杂filtergraphs

复杂filtergraphs是那些不能被描述为简单的线性处理链的过滤器组。例如,当过滤器组具有多个输入和/或输出,或当输出流的类型是不同于输入。它们可以被表示为以下图:

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

复杂filtergraphs可使用-filter_complex选项配置。注意,此选项是全局性的,因为复杂FilterGraph,就其本质,不能明确地与单个流或文件相关联。

-lavfi选项相当于-filter_complex。

一个复杂FilterGraph动态的简单的例子是在overlay过滤器,它具有两个视频输入和一个视频输出,含有一个视频重叠在另一个的上面。其对应的音频过滤器是amix。

3.2 流复制

流复制是通过添加copy选项到-codec选项完成的。它使ffmpeg对指定的流忽略解码和编码步骤,所以它只能混合和拆包。它用于改变所述容器的格式或修改容器级别的元数据是有用的。在这种情况下,可以简化为这样:

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

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