FFmpeg使用基础

版权声明:本文为原创文章,转载请注明出处 https://blog.csdn.net/leisure_chn/article/details/87645411

本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10297002.html

本文介绍FFmpeg最基础的概念,了解FFmpeg的简单使用,帮助理解FFmpeg工程源码。内容主要节选和翻译自书籍《FFmpeg Basics》及官网文档“Documentation-ffmpeg”。

1. 概述

FFmpeg是一款用于多媒体处理的自由软件工程,基于GPL许可证发布。FFmpeg提供的最核心的命令行工具是ffmpegffmpeg命令行工具的主要特征是输出快速、高品质、文件尺寸小。“FFmpeg”中“FF”表示“Fast Forward”,“mpeg”表示“Moving Pictures Experts Group”。

FFmpeg提供如下四个命令行工具:
ffmpeg 音视频编码器/解码器
ffplay 媒体播放器
ffprobe 显示媒体文件信息
ffserver 多媒体流广播服务器,使用HTTP和RTSP协议。FFmpeg 4.1版本已经删除ffserver,新的替代者还未添加进来。

FFmpeg提供如下软件开发库:
libavcodec software library for various multimedia codecs
libavdevice software library for devices
libavfilter software library containing filters
libavformat software library for media formats
libavutil software library containing various utilities
libpostproc software library for post processing
libswresample software library for audio resampling
libswscale software library for media scaling

2. 命令行格式

命令行基本格式为:
ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...
格式分解如下:

ffmpeg
    global_options
        input1_options -i input1
        input2_options -i input2
        ...
            output1_options output1
            output2_options output2
            ...

ffmpeg读取任意数量的输入“文件”(可以是常规文件、管道、网络流、录制设备等,由“-i”选项指定),写入任意数量的输出“文件”。命令行中无法被解释为选项(option)的任何元素都会被当作输出文件。

每个输入或输出文件,原则上都可以包含任意数量的流。FFmpeg中流的类型有五种:视频(video)、音频(audio)、字幕(subtitle)、附加数据(attachment)、普通数据(data)。文件中流的数量和(或)流类型种数的极限值由文件封装格式决定。选择哪一路输入的哪一路流输出到哪一路输出,这个选择过程既可以由FFmpeg自动完成,也可以通过“-map”选项指定(后续“Stream selection”章节会深入描述)。

注:关于附加数据(attachment)和普通数据(data)的说明如下:

Attachments could be liner notes, related images, metadata files, fonts, etc.
Data tracks would be for things like timecode, navigation items, cmml, streaming tracks.
参考资料[3] “What are the the data and attachment stream type?

命令行中的输入文件及输入文件中的流都可以通过对应的索引引用,文件、流的索引都是从0开始。例如,2:3表示第3个输入文件中的第4个流。(后续“Stream specifiers”章节会详细描述)。

一个通用规则是:输入/输出选项(options)作用于跟随此选项后的第一个文件。因此,顺序很重要,并且可以在命令行中多次指定同一选项。每个选项仅作用于离此选项最近的下一输入或输出文件。全局选项不受此规则限制。

不要把输入文件和输出文件混在一起———应该先将输入文件写完,再写输出文件。也不要把不同文件的选项混在一起,各选项仅对其下一输入或输出文件有效,一个选项不能跨越一个文件传递到后续文件。

举几个命令行例子:

  • 设置输出文件码率为64kbit/s:
    ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi
    其中“-b:v 64k”和“-bufsize 64k”是输出选项。
  • 强制输入文件帧率(仅对raw格式有效)是1fps,输出文件帧率为24fps:
    ffmpeg -r 1 -i input.m2v -r 24 output.avi
    其中“-r 1”是输入选项,“-r 24”是输出选项。
  • 转封装:将avi格式转为mp4格式,并将视频缩放为vga分辨率
    ffmpeg -y -i video.avi -s vga video.mp4
    其中“-y”是全局选项,“-s vga”是输出选项。

3. 转码过程

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

ffmpeg调用libavformat库(包含解复用器demuxer),从输入文件中读取到包含编码数据的包(packet)。如果有多个输入文件,ffmpeg尝试追踪多个有效输入流的最小时间戳(timestamp),用这种方式实现多个输入文件的同步。

然后编码包(packet)被传递到解码器(decoder),解码器解码后生成原始帧(frame),原始帧可以被滤镜(filter)处理(图中未画滤镜),经滤镜处理后的帧送给编码器,编码器将之编码后输出编码包。最终,由复用器(muxex)将编码包写入特定封装格式的输出文件。

4. 滤镜

在多媒体处理中,术语**滤镜(filter)**指的是修改未编码的原始音视频数据帧的一种软件工具。滤镜分为音频滤镜和视频滤镜。FFmpeg提供了很多内置滤镜,可以用很多方式将这些滤镜组合使用。通过一些复杂指令,可以将解码后的帧从一个滤镜引向另一个滤镜。这简化了媒体处理,因为有损编解码器对媒体流进行多次解码和编码操作会降低总体质量,而引入滤镜后,不需要多次解码编码操作,相关处理可以使用多个滤镜完成,而滤镜处理的是原始数据,不会造成数据损伤。

