ffmpeg的使用
首先是官网,开源的库最重要的就是官网的参考文档。FFmpeg官网
视频压缩著名的开源库,具有封装好的API便于使用,也可以通过ffmpeg自行搭建编解码器。
官网首页,打开Documentation,其中有各种封装内核的操作指令,只需要在cmd中使用这些指令即可完成对音视频的各种编解码、滤波、格式转化、截取等等操作。
主要需要看的内容在第一个和第二个框内。
**
首先需要熟悉的是ffmpeg命令行的操作
**
-f fmt (input/output) 强制输入输出格式
Force input or output file format. The format is normally auto detected for input files and guessed from the file extension for output files, so this option is not needed in most cases.
-i url (input) 输入文件的Url
input file url
-y (global) 覆盖已有文件 yes
Overwrite output files without asking.
-n (global) 不覆盖已有文件 no
Do not overwrite output files, and exit immediately if a specified output file already exists.
-stream_loop number (input) 输入流循环次数
Set number of times input stream shall be looped. Loop 0 means no loop, loop -1 means infinite loop.
-c[:stream_specifier] codec (input/output,per-stream)
-codec[:stream_specifier] codec (input/output,per-stream)
选择编码器 or 解码器 写在输入文件前就是解码器,写在输出文件前就是编码器
Select an encoder (when used before an output file) or a decoder (when used before an input file) for one or more streams. codec is the name of a decoder/encoder or a special value copy (output only) to indicate that the stream is not to be re-encoded.
-t duration (input/output) 在-i之前作为输入选项,限制读入数据的时长
When used as an input option (before -i), limit the duration of data read from the input file.
当写在输出之前限制写出的持续时间
When used as an output option (before an output url), stop writing the output after its duration reaches duration.
duration must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.
-to and -t are mutually exclusive and -t has priority.
-to position (input/output) 在某个位置停止读或者写
Stop writing the output or reading the input at position. position must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.
-to and -t are mutually exclusive and -t has priority.
-fs limit_size (output) 限制输出文件的字节大小
Set the file size limit, expressed in bytes. No further chunk of bytes is written after the limit is exceeded. The size of the output file is slightly more than the requested file size.
-ss position (input/output) 在输入选项之前写,将在输入文件中定位到position位置
eg: ffmpeg -ss 00:00:15 -t 00:00:05 -i input.mp4 -vcodec copy -acodec copy output.mp4
When used as an input option (before -i), seeks in this input file to position. Note that in most formats it is not possible to seek exactly, so ffmpeg will seek to the closest seek point before position. When transcoding and -accurate_seek is enabled (the default), this extra segment between the seek point and position will be decoded and discarded. When doing stream copy or when -noaccurate_seek is used, it will be preserved.
When used as an output option (before an output url), decodes but discards input until the timestamps reach position.
position must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.
-sseof position (input) 与-ss相似,但是是从结尾向前,位置位负值,0是结尾
Like the -ss option but relative to the “end of file”. That is negative values are earlier in the file, 0 is at EOF.
-itsoffset offset (input) 设置输入时间偏量
Set the input time offset.
offset must be a time duration specification, see (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual.
The offset is added to the timestamps of the input files. Specifying a positive offset means that the corresponding streams are delayed by the time duration specified in offset.
-itsscale scale (input,per-stream) 调整时间尺度
Rescale input timestamps. scale should be a floating point number.
-timestamp date (output) 在容器中记录时间戳
Set the recording timestamp in the container.
date must be a date specification, see (ffmpeg-utils)the Date section in the ffmpeg-utils(1) manual.
-metadata[:metadata_specifier] key=value (output,per-metadata) 设置元数据键/值对
Set a metadata key/value pair.
等等,此处并没有介绍完通用命令。
下面是ffmpeg的视频相关命令
-vframes number (output) 设置输出的视频帧数目
Set the number of video frames to output. This is an obsolete alias for -frames:v, which you should use instead.
-r[:stream_specifier] fps (input/output,per-stream) 设置帧率 eg:25
Set frame rate (Hz value, fraction or abbreviation).
As an input option, ignore any timestamps stored in the file and instead generate timestamps assuming constant frame rate fps. This is not the same as the -framerate option used for some input formats like image2 or v4l2 (it used to be the same in older versions of FFmpeg). If in doubt use -framerate instead of the input option -r.
As an output option, duplicate or drop input frames to achieve constant output frame rate fps.
-fpsmax[:stream_specifier] fps (output,per-stream) 设置最大帧率
Set maximum frame rate (Hz value, fraction or abbreviation).
Clamps output frame rate when output framerate is auto-set and is higher than this value. Useful in batch processing or when input framerate is wrongly detected as very high. It cannot be set together with -r. It is ignored during streamcopy.
-s[:stream_specifier] size (input/output,per-stream) 设置帧尺寸 eg:1280*720
Set frame size.
As an input option, this is a shortcut for the video_size private option, recognized by some demuxers for which the frame size is either not stored in the file or is configurable – e.g. raw video or video grabbers.
As an output option, this inserts the scale video filter to the end of the corresponding filtergraph. Please use the scale filter directly to insert it at the beginning or some other place.
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)
As an input option, blocks all video streams of a file from being filtered or being automatically selected or mapped for any output. See -discard option to disable streams individually.
As an output option, disables video recording i.e. automatic selection or mapping of any video stream. For full manual control see the -map option.
-vcodec codec (output) 设置视频编码器
Set the video codec. This is an alias for -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:
-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) 创建图像滤波器对视频流进行滤波
Create the filtergraph specified by filtergraph and use it to filter the stream.
This is an alias for -filter:v, see the -filter option.
-autorotate 根据文件元数据自动旋转视频
Automatically rotate the video according to file metadata. Enabled by default, use -noautorotate to disable it.
-autoscale 根据视频第一帧的分辨率自动缩放视频
Automatically scale the video according to the resolution of first frame. Enabled by default, use -noautoscale to disable it. When autoscale is disabled, all output frames of filter graph might not be in the same resolution and may be inadequate for some encoder/muxer. Therefore, it is not recommended to disable it unless you really know what you are doing. Disable autoscale at your own risk.
ffmpeg关于Video的进阶指令
-pix_fmt[:stream_specifier] format (input/output,per-stream) 设置像素格式 eg: yuv444p yuv420p
Set pixel format. Use -pix_fmts to show all the supported pixel formats. If the selected pixel format can not be selected, ffmpeg will print a warning and select the best pixel format supported by the encoder. If pix_fmt is prefixed by a +, ffmpeg will exit with an error if the requested pixel format can not be selected, and automatic conversions inside filtergraphs are disabled. If pix_fmt is a single +, ffmpeg selects the same pixel format as the input (or graph output) and automatic conversions are disabled.
-psnr 计算压缩后的帧的峰值信噪比
Calculate PSNR of compressed frames.
进阶指令并没有介绍全,更多的请到官网探索。
ffmpeg 常用命令
此部分转自该微信公众号
1. 视频转换
比如一个avi文件,想转为mp4,或者一个mp4想转为ts。
ffmpeg -i input.avi output.mp4
ffmpeg -i input.mp4 output.ts
2. 提取音频
ffmpeg -i test.mp4 -acodec copy -vn output.aac
上面的命令,默认mp4的audio codec是aac,如果不是,可以都转为最常见的aac。
ffmpeg -i test.mp4 -acodec aac -vn output.aac
3. 提取视频
ffmpeg -i input.mp4 -vcodec copy -an output.mp4
4. 视频剪切
下面的命令,可以从时间为00:00:15开始,截取5秒钟的视频。
ffmpeg -ss 00:00:15 -t 00:00:05 -i input.mp4 -vcodec copy -acodec copy output.mp4
-ss表示开始切割的时间,-t表示要切多少。上面就是从15秒开始,切5秒钟出来。
5. 码率控制
码率控制对于在线视频比较重要。因为在线视频需要考虑其能提供的带宽。
什么是码率?
bitrate = file size / duration
比如一个文件20.8M,时长1分钟,那么,码率就是:
biterate = 20.8M bit/60s = 20.810241024*8 bit/60s= 2831Kbps
一般音频的码率只有固定几种,如128Kbps,
那么,video的就是
video biterate = 2831Kbps -128Kbps = 2703Kbps。
那么ffmpeg如何控制码率。
ffmpg控制码率有3种选择,-minrate -b:v -maxrate
-b:v主要是控制平均码率。
比如一个视频源的码率太高了,有10Mbps,文件太大,想把文件弄小一点,但是又不破坏分辨率。
ffmpeg -i input.mp4 -b:v 2000k output.mp4
上面把码率从原码率转成2Mbps码率,这样其实也间接让文件变小了。目测接近一半。
不过,ffmpeg官方wiki比较建议,设置b:v时,同时加上 -bufsize
-bufsize 用于设置码率控制缓冲器的大小,设置的好处是,让整体的码率更趋近于希望的值,减少波动。
ffmpeg -i input.mp4 -b:v 2000k -bufsize 2000k output.mp4
-minrate -maxrate就简单了,在线视频有时候,希望码率波动,不要超过一个阈值,可以设置maxrate。
ffmpeg -i input.mp4 -b:v 2000k -bufsize 2000k -maxrate 2500k output.mp4
6. 视频编码格式转换
比如一个视频的编码是MPEG4,想用H264编码,咋办?
ffmpeg -i input.mp4 -vcodec h264 output.mp4
相反也一样
ffmpeg -i input.mp4 -vcodec mpeg4 output.mp4
当然了,如果ffmpeg当时编译时,添加了外部的x265或者X264,那也可以用外部的编码器来编码。
ffmpeg -i input.mp4 -c:v libx265 output.mp4
ffmpeg -i input.mp4 -c:v libx264 output.mp4
7. 只提取视频ES数据
ffmpeg –i input.mp4 –vcodec copy –an –f m4v output.h264
8. 过滤器的使用
8.1 将输入的1920x1080缩小到960x540输出:
ffmpeg -i input.mp4 -vf scale=960:540 output.mp4
8.2 为视频添加logo
比如,我有这么一个图片
想要贴到一个视频上,那可以用如下命令:
./ffmpeg -i input.mp4 -i iQIYI_logo.png -filter_complex overlay output.mp4
右上角:
./ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=W-w output.mp4
左下角:
./ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=0:H-h output.mp4
右下角:
./ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=W-w:H-h output.mp4
8.3 去掉视频的logo
语法:-vf delogo=x:y:w:h[:t[:show]]
x:y 离左上角的坐标
w:h logo的宽和高
t: 矩形边缘的厚度默认值4
show:若设置为1有一个绿色的矩形,默认值0。
ffmpeg -i input.mp4 -vf delogo=0:0:220:90💯1 output.mp4
结果如下所示:
9. 截取视频图像
ffmpeg -i input.mp4 -r 1 -q:v 2 -f image2 pic-%03d.jpeg
-r 表示每一秒几帧
-q:v表示存储jpeg的图像质量,一般2是高质量。
如此,ffmpeg会把input.mp4,每隔一秒,存一张图片下来。假设有60s,那会有60张。
可以设置开始的时间,和你想要截取的时间。
ffmpeg -i input.mp4 -ss 00:00:20 -t 10 -r 1 -q:v 2 -f image2 pic-%03d.jpeg
-ss 表示开始时间
-t 表示共要多少时间。
如此,ffmpeg会从input.mp4的第20s时间开始,往下10s,即20~30s这10秒钟之间,每隔1s就抓一帧,总共会抓10帧。
10. 序列帧与视频的相互转换
把darkdoor.[001-100].jpg序列帧和001.mp3音频文件利用mpeg4编码方式合成视频文件darkdoor.avi:
$ ffmpeg -i 001.mp3 -i darkdoor.%3d.jpg -s 1024x768 -vcodec mpeg4 darkdoor.avi
还可以把视频文件导出成jpg序列帧:
$ ffmpeg -i bc-cinematic-en.avi example.%d.jpg
H264编码profile & level控制
背景知识
先科普一下profile&level。(这里讨论最常用的H264)
H.264有四种画质级别,分别是baseline, extended, main, high:
1、Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;
2、Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少)
3、Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced),
也支持CAVLC 和CABAC 的支持;
4、High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;
H.264 Baseline profile、Extended profile和Main profile都是针对8位样本数据、4:2:0格式(YUV)的视频序列。在相同配置情况下,High profile(HP)可以比Main profile(MP)降低10%的码率。
根据应用领域的不同,Baseline profile多应用于实时通信领域,Main profile多应用于流媒体领域,High profile则多应用于广电和存储领域。
下图清楚的给出不同的profile&level的性能区别。
**
ffmpeg如何控制profile&level
**
举3个例子吧
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 output.mp4
ffmpeg -i input.mp4 -profile:v main -level 4.2 output.mp4
ffmpeg -i input.mp4 -profile:v high -level 5.1 output.mp4
如果ffmpeg编译时加了external的libx264,那就这么写:
ffmpeg -i input.mp4 -c:v libx264 -x264-params “profile=high:level=3.0” output.mp4
从压缩比例来说,baseline< main < high,对于带宽比较局限的在线视频,可能会选择high,高压缩比意味着占用硬件资源多,需要取舍。
编码效率和视频质量的取舍(preset, crf)
除了上面提到的,强行配置biterate,或者强行配置profile/level,还有2个参数可以控制编码效率。
一个是preset,一个是crf。
preset也挺粗暴,基本原则就是,如果你觉得编码太快或太慢了,想改改,可以用profile。
preset有如下参数可用:
ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow and placebo.
编码加快,意味着信息丢失越严重,输出图像质量越差。
CRF(Constant Rate Factor): 范围 0-51: 0是编码毫无丢失信息, 23 is 默认, 51 是最差的情况。相对合理的区间是18-28.
值越大,压缩效率越高,但也意味着信息丢失越严重,输出图像质量越差。
举个例子吧。
ffmpeg -i input -c:v libx264 -profile:v main -preset:v fast -level 3.1 -x264opts crf=18
(参考自:https://trac.ffmpeg.org/wiki/Encode/H.264)
H265 (HEVC)编码tile&level控制
背景知识
和H264的profile&level一样,为了应对不同应用的需求,HEVC制定了“层级”(tier) 和“等级”(level)。
tier只有main和high。
level有13级,如下所示:
eg: ffmpeg -i input.mp4 -c:v libx265 -x265-params “profile=high:level=3.0” output.mp4