《ffmpeg basics》中文版 -- 1.FFmpeg 基础

1.FFmpeg 基础

​ 为了更好的使用 FFmpeg 提供的各个组件,我们需要适当了解一些相关的基本概念和特征。如果初学者觉得本节的内容过于名词化,且不太了解其所描述的内容,那么可以先去阅读下一章节,然后再回来学习这一节。

FFmpeg介绍

​ FFmpeg是一个用于处理多媒体的开源项目,是响应GNU工程而发布的自由软件。项目中最受欢迎的成果就是名为ffmpeg的一个命令行工具,它主要用于视频和音频的编码和解码,其主要特点是运行速度快,输出质量高以及文件尺寸小。FFmpeg中的“FF”表示多媒体播放器上的快进按钮(Fast Forward),“mpeg”则是Moving Picture Experts Group的缩写,其意为:运动图像专家组。FFmpeg 的 logo 图标则是一个Z字走样的锯齿形图样,也就是一个8x8方格图样的熵编码特征。

译者注:多媒体(Multimedia)是为了人类与外部世界交往方便而开发出来的适合人类的耳、鼻、嘴和眼等感官的信息交流技术,包括但不限于图片,文本,音频,视频,ppt等,在这里特指音频和视频。

在这里插入图片描述

FFmpeg命令行工具

ffmpeg 高效的音视频编解码器
ffplay 媒体播放器
ffprobe 用于显示媒体文件的特征信息
ffserver 使用HTTP和RTSP协议的流媒体广播服务器

FFmpeg软件库

libavcodec 多媒体格式编解码器相关软件库
libavdevice 设备相关软件库
libavfilter 过滤器相关的软件库
libavformat 媒体格式相关的软件库
libavutil 各种额外工具相关的软件库
libpostproc 用于后期处理的软件库
libswresample 用于音频重采样的软件库
libswscale 用于媒体缩放的软件库

​ 以上全部组件都是由C语言编写的。其源码可在多个操作系统上编译,如Linux/Unix、Windows,Mac OS X等。

​ 本书在写作时,是在Windows下完成的,但书中所有的指令和示例都可以在其他操作系统上使用。如果想要了解有哪些选项可以使用,请查阅《索引(Glossary)》一节中的 FFmpeg configuration 条目。

FFmpeg的开发者

如何参与FFmpeg的开发

FFmpeg的下载

​ 一般我们主要从如下地址下载:

http://ffmpeg.org/download.html

​ Windows的用户可以从如下地址下载二进制文件(推荐使用static静态构建的版本):

http://ffmpeg.zeranoe.com/builds

​ 许多Linux发行版已经安装了FFmpeg工具,如果没有,也可以在该系统上编译FFmpeg。OS X系统的情况与之类似,此外OS X二进制文件可以从如下地址下载:

http://www.evermeet.cx/ffmpeg or http://ffmpegmac.net

命令行语法

​ ffmpeg 命令行工具的语法相对简单,实际使用时最重要的是在正确的位置上输入所需的参数,不要混淆多个输入和输出之间的 option (开关,选项)。ffmpeg命令的一般结构如下,其中global options参数影响所有的输入和输出项:

在这里插入图片描述

​ 上图中,蓝色的部分是必须有的,也就是说ffmpeg命令中最少也需要一个输入和一个输出。而绿色的部分则是可选的,比如输入项option,输出项option,以及更多的输入输出项等。而斜体的部分表示输入输出项,在实际使用时要用实际的多媒体数据代替,如文件、管道、网络数据流、抓取设备(如相机、摄像头)等。

Windows下的cmd界面(命令提示符界面)及其替代工具

命令行程序自然要在cmd界面下运行,当然如果觉得cmd界面太过简陋,那么可以使用类似的第三方工具,本质上都是一样的。

环境变量设置

将 FFmpeg 命令行工具所在的目录添加到环境变量中,这样在其他目录下也可以通过命令行调用这些程序。

重命名为缩写形式

如果觉得 ffmpeg 等常用的名字过长,可以为它们重命名为更简单的名称。在Windows下,使用 ren 命令完成,其他 OS 请自行查询。

显示输出预览

​ 在各种视频测试中,我们可以直接将命令的输出结果显示在屏幕上,而不是将其保存成文件然后在媒体播放器中浏览这个文件,这样可以节省大量的时间。

使用ffplay预览