4.1 滤镜的使用

FFmpeg的libavfilter库提供了滤镜API,支持多路输入和多路输出。

滤镜(filter)的语法为:
[input_link_lable1][input_link_lable2]... filter_name=parameters [output_link_lable1][output_link_lable12]...
上述语法中,输入输出都有连接标号(link lable),连接符号是可选项,输入连接标号表示滤镜的输入,输出连接标号表示滤镜的输出。连接标号通常用在滤镜图中,通常前一个滤镜的输出标号会作为后一个滤镜的输入标号,通过同名的标号将滤镜及滤镜链连接起来。连接标号的用法参考4.3.2节示例。

示例1:
ffplay -f lavfi -i testsrc -vf transpose=1
“-vf”(同“-filter:v”)选项表示使用视频滤镜,“transpose=1”是滤镜,此行命令表示使用transpose视频滤镜产生一个顺时针旋转90度的测试图案

示例2:
ffmpeg -i input.mp3 -af atempo=0.8 output.mp3
“-af”(同“-filter:a”)选项表示使用音频滤镜,“atempo=0.8”是滤镜,此行命令表示使用atempo音频滤镜将输入音频速率降低到80%后写入输出文件

注意:有些滤镜只会修改帧属性而不会修改帧内容。例如,fps滤镜,setpts滤镜等。

4.2 滤镜链的使用

**滤镜链(filterchain)**是以逗号分隔的滤镜(filter)序列,语法如下:
filter1,fiter2,filter3,...,filterN-2,filterN-1,filterN
滤镜链中如果有空格,需要将滤镜链用双引号括起来,因为命令行中空格是分隔参数用的。

示例1:
ffmpeg -i input.mpg -vf hqdn3d,pad=2*iw output.mp4
“hqdn3d,pad=2iw”是filterchain,第一个filter是“hqdn3d”(降噪);第二个filter是“pad=2iw”(将图像宽度填充到输入宽度的2倍)。此行命令表示,将输入视频经降噪处理后,再填充视频宽度为输入宽度的2倍。

4.3 滤镜图的使用

**滤镜图(filtergraph)**通常是以分号分隔的滤镜链(filterchain)序列。滤镜图分为简单滤镜图和复杂滤镜图。
滤镜图(filtergraph)的语法如下:
filter1;fiter2;filter3;...;filterN-2;filterN-1;filterN

4.3.1 简单滤镜图

简单滤镜图(filtergraph)只能处理单路输入流和单路输出流,而且要求输入和输出具有相同的流类型。
简单滤镜图由-filter选项指定。简单滤镜图示意图如下:

 _______        _____________________        ________
|       |      |                     |      |        |
| input | ---> | simple filter graph | ---> | output |
|_______|      |_____________________|      |________|

4.3.2 复杂滤镜图

复杂滤镜图(filtergraph)用于简单滤镜图处理不了的场合。比如,多路输入流和(或)多路输出流,或者输出流与输入流类型不同。
有些特殊的滤镜(filter)本身就属于复杂滤镜图,用-filter_complex选项或-lavfi选项指定,如overlay滤镜和amix滤镜就是复杂滤镜图。overlay滤镜有两个视频输入和一个视频输出,将两个输入视频混合在一起。而amix滤镜则是将两个输入音频混合在一起。
复杂滤镜图(filtergraph)示意图如下:

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

示例1:
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
上例中"split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2"是复杂滤镜图,由三个滤镜链构成(分号分隔),第二个滤镜链“[tmp] crop=iw:ih/2:0:0, vflip [flip]”由两个滤镜构成(逗号分隔)。第一个滤镜链中:滤镜split产生两个输出[main]和[tmp];第二个滤镜链中:[tmp]作为crop滤镜的输入,[flip]作为vflip滤镜的输出,crop滤镜输出连接到vflip滤镜的输入;第三个滤镜链中:[main]和[flip]作为overlay滤镜的输入。整行命令实现的功能是:将输入分隔为两路,其中一路经过裁剪和垂直翻转后,再与另一路混合,生成输出文件。示意图如下所示:

                [main]
input --> split ---------------------> overlay --> output
            |                             ^
            |[tmp]                  [flip]|
            +-----> crop --> vflip -------+

4.3.3 滤镜图中的连接标号

在滤镜图中可以使用连接标号(link lable),连接标号表示特定滤镜/滤镜链的输入或输出,参4.1节。

例如,我们想要把一个经过降噪处理后的输出文件与输入原文件进行比较,如果不使用带连接标号的滤镜图,我们需要至少两条命令:
ffmpeg -i input.mpg -vf hqdn3d,pad=2*iw output.mp4
ffmpeg -i output.mp4 -i input.mpg -filter_complex overlay=w compare.mp4

如果使用带有连接标号的滤镜图,则一条命令就可以了:
ffplay -i i.mpg -vf split[a][b];[a]pad=2*iw[A];[b]hqdn3d[B];[A][B]overlay=w

4.4 滤镜使用总结

