『FFMPEG』ffmpeg/avconv使用学习笔记『较详细』

原文链接:ffmpeg/avconv使用学习笔记


ffmpeg / avconv是通用的视频/音频编解码命令行工具。

通用是既指他们可以处理各种各样的编码的视频和音频,转换成各种需要的格式,又指他们是跨平台的工具,可以运行在Linux、Windows、MacOS X等操作系统上。

avconv和ffmpeg的渊源颇深。ffmpeg是FFmpeg项目的命令行编解码工具;avconv是Libav项目中用来代替ffmpeg的命令行编解码工具。2012年1月下旬Libav项目决定抛弃掉ffmpeg, 完全用avconv代替之,因此Libav项目的命令行编码器只有avconv。

事实上,avconv和ffmpeg是基本一致的,avconv只是对原 ffmpeg的某些选项做了些微调,并且规范了一些行为。此外,FFmpeg项目也在不断吸收Libav项目的更新,因此两者的行为几乎一样。具体的差别看这里。我们下面主要用ffmpeg来做例子

特别说明:ffmpeg和avconv的选项经常变化,本文用的是ffmpeg version N-37208-g01fcbdf和avconv version N-32611-gd55b06b。我们使用时需要结合具体版本。也就是说,这个笔记可能会很快过时…


 

一、获取

两个项目都提供了源代码的镜像地址和编译好的Windows二进制文件的下载地址。

FFmpeg:
源代码 git://git.libav.org/libav.git
Windows编译版 http://ffmpeg.zeranoe.com/builds/
下载最新版(lastest),可以下载static的build。用到压缩包里的bin文件夹里的ffmpeg.exe。

Libav:
源代码 git://git.libav.org/libav.git
32位Windows编译版 http://win32.libav.org/win32/
64位Windows编译版 http://win32.libav.org/win64/
看日期下载最新版,用到压缩包里bin文件夹里的各种文件。

 

二、文档和帮助

非常详细的在线文档

ffmpeg http://ffmpeg.org/ffmpeg.html
avconv http://libav.org/avconv.html

例0、打印帮助信息(以下用ffmpeg作为例子,用美元符号$作为命令行提示符)

在命令行里输入

$ffmpeg.exe -h

下面我们去掉.exe,因为linux下的二进制文件本来就没有扩展名,Windows下不写exe也能调用

ffmpeg的帮助非常长,Windows的cmd的缓冲区默认高度甚至装不下。用重定向符号把帮助输出到某个txt里:

$ffmpeg -h > ffmpeghelp.txt

帮助分为基本用法、主要选项(main options)、各种高级选项、各种AVOptions、编译信息等部分。

我们看AVCodecContext AVOptions里有个选项是-bufsize

-bufsize <int> E.VA. set ratecontrol buffer size (in bits)

该行告诉我们,此选项的参数应该是一个整数,单位是bit。注意到E、V和A三个字母,分别代表Encode、Video和Audio,说明这个选项在编码中有效,对视频和音频有效。另外还有D,代表Decode,比如:

-ar <int> ED.A. set audio sampling rate (in Hz)

这个选项对编码(Encode)、解码(Decode)起作用,是音频(Audio)方面的选项。

列出支持的编解码器

$ffmpeg -codecs

列出支持的滤镜

$ffmpeg -filters

列出支持的格式

$ffmpeg -formats

返回版本信息

$ffmpeg -version

 

三、ffmpeg选项基本用法

用法:

$ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

选项 -> 输入选项 -> 输入文件 … -> 输出选项 -> 输出文件 …

我们称带横线-的参数为选项(option),选项的值这里称为参数(argument),即 -option argumet。

说明:
(1)输入文件用-i指定;输出文件无选项,直接指定。
(2)选项-y 输出文件直接覆盖已存在的文件;-n 不覆盖已存在文件。
(3)选项区分先后顺序,特别是输入选项应对应输入文件,输出选项对应输出文件;滤镜调用也有顺序;-map也是顺序相关的。
(4)可以输入多个文件,输出多个文件。

 