​ 我们可以轻易地使用ffmpeg命令创建一个输出文件:
在这里插入图片描述
​ 但我们可以通过改用ffplay来直接显示命令行的输出,其效果和将输出保存成文件再显示是一样的,但更为简单和省时:
在这里插入图片描述

使用SDL输出设备预览

​ 这种预览效果是通过使用SDL(Simple DirectMedia Layer)输出设备生成的,其详细信息如下:

在这里插入图片描述

输出设备:sdl
描述 可以在SDL窗口中显示视频流,需提前安装libsdl库
语法 [-icon_title i_title][-window_size w_size][-window_title w_title] -f sdl output
sdl相关的option
icon_title 指定SDL窗口iconified时的标题,默认为window_title属性的值
window_size 指定SDL窗口的尺寸,宽度x高度或者 w x h,默认为输入视频的尺寸
window_title 指定SDL窗口的标题,默认为SDL输出设备要显示的文件的名称

​ iconified:简单来说,就是指窗口最小化到任务栏中对应的小图标的过程

​ 请注意,SDL设备仅可以播放yuv420p像素格式的视频流,当视频流的格式不是yuv420p时,我们必须使用 -pix_fmt选项强制转化为yuv420p像素格式播放,否则就会发生错误:

在这里插入图片描述

译者注:预览有两种方法:使用 ffplay 代替 ffmpeg ,从而直接显示输出;仍旧使用 ffmpeg ,但可以使用 SDL 输出设备来直接显示输出。

译者注:ffmpeg 需要指定输入和输出,也就是说它需要明确数据从什么地方来,又到哪里去,如我们之前所说,它们可以是文件、管道、网络数据流、抓取设备(如相机、摄像头)等。而 ffplay 的目的是播放,因此数据的去处是明确的,只需要指定输入即可【预览方法1】。而当 ffmpeg 明确指定数据输出到一个输出设备 SDL,而不是一个文件,那么 SDL 就替代了 ffplay 的作用【预览方法2】。因此,这里的命令并不是什么特例,而是规则之内的非常自然的产物,只不过用途特殊特意指出来而已。

译者注:rgbtestsrc 是一个 source:源,而source则是特殊的 filter。filter ,翻译为过滤器,滤镜等,它用于将输入的数据做一定的修改,然后输出,可以将它视为一个功能块。而 source 是特殊的 filter,如 rgbtestsrc 不需要输入,但却有输出,如上图所示的红绿蓝三色图片就是它的输出。ffmpeg 中内置了不少的 source,由于输出数据的不同,分为 视频源 和 音频源 。

译者注:输入如果是一个文件,仅需用 -i 选项指定,如果是特殊的 视频源 或者 音频源(它们本质上是一个 filter),则需使用 Lavfi 来将其(确切的说是 filtergraphs 的输出)转化成一个输入。Lavfi的作用就是将一个 filtergraphs 的输出转化为一个输入,因此称为虚拟输入设备。

译者注:-f 选项常用于指定媒体的封装格式,如 mp4,avi等,但也可以用于一些特殊的设备,如这里的 sdl 和 lavfi。

在FFmpeg中可用的SI prefixes

​ SI prefixes:标准国际单位制词头,如K代表10的3次方,M代表10的6次方,G代表10的9次方等。

​ ffmpeg命令中,有一部分option的值是数字,而在指明数字值时,就可以使用SI prefixes以简化形式。下面的几个命令都指定了每秒1.5M的比特率,它们的形式虽然不同,但效果是一样的:

在这里插入图片描述

​ 请注意,在FFmpeg文档中SI prefixes被称为postfixes(后缀,词尾),这是因为它们必须紧紧跟随在数字后面。

​ 除了上述后缀外,B也可以用作数字的后缀,当使用它时,表示将数字乘以8倍,换一种说法就是它表示计算机中内存的基本单位byte(一个字节等于8个比特,是内存的基本单位)。B可以和其他后缀结合,从而形成如KB,MB等新的形式。例如,我们制定输出文件的最大尺寸为10M:
在这里插入图片描述

ffmpeg转码处理流程

​ 在执行ffmpeg命令时,ffmpeg程序会将命令中使用 -i 选项指定的多个输入项的内容读入内存中,然后按照输入的选项值或者默认的选项值对其进行处理,最后将结果写入到指定的多个输出中。输入输出项,都表示一个多媒体数据流,如文件、管道、网络数据流、抓取设备(如相机、摄像头)等。