滤镜(广义)通常以滤镜链(filterchain, 以逗号分隔的滤镜序列)和滤镜图(filtergraph, 以分号分隔的滤镜序列)的形式使用。滤镜链由滤镜构成,滤镜图由滤镜链构成,这样可以提供复杂多样的组合方式以应对不同的应用场景。
滤镜(狭义)是滤镜链的简单特例,滤镜链是滤镜图的简单特例。注意这里滤镜(狭义)、滤镜链、滤镜图之间不是继承的关系,而是组合的关系,比如,一个滤镜图可以只包含一个滤镜链,而一个滤镜链也可以只包含一个滤镜,这种特例情况下,一个滤镜图仅由单个滤镜构成。FFmpeg的命令行中,滤镜(广义)的出现形式有滤镜(狭义)、滤镜链、滤镜图三种形式,但滤镜(狭义)和滤镜链可以看作是特殊的滤镜图,因此,为了简便,FFmpeg的命令行中滤镜相关选项,只针对滤镜图(filtergraph)概念,分为如下两类:
针对简单滤镜图的选项:“-vf”等同“-filter:v”,“-af”等同“-filter:a”
针对复杂滤镜图的选项:“-lavfi”等价“-filter_complex”

5. 流拷贝

“-codec copy”可使能流拷贝(stream copy)模式。流拷贝直接将输入流拷贝到输出,仅涉及解复用和复用,不涉及解码和编码,因此也不支持滤镜操作。流拷贝对于修改容器格式或容器级别元数据非常有用。因为不涉及编解码操作,整个过程会非常快。示意图如下所示:

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

6. 流选择

有些容器,如AVI、MP4等,可以包含多种不同类型的流。FFmpeg可以识别5种流类型:音频(audio, a),视频(video, v),字幕(subtitle, s),附加数据(attachment, t)和普通数据(data, d)。
**流选择(stream selection)**是从输入文件中选定某些流进行处理。流选择有两种模式,1) 使用-map选项手动指定要选择的流;2) 无-map选项时由FFmpeg根据相应规则自动选择流。

6.1 流选择自动模式

自动选择模式下,每种类型的流只选择一路,规则如下:
音频流:选择具有最多通道的流,若多个音频流通道数相同且通道数最多,则选第一个
视频流:选择具有最高分辨率的流,若多个视频流分辨率相同且是最高分辨率,则选第一个
字幕流:选择第一个字幕流。注意:字幕流有文本字幕流和图形字幕流,输出格式默认的字幕编码器仅处理其支持的字幕类型

6.2 流选择手动模式

手动选择模式下,要选定的流由-map选项后的流指定符(stream specifer)指定。stream_specifier语法如下:
[-]file_index:stream_type[:stream_index]
-表示排除此流,不带-表示选中此流。文件序号file_index和流序号stream_index都是从0开始计数。

几个特殊的stream_specifier如下:
–map 0 选择所有类型的所有流。
–map i:v 选择文件i中所有的视频流,i:a、i:s等同理。
–map -vn 排除所有视频流,-an、-sn等同理。

示例:
假设ffmpeg命令行如下:
ffmpeg -i file1 -i file2 select_streams output
其中有两个输入文件file1和file2,选择的流位于select_streams
file1的流组成与对应的stream_specifier如下:

file streams            stream_specifier
1st video               0:v:0
2nd video               0:v:1
1st audio               0:a:0
2nd audio               0:a:1
1st subtitle            0:s:0
2nd subtitle            0:s:1
3rd subtitle            0:s:2

file2的流组成与对应的stream_specifier如下:

file streams            stream_specifier
1st video               1:v:0
1st audio               1:a:0
1st subtitle            1:s:0

select_streams各种示例说明如下:
-map 0 -map 1
选择两个文件的所有流

-map 0:s:2 -map 1:v:0 -map 1:a:0
选择file1的3rd字幕流,file2的1st视频流和file2的1st音频流

-map 0 -map 1:s:0 -an
选择file1除音频外的所有流和file2的1st字幕流

-map 0 -map 1 -map -0:v:0 -map -0:a:1
选择除file1的1st视频流和2nd音频流外的所有流,选择file2中的所有流

6.3 stream_specifier

有些选项(比如设置码率、设置编解码器)是针对流的。一个选项具体作用于哪些流,由stream_specifier指定。

stream_specifier附在选项后面,由“:”分隔。例如:-codec:a:1 ac3a:1就是stream_specifier。

stream_specifier可以匹配一路流或多路流,对应的选项可作用于stream_specifier匹配的这些流。一个空的stream_specifier将匹配所有的流。例如:-b:a 128k匹配所有音频流,而-codec copy-codec: copy则匹配所有流。

除上一节所述-map选项外,stream_specifier还可用在很多其他选项中,形式有如下几种:

specifer形式                描述
stream_index                选择索引为stream_index的流
stream_type[:stream_index]  选择类型为stream_type索引为stream_index的流
p:program_id[:stream_index] 选择节目program_id中索引为stream_index的流
stream_id                   选择指定ID的流

例如,使用-b选项设置音频流和视频流的码率:
ffmpeg -i input.mpg -b:a 128k -b:v 1500k output.mp4

6.4 扩展1:复杂滤镜图中的流选择