好,用例子体会。

 

四、初步任务

一些简单的音频和视频单独编码和转换封装
 

1、编码音频

例1、把3po.ac3压成128Kbps的mp3

$ffmpeg -i 3po.ac3 -acodec libmp3lame -b:a 128000 3po_enc.mp3

说明:
(1)使用选项-acodec指定音频编码,如果用参数copy是直接复制相应的流。
(2)选项-b:a指定音频码率,单位是bits/s;使用-aq指定音频质量,具体数值和编码有关。

 

2、视频编码

例2、把只有视频的、编码为xvid的obi-wan.avi压成编码为H264、封装为mkv的视频

$ffmpeg -i obi-wan.avi -vcodec libx264 -crf 22 -preset medium -tune film -deblock 1:1 -refs 4 -bf 8 -psy-rd 0.6:0.2 -subq 6 obi-wan_enc.mkv

说明:
(1)使用选项-vcodec指定音频编码,如果用参数copy是直接复制相应的流。参数指定libx264就是调用编译在ffmpeg中的libx264。
(2) 这里例子中的很多选项和直接使用x264是很像的,其中-crf、-preset、-tune、-deblock、-psy-rd等都是对应的,而 -refs对应x264的–ref,-subq对应–subme,-bf对应–bframes。写法基本一致,具体可以参考帮助的libx264 AVOptions部分,但有些选项是在AVCodecContext AVOptions部分的。
(3)我们指定的输出文件为obi-wan.mkv,ffmpeg会根据扩展名用相应的封装格式。
(4)编码过程中按q停止。

例3、调用libx264 2 pass编码,输入文件还是没有音频的obi-wan.avi

#1pass:

$ffmpeg -i obi-wan.avi -vcodec libx264 -preset medium -tune film -pass 1 -passlogfile 1pass.stats -crf 20 -f null obi-wan1p.mkv

 
#2pass:

$ffmpeg -i obi-wan.avi -vcodec libx264 -preset medium -tune film -pass 2 -passlogfile 1pass.stats -b:v 400000 obi-wan2p.mkv

说明:
(1)-pass指定某个pass,我们看到用ffmpeg编码时1pass也可以用crf模式;用-passlogfile指定stats文件。
(2)用-b:v指定码率,单位是bits/s。
(3)-f null不输出文件,其实后面输出文件的名字随便,但至少要指定一个输出;passlogfile还是会正常输出的。

例4、改变视频的分辨率,这次是有音频的r2d2.mkv,但是我们要把音频去掉

$ffmpeg -i r2d2.mkv -an -vcodec libx264 -filter scale=480:204 r2d2_small.mkv

说明:
(1)用scale滤镜调整分辨率,用法是 -filter scale=out_w:out_h,宽:高。
(2)用选项-an去掉所有音频流;-vn去掉所有视频流;-sn去掉所有字幕流。流(stream)会在下面讲。
(3)ffmpeg会根据输入视频流的DAR自动调整缩放后视频的SAR,以保证DAR不变。

 

3、转换封装(remux),但不重编码

例5、例子是有音频的r2d2.mkv,转换成mp4封装

$ffmpeg -i r2d2.mkv -codec:v copy -codec:a copy r2d2_remux.mp4

说明:
(1) -codec:v copy表示不重编码视频, -codec:a copy表示不重编码音频
(2)这个例子再次说明了ffmpeg会根据扩展名选择封装
(3)因为只有音频流和视频流,因此可以用”-codec copy”代替”-codec:v copy -codec:a copy”

 

五、复杂一点的例子和为某些设备编码

1、更多滤镜的例子

例6、对有音频的r2d2.mkv先切边(crop),再缩小(resize)

$ffmpeg -i r2d2.mkv -filter crop=1240:544:20:0,scale=464:204 -sws_flags lanczos r2d2_smaller.mp4

