FFmpeg系列-2-命令行工具之FFmpeg

FFmpeg是一个强大的音视频转换工具,能进行流拷贝、过滤和格式转换。本文详细介绍了FFmpeg的过滤功能,包括简单过滤图和复杂过滤图的使用,以及流选择和选项配置,帮助用户理解和掌握FFmpeg的命令行操作。
摘要由CSDN通过智能技术生成

目录 | TABLE OF CONTENT



注意:为了避免专有名词翻译带来的混淆,直接使用专有名词原语言。你应该在理解其原理的基础之上来处理这些专有名词,而不是为了翻译。

1. 概述

ffmpeg是ffmpeg项目下的一个命令行工具,它是一个非常快速的音视频转换在工具,也可以从现场的音视频源获取(捕捉音视频源)。它可以在任意采样率之间进行转换,并使用高质量的多相过滤器即时调整视频大小。

  ffmpeg通过指定-i选项可以从任意数量的输入”文件”中读取数据(这些可以是常规文件、命名管道文件、网络流、捕获设备等),并写入任意数量的输出”文件”,其中输出由一个纯粹的输出URL指定,任何在命令行中不能被解释为选项的内容都被认为是一个输出URL。

  原则上,每个输入或者输出URL都能够包含不同类型的任意数量的流(视频/音频/字幕/附件/数据)。流的数量和(或者)类型可能受到容器格式1的限制。选择哪个流从哪个输入到哪个输出操作是自动完成的,我们也可以使用-map选项来指定(具体请查看stream selection 章节)。

  为了在选项中引用输入文件,你必须使用索引(索引从0开始)。比如:第一个输入文件是0,第二个是1,等等

  类似地,文件中的流由它们的索引引用。比如:2:3 就表示引用第三个文件中的第四个流。n:m的形式其实可以简单地看作:n代表文件索引,m代表流的索引。(该知识会在后续章节详细讲解)

  作为一个基本的原则,在FFmpeg中,选项被应用于下一个指定的文件。因此,顺序非常重要,并且你可以在命令行下多次使用相同的选项。然后每一个事件被应用于下一个输入或者输出文件。除了这个规则之外的选项被做为全局选项,应当首先指定。

  不要混淆了输入和输出文件,首先被指定的一定是输入文件,然后才是输出文件。同样,也别混淆了属于每一个文件的选项,所有的选项被应用于下一个输入或者输出文件,并在文件之间复位。

  例如:

  设置输出文件的比特率为64 kbit/s2

ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi

  强制输出文件的帧数率3为24fps

ffmpeg -i input.avi -r 24 output.avi

  强制输入文件(仅仅适用于原始格式)的帧数率为1fps,强制输出文件的帧数率为24fps。

ffmpeg -r 1 -i input.m2v -r 24 output.avi

注意:有些格式的选项可能要求输入文件是原始的,比如要更改输入文件的帧数率的时候,有些容器格式协议难以或者不支持该操作

2. 详细说明

  在FFmpeg中,每一个输出的转码过程可以用如下图来描述:

  trancoding_process.png

  简单地讲,转码就是将数据从一种格式转换为另一种格式的过程。

  ffmpeg调用libavformat库(包含多路解复用器[^4])来读取输入文件,并从中获取包含编码数据的数据包。当有多个输入文件时,ffmpeg尝试在任何活动的输入流上通过跟踪最低时间戳来保持同步。然后将编码的数据包传递给解码器。解码器会产生未压缩的数据帧(原始的video/PCM、audio/…),随后被过滤后进一步处理。过滤之后,数据帧被传递给编码器,编码器将其编码,然后输出编码包。最终这些编码好的包被传递给复用器[^5],复用器将编码包写入输出文件。

  这里简单解释一下复用器和解复用器。视频文件实际上类似于zip文件,它们是由多个不同类型的数据文件组成的,其中包含元数据、视频轨道、音频轨道、字幕数据等,各个数据还具备自己的元数据,因此,这些数据文件会通过一个叫做复用器的机制按照一定的标准组合成一个文件。相反,解复用器就是将文件还原为多个数据文件的机制,二者是相反的过程,由于标准的存在,二者是可逆的操作。被还原成的数据文件(如数据帧、音频等)叫做原始文件。