如果某个复杂filtergraph中的输出流未携带标号,则这些流将被添加到第一个输出文件中。如果封装器格式不支持某种流类型,将会导致致命错误。
如果未使用-map选项,包含这些复杂filtergraph输出流将导致不会对这些流类型启用自动选择。
如果使用了-map选项,除-map选定的流之外,这些filtergraph输出流也会被包含进来。

复杂filtergraph的输出流若带标号,则标号必须被映射一次,且只能被映射一次。

假设有三个输入文件用于示例,其流组成成分如下:

input file 'A.avi'
      stream 0: video 640x360
      stream 1: audio 2 channels

input file 'B.mp4'
      stream 0: video 1920x1080
      stream 1: audio 2 channels
      stream 2: subtitles (text)
      stream 3: audio 5.1 channels
      stream 4: subtitles (text)

input file 'C.mkv'
      stream 0: video 1280x720
      stream 1: audio 2 channels
      stream 2: subtitles (image)

示例1:无标号filtergraph的流选择
ffmpeg -i A.avi -i C.mkv -i B.mp4 -filter_complex "overlay" out1.mp4 out2.srt
-filter_complex选项指定了一个复杂filtergraph,此filtergraph由单个视频滤镜overlay构成。overlay滤镜需要两个视频输入,但此处并未为overlay滤镜指定输入,因此A.avi和C.mkv中头两个有效视频流会被作为overlay滤镜的输入。overlay滤镜输出无标号,因此overlay滤镜的输出会被写入第一个输出文件out1.mp4中。
本来自动选择模式会选中B.mp4中的“stream 0”视频流(最高分辨率真)和B.mp4中的“stream 3”音频流(最多通道数)。但overlay滤镜输出流是视频流,因此,不会对视频流进行自动选择,即不会选择B.mp4中的“stream 0”。
不会选中任何字幕流,因为MP4封装格式未注册默认字幕编码器,用户也未指定字幕编码器,无编码器可用所以不会选择字幕流。

第二个输出文件out2.srt,仅接受文本类型的字幕流。所以,就算C.mkv中的“stream 2"是第一个被找到的字幕流,也会因类型不符合被忽略掉。B.mp4中的“stream 2”会被选中,因为它才是第一个文本字幕流。

示例2:带标号filtergraph的流选择

ffmpeg -i A.avi -i B.mp4 -i C.mkv -filter_complex "[1:v]hue=s=0[outv];overlay;aresample" \
       -map '[outv]' -an        out1.mp4 \
                                out2.mkv \
       -map '[outv]' -map 1:a:0 out3.mkv

上述命令会执行失败,因为filtergraph的输出标号[outv]被映射了两次。此命令不会生成任何输出文件。

ffmpeg -i A.avi -i B.mp4 -i C.mkv -filter_complex "[1:v]hue=s=0[outv];overlay;aresample" \
       -an        out1.mp4 \
                  out2.mkv \
       -map 1:a:0 out3.mkv

上述命令也会执行失败,因为hue滤镜有一个输出标号[outv],但此标号未作任何映射。

正确的命令应该写成下面这样:

ffmpeg -i A.avi -i B.mp4 -i C.mkv -filter_complex "[1:v]hue=s=0,split=2[outv1][outv2];overlay;aresample" \
        -map '[outv1]' -an        out1.mp4 \
                                  out2.mkv \
        -map '[outv2]' -map 1:a:0 out3.mkv

“[1:v]”表示B.mp4中的视频流,B.mp4中的视频流被发送到hub滤镜,hub滤镜的输出被split滤镜拷贝了一份,生成两份输出,两份输出用标号[outv1]和[outv2]表示。

overlay滤镜需要两个视频输入,使用头两个未使用的视频流作输入,即A.avi和C.mkv中的视频流。overlay滤镜输出未带标号,所以overlay滤镜输出被发送到第一个输出文件out1.mp4,有没有-map选项对此无影响。

aresample滤镜使用第一个未使用的音频流(A.avi中的“stream 1”)作为输入。aresample滤镜输出也未带标号,所以avresample滤镜输出也被映射到第一个输出文件out1.mp4。-an选项仅仅抑制了音频流的自动或手动流选择,而不会抑制filtergraph的输出。所以,out1.mp4有三个输入流:1)overlay滤镜输出、2)aresample滤镜输出和3)标号outv1,B.mp4中1)2)排序应在3)之前。

映射到out2.mkv的视频、音频和字幕流由自动选择模式选定。

out3.mkv由hue滤镜输出和B.mp4中的“stream 1”构成。

6.5 扩展2:流处理

流处理(stream handling)和流选择是互不影响的(字幕例外)。流处理通过-codec选项设置,-codec选项针对输出文件中的流。FFmpeg对-codec选项的处理是在流选择(stream selection)过程之后的,因此-codec选项(流处理)不会影响流选择。如果某类型的流未指定-codec选项,将会使用输出文件muxer注册的默认编码器。

上述规则不适用于字幕。如果一个输出文件指定了字幕编码器,那么找到的第一个字幕流(文本字幕或图形字幕)总会被包含进来。FFmpeg不会检查编码器是否能转换选定的流或已转换的流能否被输出格式接受。这通常也适用:当用户手动设置编码器时,流选择过程不能检查编码流是否可以复用到输出文件中。如果编码流不能复用到输出文件,FFmpeg会终止,所有的输出文件处理会失败。

