ffmpeg
的每个转换过程像下图描述的程序
_______ ______________ | | | | | input | demuxer | encoded data | decoder | file | ---------> | packets | -----+ |_______| |______________| | v _________ | | | decoded | | frames | |_________| ________ ______________ | | | | | | | output | <-------- | encoded data | <----+ | file | muxer | packets | encoder |________| |______________|
ffmpeg
调用libavformat
库(含分离器)读取输入文件,分离出各类编码的数据包(流),当有多个输入文件时,ffmpeg
试图跟踪最低时间戳实现任意输入流同步。编码数据包(除非是指定为流式拷贝,相关内容请参考特性描述对流式拷贝的说明)通过解码器解码出非压缩的数据帧(raw视频/PCM格式音频...),这些数据帧可以被滤镜进一步处理(下面会讲到)。经过滤镜处理的数据被重新编码为新的数据包(流),然后经过混合器混合(例如按一定顺序和比例把音频数据包和视频数据包交叉组合),写入到输出文件。
在编码前,ffmpeg
可以对raw(真实/原)音频和视频使用libavfilter
库中的滤镜进行处理。多个滤镜可以组成滤镜链图(滤镜链图filtergraphs )。在ffmpeg
看来只有2种滤镜:简单滤镜,复合滤镜。
简单滤镜就是只有1个输入和输出的滤镜,滤镜两边的数据都是同一类型的,可以理解为在非压缩数据帧到再次编码前简单附加了一步:
_________ ______________ | | | | | decoded | | encoded data | | frames |\ _ | packets | |_________| \ /||______________| \ __________ / simple _\|| | / encoder filtergraph | filtered |/ | frames | |__________|
简单滤镜一般用于配置每个流 -filter 选项(-vf 和 -af 分别对应视频和音频)。一个最简单的视频滤镜如下:
_______ _____________ _______ ________ | | | | | | | | | input | ---> | deinterlace | ---> | scale | ---> | output | |_______| |_____________| |_______| |________|
注意一些滤镜改变帧属性而不是帧内容。例如前面提到的fps滤镜就只是引起帧率的变化,但不处理帧内容,另外一个例子是setpts则仅仅设置时间戳,通过滤镜的帧内容完全不变化。
复合滤镜是那些不能简单描述为一个线性处理过程应用到一个流的情况,例如当过程中有多个输入和/或输出,或者输出流类型不同于输入时,示意图如下:
_________ | | | input 0 |\ __________ |_________| \ | | \ _________ /| output 0 | \ | | / |__________| _________ \| complex | / | | | |/ | input 1 |---->| filter |\ |_________| | | \ __________ /| graph | \ | | / | | \| output 1 | _________ / |_________| |__________| | | / | input 2 |/ |_________|
复合滤镜由-filter_complex
选项进行设定。注意这是一个全局选项,因为一个复合滤镜必然是不能只关联到一个单一流或者文件的。-lavfi
选项等效于-filter_complex
一个复合滤镜的简单例子就是overlay
滤镜,它从两路输入中,把一个视频叠加到一个输出上。对应的类似音频滤镜是amix
。
流拷贝(Stream copy)是一种对指定流数据仅仅进行复制的拷贝(copy)
模式。这种情况下ffmpeg
不会对指定流进行解码和编码步骤,而仅仅是分离和混合数据包。这种模式常用于文件包装格式的转换或者修改部分元数据信息,这个过程简单图示如下:
_______ ______________ ________ | | | | | | | input | demuxer | encoded data | muxer | output | | file | ---------> | packets | -------> | file | |_______| |______________| |________|
因为这种模式下不存在解码和编码过程,所以也特别快,而且不会造成新的质量损失。然而这也使得这样的模式不能适合很多工作需求,例如这个模式下不能使用大量的滤镜了,因为滤镜仅能对未压缩(编码)的数据进行处理。