​ 转码处理流程如下:首先,ffmpeg会调用libavformat库中的demuxers来读取输入项,然后从demuxers获取未解码数据的package。如果有多个输入,ffmpeg可以通过在所有活跃的(active)输入流上追踪最低时间戳来保持他们同步。接着,decoder会处理未解码的package,生成解压缩后的frame,再通过可选的filtering操作后,frame会被发送给encoder。Encoder会将frame转化成新的编码package,然后将该package发送给muxer,muxer会将其写入到输出项中。

​ demuxer:解封装,将保存在文件中的数据按照对应的格式,解析为一个个编码帧数据包

​ decoder:解码,将一个已编码的帧数据包还原为一个帧

​ frame:表示视频中的一个画面,视频就是由一连串的画面组成的

​ encoder:编码,将一个帧,按照某种方式(格式:format)保存为一个数据包

​ muxer:封装,将视频的全部编码好的帧数据包,以及额外的元数据等封装为一个实际的文件,如mp4,avi等,格式不同,其内的数据结构不同

​ demuxer的直接翻译是:分流器或解复用器,就是将多个并行的数据流拆分开,muxer则正好相反,这里并行的是视频数据流,音频数据流,字幕数据流等。encoder和decoder则称为编解码,简单来说,就是将人类可见可知的帧(图片)按照某种方式省时省空间的保存(编码)并将其还原为图片(解码)的概念,中间涉及到如何保存图片,如何压缩数据等。

​ FFmpeg处理流程中,最重要的部分就是filter,它可以被组织为两种方式:filterchains和filtergraphs。其中,filtergraphs可以很简单,也可以变得很复杂。Filtering流程处在解码源数据和编码输出中间。整体的转码处理流程如下图所示:

在这里插入图片描述

Filters,filterchains和filtergraphs

​ filter:过滤器,滤镜 filterchains:过滤器链,滤镜链 filtergraphs:过滤器图,滤镜图

​ 简单来说,这三者就是 点 ,点穿起来的线,和线交汇而成的图的关系。filter,虽然被译为过滤器,但它实际是用来修改输入数据的,可增,可删,可改,而非单一的过滤。当然过滤也是修改的一种。

​ 在多媒体处理中,术语filter的含义是:在输入数据被编码为输出文件之前,可以修改输入项数据的一个软件工具。Filter可以分为audio filters和video filters(详情请查看《索引(Glossary)》一节中的filter关键字)。FFmpeg内置了很多filter,它们可以通过多种方式组合使用。在命令行中,我们可以使用相关语法指示解码后的frame从一个filter移动到另一个filter。这简化了媒体处理,因为多次使用有损格式对媒体流进行解码和编码处理会降低媒体的整体质量。FFmpeg中,Filtering API是放置在libavfilter库中的,它可以使filter处理多个输入和输出。当我们要在命令行中使用filters时,其参数应该放在输入项和输出项之间,其中 -vf 选项表示 video filters,-af 选项表示audio filters。例如,以下命令使用transpose filter(它是一个video filters,将在第7章节进行描述)生成了一个90度顺时针旋转的测试图:

在这里插入图片描述

​ 下面的命令使用atempo(audio filter)将输入的audio播放速度减少到了原来的80%:

在这里插入图片描述
在这里插入图片描述

​ filterchain是由多个用逗号分隔的filter组成的,而filtergraph则是由多个用分号分隔的filterchain组成。filterchain中如果有空格,那么应该使用双引号将整个filterchain括起来,这表示它们是一个整体。在filtergraph中,我们可以将某个filterchain的输出流使用一个link label(链接标签)来标识,那么在后续的filtergraphs中,我们就可以使用这个link label来表示该输出流。例如,我们使用了hqdn3d filter对原视频进行降噪处理,现在想要比较原视频和降噪后的结果,如果我们不用filtergraphs,那么我们至少需要两条命令:
在这里插入图片描述
​ 而使用了filtergraphs和link label,则就用一条命令完成上述任务:
在这里插入图片描述
​ split是一个filter,它将输入分裂为两部分,我们将这两个输出分别定义link label,为[a]和[b]。然后在第二个filterchain中,[a]作为输入使用,通过pad filter进行了填充操作,将输出定义为[A]。第三个filterchain中,[b]作为输入,通过hqdn3d进行降噪处理,将其输出定义为[B]。在最后一个filterchain中,[A][B]作为输入,通过overlay filter做最后的比较。