7. 选项

如下内容取自官网文档“Documentation-ffmpeg”第5节

7.1 帮助信息

如下选项适用于ff系列工具:

-h, -?, -help, --help [arg]
    显示帮助信息。可指定一个可选参数,以显示针对此参数的帮助信息。如果不指定参数,仅显示基本选项。

    可用参数如下:

    long
        打印高级选项

    full
        打印所有选项,包括编码器、解码器、解复用器、复用器、滤镜等的共享或私有选项。

    decoder=decoder_name
        打印名为decoder_name的解码器的详细信息。使用-decoders选项可获取解码器列表。

    encoder=encoder_name
        打印名为encoder_name的编码器的详细信息。使用-encoders选项可获取编码器列表。

    demuxer=demuxer_name
        打印名为demuxer_name的解复用器的详细信息。使用-formats选项可获取解复用器和复用器列表。

    muxer=muxer_name
        打印名为muxer_name的复用器的详细信息。使用-formats选项可获取解复用器和复用器列表。

    filter=filter_name
        打印名为filter_name的滤镜的详细信息。使用-filters选项可获取滤镜列表。
        Print detailed information about the filter name filter_name. Use the -filters option to get a list of all filters. 

7.2 通用选项

如下选项适用于ff系列工具:

-L
    显示许可证。

-version
    显示版本。

-formats
    显示可用格式(包含可用设备)。

-demuxers
    显示可用的解复用器。
    Show available demuxers.

-muxers
    显示可用的复用器。

-devices
    显示可用的设备。

-codecs
    显示libavcodec库支持的所有编解码器。
    编解码器(codec)是一种简称,媒体位流格式(media bitstream format)是一种更正式和准确的称法。

-decoders
    显示可用的解码器。

-encoders
    显示可用的编码器。

-bsfs
    显示可用的位流滤镜(bitstream filters)。

-protocols
    显示可用的协议。

-filters
    显示可用的libavfilter滤镜。

-pix_fmts
    显示可用的像素格式。

-sample_fmts
    显示可用的采样格式。

-layouts
    显示声道名称及标准声道布局。

-colors
    显示可识别的颜色名。

7.3 AV选项

这些选项由libavformat、libavdevice及libavcodec库直接提供。使用-help选项(如何查看?)可查看AV选项列表。AV选项有如下两类:
generic:通用选项可用于任意容器、编解码器或设备。容器/设备的通用选项位于AVFormatContext中,编解码器的通用选项位于AVCodecContext中。
private:私有选项仅用于特定的容器、编解码器或设备。私有选项位于选项对应的容器/设备/编解码器中。

例如要在一个默认为ID3v2.4为头的MP3文件中写入ID3v2.3头,需要使用MP3复用器的id3v2_version私有选项:
ffmpeg -i input.flac -id3v2_version 3 out.mp3

所有编解码器AV选项都是针对某路流的,所以AV选项后应跟随stream_specifer。

注意-nooption语法不能被用于布尔型的AV选项,应使用-option 0/-option 1。

7.4 主选项

-f fmt (input/output)
    强制指定输入或输出文件格式。输入文件的格式通常是自动检测得到,而输出文件的格式一般是由文件扩展名猜测得到,所以大部分情况下并不需要此选项。

-i url (input)
    输入文件url。

-y (global)
    静默覆盖输出文件。

-n (global)
    不覆盖输出文件,如果输出文件已存在则立即退出。

-stream_loop number (input)
    设置输入流的循环次数。0表示不循环,-1表示永久循环。