2.1. 过滤(filtering)

  在编码之前,ffmpeg可以利用libavfilter库中的过滤器来处理原始的视频和音频数据帧(这个过程称之为过滤,在最终输出文件之前,对各个产出的数据进行处理,并且这个过程是链式的,想象一个流水线作业,多个过滤器就在该流水线中)。因此,多个过滤链就形成了一个过滤图。ffmpeg可以区分两种过滤器图类型:简单类型(simple filtergraphs)和复合类型(complex filtergraphs)。

通俗解释小贴士:filter主要处理音视频数据的各种特性,诸如视频大小伸缩、添加水印、添加logo、去除logo等。这些操作会在产生最终输出文件的过程中利用过滤器来注入,因此,形象的表示为“过滤”。虽然在命令行中一串指令即可完成需要的输出文件,但是ffmpeg底层是通过libavfilter库来对该过程进行过滤处理。

2.1.1. 简单过滤图(以下使用simple filtergraphs)

  simple filtergraphs(简单过滤图)只有一个相同类型的输入和输出。可以通过简单地在编码和解码之间插入一个步骤来表示,如下图:

  simple-filtergraphs.png

  simple filtergraphs(简单过滤图)通过使用-vf或者-af别名选项来指定,-vf用于视频选项,展开vf为video filter,同理-af为audio filter。

  由此可见,过滤操作就是在输入和输出之间插入的过程,这个过程可以对数据帧做调整,然后再次按照容器格式标准编码进行输出。下图是一个简单的对视频进行伸缩的过程:

  scale.png

注意:有些过滤器会改变帧的属性,但是不会改变帧的内容,比如fps过滤器,它改变了帧数,却不改变帧内容。

小贴士:simple filtergraphs是只有一个输入和输出的过滤图。

2.1.2. 复杂过滤图(complex filtergraphs)

  复杂过滤图在一个流中,不能描述为一个简单的过滤链的线性处理过程。它相比于simple filtergraphs要复杂,不再是单一的输入和输出了,它接受多个输入和产生多个输出。如下图:

  complex-filter-graph.png

  complex filtergraphs(复杂过滤器)使用-filter_complex选项来配置。请注意,这个选项是全局的,因此,它不能与单个的流或者文件相关联。-lavfi选项等同于-filter_complex选项。

小贴士:复杂过滤器由多个输入和输出,通过-filter_complex选项来指定,该选项是全局的,不能和单个的流或者文件关联。

2.2. 流拷贝(Stream copy)

  流复制对于更改容器格式或者修改容器级别的元数据很有用。它使ffmpeg省略了指定流的编码和解码的步骤。其过程如下图:

  stream-copy.png

  因为省略流编码解码过程,该过程将会非常快速,并且没有质量的损失。然而,由于很多其他因素,可能会失败。而且无法提供过滤器,过滤器的过程需要未压缩的数据。

3. 流的选择(Stream selection)

  默认情况下,ffmpeg只包含输入文件中存在的每种类型的一个流(video/audio/subtitle),并将它们添加到每个输出文件。它根据以下标准选择最好的:

  1. 对视频而言,选择最高分辨率的流;
  2. 对音频而言,选择具有最多频道的流;
  3. 对字幕而言,选择第一个字幕流;
  4. 在相同类型的几个流速率相同的情况下,选择索引最低的一个流。

  你可以使用-vn/-an/-sn/-dn选项来禁用这些默认项。对于完全地手动控制,可以使用-map选项来指定,该选项会禁用前面描述的默认项。