​ 另一个例子如下图所示:
在这里插入图片描述

媒体流的选择

​ 如AVI,Matroska,MP4等多媒体格式,它们会包含不同类型的多个数据流。在FFmpeg中,我们可以识别5中类型的数据流:音频(audio,简称a),附属项(attachment,简称t),数据(data,简称d),字幕(subtitle,简称s),视频(video,简称v)。

​ 我们可以使用 -map 选项选择数据流,指定流的说明符格式如下:

在这里插入图片描述

​ file_number和stream_number也可以用file_index和stream_index代替,它们都从0开始计数,即第一个标识为0,第二个标识为1,依次类推。下面是一些特殊的流说明符:

  • -map 0 : 表示选择第一个输入文件中所有类型的所有流
  • -map i:v : 其中,i表示文件的下标,即file_number,v表示选择该文件的所有视频流。v可以被替换为a、s等,表示选择文件的所有音频流或者字幕流。
  • 特殊选项 -an,-vn,-sn 分别表示排除所有的音频流,视频流或者字幕流

​ 如果输入项(如多个文件)中各类型的流不仅仅只有一个,且也没有使用 -map 选项指定要选择的流,那么此时每个类型的流仅会选取一个(并非第一个)。例如,如果文件中包含2个视频流,那么会选择高分辨率的那个,对于多个音频流,那么会选择多通道的那个,具体细节如下图所示:

在这里插入图片描述

​ 注:请详细阅读上图中的示例。

​ 流说明符除了可以在 -map 选项中使用之外,它还可以用在其他选项中,其形式也可以有如下变化:

在这里插入图片描述

​ 例如,我们使用 -b 选项指定视频和音频的比特率,其命令如下:

在这里插入图片描述

Lavfi虚拟设备

​ 在之前的内容中,我们使用过 -f lavfi 字样的命令,其中lavfi是libavfilter虚拟输入设备的名称,其具体描述如下:

在这里插入图片描述

​ Lavfi 常用于测试时使用,例如显示 SMPTE Bar:

ffplay -f lavfi -i smptebars

​ 其他常用的源是 color 源,可以用下面的命令显示:

ffplay -f lavfi -i color=c=blue

​ 译者注:如 color 和 smptebars 等,都是一个 filter ,而 Lavfi 的作用就是将这个 filter 的输出转变为一个输入,这样就可以供 ffplay 和 ffmpeg 使用了。当然这里的 filter 都是特殊的 filter,被称为 视频源 或者 音频源 ,它们都会产生特定的输出以供用户使用。如 color 就会输出纯色背景的静态图片数据。

颜色名

​ 在有些命令中,我们需要指定自己想要的颜色。有四种可以表示颜色的方法:

  • W3C为部分颜色定义了标准名称,我们可以使用这些名称来标识相关颜色,如white,black,red等就采用了这种方法
  • 使用16进制的数字来标识一个颜色,形如0xRRGGBB或0xRRGGBBAA,其中RR表示红色通道,GG表示绿色通道,BB表示蓝色通道,AA表示alpha通道,其取值范围为00~FF,大小写均可。
  • 和上述方法相同,仅仅表现形式不同,需将0x替换为#即可。
  • 可以使用random表示一个颜色,它表示随机颜色,由计算机临时生成。

注意:除了最后一种方式外,其他表示方法在计算机中是通用的,如有疑虑,可自行查询。

需要指定自己想要的颜色。有四种可以表示颜色的方法:

  • W3C为部分颜色定义了标准名称,我们可以使用这些名称来标识相关颜色,如white,black,red等就采用了这种方法
  • 使用16进制的数字来标识一个颜色,形如0xRRGGBB或0xRRGGBBAA,其中RR表示红色通道,GG表示绿色通道,BB表示蓝色通道,AA表示alpha通道,其取值范围为00~FF,大小写均可。
  • 和上述方法相同,仅仅表现形式不同,需将0x替换为#即可。
  • 可以使用random表示一个颜色,它表示随机颜色,由计算机临时生成。

注意:除了最后一种方式外,其他表示方法在计算机中是通用的,如有疑虑,可自行查询。

H&A
发布了7 篇原创文章 · 获赞 4 · 访问量 832

猜你喜欢

转载自blog.csdn.net/qq_34305316/article/details/102760106