说明:
(1)crop 的用法是 -filter crop=out_w:out_h:x:y,宽:高:x坐标:y坐标。坐标原点在左上角,往右x增加,往下y增加。因此 crop=1240:544:20:0代表在坐标(20,0)处框出一个1240×544的框,框内部的画面保留。
(2)滤镜之间用逗号(,)分开。滤镜有先后顺序。
(3)这个例子中使用了选项-sws_flags指定缩放算法,这里指定了lanczos。
(4)我们没有指定编码,ffmpeg会自动使用输入文件的编码压一遍。

例7、把字幕嵌进视频,视频是r2d2.mkv,字幕是r2d2.ass

$ffmpeg -i r2d2.mkv -filter ass=r2d2.ass -codec:a copy r2d2_sub.mkv

说明:
(1)需要configure时有–enable-libass的ffmpeg
(2)这里-codec:a等于-acodec;类似的,-codec:v等于-vcodec

 

2、为设备编码

例8、给iPhone 4压片,源是分辨率为1280×720的darth_vader.mkv,有1条2.0的音轨

我们知道,iPhone 4的分辨率是960×640,因此片子分辨率不需要那么大。iPhone 4支持H264 level小于或等于3.1,音频需要2.0声道AAC,封装是mp4。

我们先算好,960/(1280/720)=540,因此应该缩小到960/540。

$ffmpeg -i darth_vader.mkv -filter scale=960:540 -codec:v libx264 -f ipod -level 3 -preset slow -tune film -crf 20 -codec:a aac -b:a 160k darth_vader_iphone.mp4

说明:
如果懒得算分辨率,就用 scale=960:-1,ffmpeg会自动按照比例调整。或者连原视频的分辨率都不需要知道,用scale=’min(960, iw):-1′,如果小于宽度960,就不动分辨率,如果宽度大于960就缩小到960。scale的用法很灵活,具体参考http://ffmpeg.org/ffmpeg.html#Video-Filters

 

3、只压一部分

-ss 指定开始时间(s)
-t 指定视频/音频长度(s)
-fs 文件到指定大小编码结束,单位byte
-timelimit 指定ffmepg最大运行时间(s)
-frames 指定编码帧数

例9、只编码前500帧,用有一个视频流和音频流的padme.mkv作为例子

$ffmpeg -i padme.mkv -frames:v 500 padme_trim1.mkv

说明:
用-frames:v指定编码视频的帧数。

例10、从5分33.145秒开始到8分20.073秒结束

$ffmpeg -i padme.mkv -ss 00:05:33.145 -t 00:02:46.928 padme_trim2.mkv

说明:
(1)用-ss指定开始时间,用hh:mm:ss[.ms]格式,或者换算成用秒计。
(2)用-t指定长度,和-ss的格式一样,用hh:mm:ss[.ms]格式,或者换算成用秒计。
(3)如果-ss放在-i之前,就会成为输入选项,会先跳转过去。如果-i放在输出文件前面,则会成为输出选项,ffmpeg会先解码到给定时间,再开始编码行为,这样做会比较慢,但更精确。
(4)如果想用这个方法无损分割(用-codec copy),是不一定能切准的。

 

六、更复杂的用法和pipe

1、流映射(stream mapping)选项-map

ffmpeg把输入文件的轨道称为stream,如果我们只输入darth_vader.mkv但不指定输出

$ffmpeg -i darth_vader.mkv

会看到以下返回信息

Input #0, matroska,webm, from 'darth_vader.mkv':
Duration: 00:22:52.09, start: 0.000000, bitrate: 2753 kb/s
Stream #0:0: Video: h264 (High), yuv420p, 1280x720, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc (default)
Stream #0:1: Audio: aac, 48000 Hz, stereo, s16 (default)

第一个输入文件的第一个流叫stream #0:0,编号是从0开始的,如果有两个输入,第二个输入文件的第一个流则是stream #1:0,依次类推。

音频流、视频流、字幕流的地位平等。