4. 选项(Options)

  如果没有另外指定,所有的数值选项接受一个表现为数字的字符串作为输入,后面跟上国际单位制,如“K”、“M”、“G”等单位后缀。比如:1M,1K,1G等,如果在单位前缀中加入了i,ffmpeg将会解释为二进制的倍数,比如1KB=1000Byte,1KiB=1024Byte

  不带参数的选项是布尔选项,这会设置相应的值为true,也可以在参数前面添加no前缀来设置为false,比如“-foo”和“-nofoo”

 4.1. 流说明符

  格式:

stream_index
    #通过索引来匹配,如:-threads:1 4

stream_type[:stream_index]
    # 通过类型/类型+索引来匹配,流类型由v/V(视频)、a/A(音频)、s(字幕)、d(数据)、t(附件)。
    # v匹配所有视频流,V仅仅匹配没有附加图片的视频,如视频缩略图或者封面艺术图片。
    # 如果stream_index被指定了,它将匹配该类型的指定索引的流。否则将匹配所有该类型的流。

p:program_id[:stream_index]
    # 如果指定了stream_index,将会在指定节目id的节目中匹配指定stream_index的流。否则,将匹配所有在该节目中的流。

stream_id 或者 i:stream_id
    # 通过流id匹配流。

m:key[:value]
    # 使用具有指定值的元数据标签键匹配流,如果没有指定值,则匹配包含具有任意值的给定标签的流。

u
    # 匹配可用配置的流,必须定义编解码器,且必须存在的信息,如视频维度、音频采样率。
    # 注意,在ffmpeg中,通过元数据匹配只对输入文件有效。

  一些选项应用于每一个流中,比如比特率和编解码器。流说明符用于精确地指定哪一个指定了选项的流属于谁的。流说明符通常是附加到选项名上的一个字符串,它被一个冒号分割。如下:

-codec:a:1 ac3

  上述指令中包含了a:1流说明符,这会匹配第二个音频流,a代表audio(音频),1代表索引(从0开始)。因此,它将为第二个音频流选择ac3编解码器。

  一个流说明符可以匹配多个流,以便将该选项应用于所有匹配的流。比如:

-b:a 128k

  在上述说明符中匹配了所有的音频流(通过省略数字)。

  一个空的说明符能匹配所有所有流。比如:

-codec copy
# 或者
-codec:copy

  上述指令可以匹配所有流,如流复制一节讲到的,copy不必重新编码。

4.2. 一般选项

  以下选项可以在所有ff*工具中共享(如ffmpeg、ffserver、ffplay、ffprobe)。

-L
    # 显示许可(LICENSE)

-h,-?,-help,--help [arg]
    # 显示帮助信息,如果在后面给定了参数,那么显示该指定参数的特定帮助信息。
    [arg]的值:
        long
            # 打印除基本工具之外的高级工具选项。
        full
            # 打印完整的选项列表,包括共享选项和编解码器、解复用器、复用器、过滤器等的私有选项。
        decoder=decoder_name
            # 打印给定的解码器名的详细信息。可以使用-decoders选项获取所有的解码器。
        encoder=encoder_name
            # 打印给定编码器名称的详细信息。可以使用-encoders选项获取所有的编码器。
        demuxer=demuxer_name
            # 打印给定解复用器的详细信息。使用-formats选项获取所有解复用器和复用器。
        muxer=muxer_name
            # 打印给定复用器的详细信息。使用-formats选项获取所有复用器和解复用器。
        filter=filter_name
            # 打印给定过滤器的详细信息。使用-filters选项获取所有的过滤器。

-version
    # 显示版本号。

-formats
    # 显示可用的容器格式(包括设备)。

-demuxers
    # 显示可用的解复用器。

-muxers
    # 显示可用的复用器。

-devices
    # 显示可用的设备。

-codecs
    # 显示所有libavcodec已知的编解码器。

-decoders
    # 显示可
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值