-c[:stream_specifier] codec (input/output,per-stream)
-codec[:stream_specifier] codec (input/output,per-stream)
    作输出选项时用于选择编码器,作输入选项时用于选择解码器,解码器或解码器都是用于一路或多路流的。上述命令语法中codec是解码器/编码器的名字,或者指定为copy,用于表示流不需要重编码。

    例如:
    ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT
    使用libx264编码所有视频流并拷贝所有音频流。

    For each stream, the last matching c option is applied, so
    对每路流来说,最后一个匹配的c选项起作用,所以
    ffmpeg -i INPUT -map 0 -c copy -c:v:1 libx264 -c:a:137 libvorbis OUTPUT
    第2路视频流使用libx264编码,第138路音频流使用libvorbis编码,所有其他流直接拷贝。
    展开说明一下:上述命令行中,有“-c copy”、“-c:v:1 libx264”和“-c:a:137 libvorbis”三个c选项,
    对第138路音频流来说,第一个和第三个选项可匹配,因此起作用的是第三个选项(命令行中最后一个匹配的选项)
    对第2路视频流来说,第一个和第二个选项可匹配,因此起作用的是第二个选项((命令行中最后一个匹配的选项)
    对其他流而言,只能匹配第一个选项

-t duration (input/output)
    作输入选项时,限制输入的时长,即最多只读入duration时长的数据。
    作输出选项时,达到duration时长时就停止写输出。

    duration是时间长度,遵循时长规范,参考“ffmpeg-utils”手册中的“Time duration”章节。
    duration must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.

    -to选项和-t选项是互斥的,-t选项优先。

-to position (input/output)
    到达指定position位置时停止写输出或读输入。position是时间刻度,遵循时长规范,参考“ffmpeg-utils”手册中的“Time duration”章节。

    -to选项和-t选项是互斥的,-t选项优先。

-fs limit_size (output)
    设置文件尺寸限制,单位字节。达到设置值后就不会再写新的数据块了。输出文件尺寸比请求设置的值略大。

-ss position (input/output)
    作输入选项(在-i之前)时,将在输入文件中执行seek操作,seek至目标位置position处。注意在大多数格式中,seek都不精确,ffmpeg会seek至离position最近的seek点。当转码功能和-accurate_seek都使能(默认情况)时,在实际seek点和position间的一小段会被解码,但是会丢弃(如何丢弃?)。在作流拷贝(不需要转码)操作或使用了-noaccurate_seek选项时,这一小段会保留(如何保留?)。

    作输出选项(在输出url之前)时,会对输入一直解码并丢弃,直到到达position位置处。

    position是时间刻度,遵循时长规范,参考“ffmpeg-utils”手册中的“Time duration”章节。

-sseof position (input)
    与-ss选项类似,只不过-ss选项是相对于文件头,而此选项是相对于文件尾。position值是负值,0表示位于文件尾。

-itsoffset offset (input)
    设置输入时间偏移。

    offset遵循时长规范,参考“ffmpeg-utils”手册中的“Time duration”章节。

    输入文件的时间戳会加上offset值,使用相加后的新值作为新的时间戳。offset取正值时表示对应的流将延时offset指定的时长。

-timestamp date (output)
    设置容器中的录制时间戳。

    data遵循日期规范,参考“ffmpeg-utils”手册中的“Date”章节。

-metadata[:metadata_specifier] key=value (output,per-metadata)
    设置一个metedata键/值对。
    一个可选的metadata_specifier可用于设置流、章节或节目的metadata。详情可参考-map_metadata文档。
    此选项会覆盖-map_metadata选项设置的metadata。此选项携带一个空值可以删除metadata。

    例如,设置输出文件的标题:
    ffmpeg -i in.avi -metadata title="my title" out.flv

    设置第一路音频流的语言:
    ffmpeg -i INPUT -metadata:s:a:0 language=eng OUTPUT

......

-dframes number (output)
    设置输出的数据(data类型,与video/audio类型对应)帧的数量。此选项已经过时,等价于-frames:d选项,应使用-frames:d替代此选项。

-frames[:stream_specifier] framecount (output,per-stream)
    设置输出帧的数量。超过framecount帧数时将停止写输出。

7.5 视频选项

-vframes number (output)
    设置输出视频帧数。此选项已经过时,等价于-frames:v,应使用-frames:v替代此选项。

-r[:stream_specifier] fps (input/output,per-stream)
    设置帧率(Hz)。
    作输入选项时,忽略文件中的所有时间戳,生成以fps为帧率的新时间戳。此选项和用于某些输入格式(如image2和v412)的-framerate选项并不一样(在旧的FFmpeg版本中这两个选项是一样的)。如果有疑问,使用-framerate替换-r输入选项。
    作输出选项时,重复或丢弃输入帧以获得fps指定的帧率。

-s[:stream_specifier] size (input/output,per-stream)
    设置帧大小。
    作输入选项时,此选项是video_size私有选项的便捷方式,可被某些解复器识别,用于帧大小未存储在文件中或帧大小可配置的情况,例如原始视频或视频捕获。
    作输出选项时,此选项将在对应滤镜图的末尾插入scale视频滤镜,以缩放视频帧。请直接使用scale滤镜,将scale滤镜插入开头或其他位置,而不要使用此选项。
    The format is ‘wxh’ (default - same as source).
    
-aspect[:stream_specifier] aspect (output,per-stream)
    Set the video display aspect ratio specified by aspect.
    aspect can be a floating point number string, or a string of the form num:den, where num and den are the numerator and denominator of the aspect ratio. For example "4:3", "16:9", "1.3333", and "1.7777" are valid argument values.
    If used together with -vcodec copy, it will affect the aspect ratio stored at container level, but not the aspect ratio stored in encoded frames, if it exists.

-vn (input/output)
    作输入选项时,阻止文件中所有视频流被用于滤镜操作或自动/手动选择进任何输出。本选项禁止所有视频流,-discard选项可单独禁止某一路视频流。
    作输出选项时,禁止视频录制,也就是禁止任何视频流的自动或手动选择。

-vcodec codec (output)
    设置视频编解码器。等价于-codec:v选项。

-pass[:stream_specifier] n (output,per-stream)
    Select the pass number (1 or 2). It is used to do two-pass video encoding. The statistics of the video are recorded in the first pass into a log file (see also the option -passlogfile), and in the second pass that log file is used to generate the video at the exact requested bitrate. On pass 1, you may just deactivate audio and set output to null, examples for Windows and Unix:

    ffmpeg -i foo.mov -c:v libxvid -pass 1 -an -f rawvideo -y NUL
    ffmpeg -i foo.mov -c:v libxvid -pass 1 -an -f rawvideo -y /dev/null

-passlogfile[:stream_specifier] prefix (output,per-stream)
    Set two-pass log file name prefix to prefix, the default file name prefix is “ffmpeg2pass”. The complete file name will be PREFIX-N.log, where N is a number specific to the output stream

-vf filtergraph (output)
    创建由filtergraph指定的滤镜图,使用此滤镜图对流执行滤镜操作。本选项等价于-filter:v选项, 参考-filter选项。
-b bitrate 设置比特率,缺省200kb/s  
-r fps 设置帧频 缺省25  
-s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用:  
Sqcif 128X96 qcif 176X144 cif 252X288 4cif 704X576  
-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777  
-croptop size 设置顶部切除带大小 像素单位  
-cropbottom size –cropleft size –cropright size  
-padtop size 设置顶部补齐的大小 像素单位  
-padbottom size –padleft size –padright size –padcolor color 设置补齐条颜色(hex,6个16进制的数,红:绿:兰排列,比如 000000代表黑色)  
-vn 不做视频记录  
-bt tolerance 设置视频码率容忍度kbit/s  
-maxrate bitrate设置最大视频码率容忍度  
-minrate bitreate 设置最小视频码率容忍度  
-bufsize size 设置码率控制缓冲区大小  
-vcodec codec 强制使用codec编解码方式。如果用copy表示原始编解码数据必须被拷贝。  
-sameq 使用同样视频质量作为源(VBR)  
-pass n 选择处理遍数(1或者2)。两遍编码非常有用。第一遍生成统计信息,第二遍生成精确的请求的码率  
-passlogfile file 选择两遍的纪录文件名为file  

高级视频选项

-g gop_size 设置图像组大小
-intra 仅适用帧内编码
-qscale q 使用固定的视频量化标度(VBR)
-qmin q 最小视频量化标度(VBR)
-qmax q 最大视频量化标度(VBR)
-qdiff q 量化标度间最大偏差 (VBR)
-qblur blur 视频量化标度柔化(VBR)
-qcomp compression 视频量化标度压缩(VBR)
-rc_init_cplx complexity 一遍编码的初始复杂度
-b_qfactor factor 在p和b帧间的qp因子
-i_qfactor factor 在p和i帧间的qp因子
-b_qoffset offset 在p和b帧间的qp偏差
-i_qoffset offset 在p和i帧间的qp偏差
-rc_eq equation 设置码率控制方程 默认tex^qComp
-rc_override override 特定间隔下的速率控制重载
-me method 设置运动估计的方法 可用方法有 zero phods log x1 epzs(缺省) full
-dct_algo algo 设置dct的算法 可用的有 0 FF_DCT_AUTO 缺省的DCT 1 FF_DCT_FASTINT 2 FF_DCT_INT 3 FF_DCT_MMX 4 FF_DCT_MLIB 5 FF_DCT_ALTIVEC
-idct_algo algo 设置idct算法。可用的有 0 FF_IDCT_AUTO 缺省的IDCT 1 FF_IDCT_INT 2 FF_IDCT_SIMPLE 3 FF_IDCT_SIMPLEMMX 4 FF_IDCT_LIBMPEG2MMX 5 FF_IDCT_PS2 6 FF_IDCT_MLIB 7 FF_IDCT_ARM 8 FF_IDCT_ALTIVEC 9 FF_IDCT_SH4 10 FF_IDCT_SIMPLEARM
-er n 设置错误残留为n 1 FF_ER_CAREFULL 缺省 2 FF_ER_COMPLIANT 3 FF_ER_AGGRESSIVE 4 FF_ER_VERY_AGGRESSIVE
-ec bit_mask 设置错误掩蔽为bit_mask,该值为如下值的位掩码 1 FF_EC_GUESS_MVS (default=enabled) 2 FF_EC_DEBLOCK (default=enabled)
-bf frames 使用frames B 帧,支持mpeg1,mpeg2,mpeg4
-mbd mode 宏块决策 0 FF_MB_DECISION_SIMPLE 使用mb_cmp 1 FF_MB_DECISION_BITS 2 FF_MB_DECISION_RD
-4mv 使用4个运动矢量 仅用于mpeg4
-part 使用数据划分 仅用于mpeg4
-bug param 绕过没有被自动监测到编码器的问题
-strict strictness 跟标准的严格性
-aic 使能高级帧内编码 h263+
-umv 使能无限运动矢量 h263+
-deinterlace 不采用交织方法
-interlace 强迫交织法编码仅对mpeg2和mpeg4有效。当你的输入是交织的并且你想要保持交织以最小图像损失的时候采用该选项。可选的方法是不交织,但是损失更大
-psnr 计算压缩帧的psnr
-vstats 输出视频编码统计到vstats_hhmmss.log
-vhook module 插入视频处理模块 module 包括了模块名和参数,用空格分开

7.6 音频选项

-ab bitrate 设置音频码率
-ar freq 设置音频采样率
-ac channels 设置通道 缺省为1
-an 不使能音频纪录
-acodec codec 使用codec编解码

7.7 音频/视频捕获选项

-vd device 设置视频捕获设备。比如/dev/video0
-vc channel 设置视频捕获通道 DV1394专用
-tvstd standard 设置电视标准 NTSC PAL(SECAM)
-dv1394 设置DV1394捕获
-av device 设置音频设备 比如/dev/dsp

7.8 高级选项

-map file:stream 设置输入流映射
-debug 打印特定调试信息
-benchmark 为基准测试加入时间
-hex 倾倒每一个输入包
-bitexact 仅使用位精确算法 用于编解码测试
-ps size 设置包大小,以bits为单位
-re 以本地帧频读数据,主要用于模拟捕获设备
-loop 循环输入流(只工作于图像流,用于ffserver测试) 

8. 示例

8.1 提取视频流/音频流

ffmpeg -i input_file -vcodec copy -an output_file_video  //分离视频流
ffmpeg -i input_file -acodec copy -vn output_file_audio  //分离音频流

8.2 视频转封装

ffmpeg –i test.mp4 –vcodec copy –acodec copy –f m4v test.m4v
ffmpeg –i test.avi –vcodec copy –acodec copy –f m4v test.m4v

8.3 视频转码

ffmpeg –i test.mp4 –vcodec h264 –s 352*278 –an –f m4v test.264              //转码为码流原始文件
ffmpeg –i test.mp4 –vcodec h264 –bf 0 –g 25 –s 352*278 –an –f m4v test.264  //转码为码流原始文件
ffmpeg –i test.avi -vcodec mpeg4 –vtag xvid –qsame test_xvid.avi            //转码为封装文件

上述命令中部分选项说明:
-bf B帧数目控制
-g 关键帧间隔控制
-s 分辨率控制

8.4 视频封装

ffmpeg –i video_file –i audio_file –vcodec copy –acodec copy output_file

8.5 视频剪切

ffmpeg -ss 0:1:30 -t 0:0:20 -i input.avi -vcodec copy -acodec copy output.avi    //剪切视频
//-r 提取图像的频率,-ss 开始时间,-t 持续时间

8.6 视频截图

先运行如下命令测试一下:

ffmpeg -ss 00:00:08 -i test.mp4 -f image2 test.jpg

发现截图已经正常生成,但是命令行有如下报错信息:
[image2 @ 0x1370f80] Could not get frame filename number 2 from pattern ‘test.jpg’ (either set update or use a pattern like %03d within the filename pattern)
av_interleaved_write_frame(): Invalid argument

参考“Solutions to some ffmpeg errors and messages”得到原因如下:
这个错误通常是因为输出名不正常或者少了某些选项:
如果输出单幅图像,应添加“-frames:v 1”输出选项;
如果输出一系列图像,应当使用正确的名称形式,例如输出文件名为output_%03d.png时,将会依次生成output_001.png, output_002.png, output_003.png等;
如果输出单幅图像,总是用最新的图像覆盖掉旧图像,应添加“-update 1”选项。

根据以上建议,修改命令如下:

  1. 提取单幅图像
    第8秒处的提取一帧图像:
ffmpeg -ss 00:00:08 -i ring.mp4 -frames:v 1 -f image2 ring.jpg

各参数说明如下:
“-ss 00:00:08”:输入选项,截取输入文件中第8秒处的图像
“-frames:v 1”:输出选项,往输出中写入一个视频帧
“-f image2”:输出选项,指定输出格式为image2

注意“-ss 00:00:08”应放在“-i ring.mp4”之前,作为输入选项,可以很快就能获得视频截图。如果放在“-i ring.mp4”之后就成了输出选项,作输出选项时,ffmpeg会一直从输入文件中读取,直到到达指定时间点,才能获取截图,如果凑巧截图的位置在文件尾,则要等整个视频播放完才能得到视频截图。

  1. 提取一系列图像
    每隔1秒(1Hz)提取一帧图像:
ffmpeg -i ring.mp4 -r 1 -f image2 ring-%3d.jpg

“-r 1”:输出选项,设置帧率,通过重复(比输入文件帧率大)或丢弃(比输入文件帧率小)视频帧来满足此帧率

从第8秒开始的持续10秒的视频里,每隔1秒(1Hz)提取一帧图像:

ffmpeg -ss 00:00:08 -t 00:00:10 -i ring.mp4 -r 1 -f image2 ring-%03d.jpg

从第8秒开始的持续10秒的视频里,提取前3帧图像:

ffmpeg -ss 00:00:08 -t 00:00:10 -i ring.mp4 -frames:v 3 -f image2 ring-%03d.jpg

8.6 视频录制

ffmpeg –i rtsp://192.168.2.104:1235/test –vcodec copy out.avi

9. 参考资料

[1] FFmpeg Basics
[2] ffmpeg.htmlhttp://ffmpeg.org/ffmpeg.html
[3] What are the the data and attachment stream type?, https://ffmpeg.org/pipermail/ffmpeg-user/2015-June/027333.html
[4] Solutions to some ffmpeg errors and messages

10. 修改记录

2018-12-15 V1.0 首次整理
2019-02-15 V1.1 完善stream_specifier章节,补充选项章节与示例章节
2019-02-16 V1.1 增加视频截图命令行示例
2019-02-19 V1.2 整理完善滤镜章节

猜你喜欢

转载自blog.csdn.net/leisure_chn/article/details/87645411
今日推荐