ffmpeg默认不调整流的顺序,也不去掉任何流,如果想调整流的顺序,或把不同文件的流mux起来,需要用-map强制顺序。ffmpeg会根据-map的先后顺序调整输出文件中流的顺序。

例11、把r2d2.mkv的视频和darth_vader.mkv的音频合成一个文件

$ffmpeg -i r2d2.mkv -i darth_vader.mkv -map 0:0 -map 1:1 -c:v copy -c:a copy r2d2_remux.mkv

说明:
(1)这里有两个-i,输入了两个文件。
(2)-c代表-codec。-c:v copy表示对所有的视频流做copy;-c:a copy表示对所有的音频流做copy。

 

2、多输出

ffmpeg实际可以指定多个输出文件。把选项和输出文件按照顺序写下来即可。

例12、把yoda.m2ts的视频remux成mkv格式,音频压成flac

$ffmpeg -i yoda.m2ts -map 0:0 -c:v copy yoda_v.mkv -map 0:1 -c:a flac yoda_a.flac

说明:
(1)第一个-map配合-c:v copy,输出了第一个文件yoda_v.mkv
(2)第二个-map配合-c:a flac,编码了第二个输出文件yoda_a.flac

 

3、pipe

这个技巧经常用在32位avs配合64位x264上。ffmpeg可以输出rawyuv或yuv4mpeg,pipe给x264

例13、用两种方法把分辨率为1280×720、fps为23.976的count_dooku.avs pipe给x264

$ffmpeg -i count_dooku.avs -f rawvideo - | x264 --input-res 1280x720 --fps 24000/1001 -o count_dooku_rawyuv.mkv -

$ffmpeg -i count_dooku.avs -f yuv4mpegpipe pipe: | x264 --demuxer y4m -o count_dooku_y4m.mkv -

说明:
(1)pipe时,ffmpeg的输出用-或pipe:,x264的输入用-,两个程序用|分开
(2)前一个例子pipe rawyuv,需要为x264指定–input-res、–input-csp和–fps。由于两者默认色彩空间相同,因此–input-csp可以省掉;指定–fps是为了更准的码率控制
(3)后一个例子pipe yuv4mpeg,不需要为x264指定分辨率等格式。

例14、一边pipe给x264做1pass,一边压出ffv1,以count_dooku.avs作为例子

$ffmpeg -i count_dooku.avs -vcodec ffv1 count_dooku_ffv1.mkv -f yuv4mpegpipe - | x264 --demuxer y4m -o count_dooku_1p.mkv -p 1 --stats 1p.stats -

说明:
纯蛋疼

 

4、其他

例15、隔行扫描视频luke.m2ts,先用yadif反交错并缩小,再用libx264压

$ffmpeg -i luke.m2ts -filter yadif:scale=1280:-1 -v:c libx264 -c:a copy luke_deint.mkv

说明:

yadif是反交错滤镜,缩放应在反交错之后。

例16、把视频darth_sidious.mkv的每一帧输出成png

$ffmpeg -i darth_sidious.mkv darth_sidious%03d.png

说明:
(1)会浪费大量硬盘空间。
(2)%03d的行为和C语言的格式化字符一样。

 

七、总结

ffmpeg和avconv是通用的编解码工具,可以胜任绝大多数编码的任务。虽然上面的例子几乎都可以用专门性更强的工具解决,但像ffmpeg和 avconv功能如此多、用起来如此方便的工具的是找不到第四个的(因为还有mencoder,但已经很久不开发了,在mplayer2中甚至被拿掉 了)。

-vcodec和-acodec是选择编码的核心选项。但这是原来的写法,面向未来,这两个选项统一成了-codec,通过选 择stream指定,即-codec:v和-codec:a,或者简写成-c:v和-c:a。ffmpeg和avconv有越来越多选项可以选择 stream,比如-filter、-frames、-q。应该多使用-codec:v这种形式的写法。

 

参考

http://ffmpeg.org/ffmpeg.html

http://libav.org/documentation.html

http://howto-pages.org/ffmpeg/


你可能感兴趣的:(ffmpeg)