0.概述
FFmpeg的名称来自MPEG视频编码标准,前面的"FF"代表"Fast
Forward",FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。
FFmpeg
是领先的多媒体框架,能够解码、编码、转码、混合、解密、流媒体、过滤和播放人类和机器创造的几乎所有东西。它支持最晦涩的古老格式,直到最尖端的格式。无论它们是由某个标准委员会、社区还是公司设计的。它还具有高度的便携性。\
\
FFmpeg 可以在 Linux、Mac OS X、Microsoft Windows、BSDs、Solaris
等各种构建环境、机器架构和配置下编译、运行,并通过测试基础设施 FATE。\
\
它包含了
libavcodec、libavutil、libavformat、libavfilter、libavdevice、libswscale
和 libswresample,可以被应用程序使用。还有 ffmpeg、ffplay 和
ffprobe,可以被终端用户用于转码和播放。
其中:
-
ffmpeg:是一个命令行工具,用来对视频文件转换格式,也支持对电视卡实时编码
-
libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能,包含demuxers和muxer库;
-
libavcodec:用于各种类型声音/图像编解码;
-
libavfilter:滤镜库
-
libavutil:包含一些公共的工具函数;
-
libswscale:用于视频场景比例缩放、色彩映射转换;
-
libpostproc:用于后期效果处理;
-
ffsever:是一个HTTP多媒体实时广播流服务器,支持时光平移;(注:本文不介绍)
-
ffplay:是一个简单的播放器,使用ffmpeg
库解析和解码,通过SDL显示;(一般编译完没有带ffplay,新版本版本依赖于sdl-2.0,需要安装sdl-2.0才能生成ffplay)
0.1.术语
容器(Container)容器就是一种文件格式,比如flv,mkv等。包含下面5种流以及文件头信息。
流(Stream)是一种视频数据信息的传输方式,5种流:音频(a)、附件(t)、数据(d)、字幕(s)和视频(v)。
帧(Frame)帧代表一幅静止的图像,分为I帧,P帧,B帧。
编解码器(Codec)是对视频进行压缩或者解压缩,CODEC =Code (编码)
+DECode(解码)
复用/解复用(mux/demux)把不同的流按照某种容器的规则放入容器,这种行为叫做复用(mux)把不同的流从某种容器中解析出来,这种行为叫做解复用(demux);
视频转换流程解析
代码转换过程中,ffmpeg在libavformat库中调用demuxers来读取输入,并从数据包中获取编码数据。如果有更多的输入,ffmpeg可以通过跟踪任何活动输入流的最低时间戳来保持它们的同步。然后解码器从编码的数据包中生成未压缩的帧,在可选的过滤后,帧被发送到编码器。编码器产生新的编码包,它被发送到muxer并写入到输出。
流拷贝
流拷贝是对指定数据流仅仅进行复制,这种情况下不会进行编码解码,仅仅是分离和混合数据包,所以特别快,也不会造成质量损失,这也导致这种模式不适用复杂的滤镜处理等,这种模式常用于文件包格式或者修改部分元数据信息。
播放原理
封装格式作用:视频码流和音频码流按照一定的格式储存在一个文件汇总
视频编码数据作用:将视频像素数据(RGB,YUV等)压缩成为视频码流,从而降低视频的数据量
音频编码数据作用:将音频采样数据(PCM等)压缩成为音频码流,从而降低音频的数据量
视频像素数据作用:保存了屏幕上每一个像素点的像素值格式:常见的像素数据格式有RGB24,
RGB32, YUV420P,YUV422P,YUV444P等。
压缩编码中一般使用的是YUV格式的像素数据,最为常见的格式为YUV420P。特点:视频像素数据体积很大
音频采样数据作用:保存了音频中每个采样点的值。特点:音频采样数据体积很大
0.2.码流 kb/s
码流(Data
Rate)是指视频图像经过编码压缩后在单位时间内的数据流量,也叫码率,一般我们用的单位是kb/s或者Mb/s。是视频编码中画面质量控制中最重要的部分。同样分辨率下,压缩比越小,视频图像的码率就越大,画面质量就越高,文件体积也越大。
其计算公式是文件体积=时间X码率/8。
0.3.采样率Hz
采样率(也称为采样速度或者采样频率)定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。采样率是指将模拟信号转换成数字信号时的采样频率,也就是单位时间内采样多少点。一个采样点数据有多少个比特。
0.4.比特率bps
比特率是指每秒传送的比特(bit)数。单位为bps(BitPer
Second),比特率越高,传送的数据越大。比特率表示经过编码(压缩)后的音、视频数据每秒钟需要用多少个比特来表示,而比特就是二进制里面最小的单位,要么是0,要么是1。比特率与音、视频压缩的关系,简单的说就是比特率越高,音、视频的质量就越好,但编码后的文件就越大;如果比特率越少则情况刚好相反。比特率是指将数字声音、视频由模拟格式转化成数字格式的采样率,采样率越高,还原后的音质、画质就越好。
比特率是决定整体音频或视频质量的参数。
它规定了每时间单位处理的位数,在Ffmpeg中,位速率以每秒位数表示。比特率决定了存储1秒编码流的位数
比特率 =采样率 x 采用位数 x声道数.
VBR(Variable Bitrate)动态比特率
也就是没有固定的比特率,压缩软件在压缩时根据音频数据即时确定使用什么比特率,这是以质量为前提兼顾文件大小的方式,推荐编码模式;
ABR(Average
Bitrate)平均比特率是VBR的一种插值参数。LAME针对CBR不佳的文件体积比和VBR生成文件大小不定的特点独创了这种编码模式。ABR在指定的文件大小内,以每50帧(30帧约1秒)为一段,低频和不敏感频率使用相对低的流量,高频和大动态表现时使用高流量,可以做为VBR和CBR的一种折衷选择。
CBR(Constant Bitrate),常数比特率
指文件从头到尾都是一种位速率。相对于VBR和ABR来讲,它压缩出来的文件体积很大,而且音质相对于VBR和ABR不会有明显的提高。
0.5.帧速率
帧速率是编码成视频文件的每秒帧数(FPS或fps),人眼需要至少约15
fps来观看连续运动。
帧率也称为帧频,其单位是赫兹(Hz),LCD显示器通常具有60
Hz的频率。有两种帧速率 --
隔行(在FPS编号后表示为i)和逐行(在FPS编号后表示为p)。越高的帧速率可以得到更流畅、更逼真的动画。每秒钟帧数(FPS)越多,所显示的动作就会越流畅。
0.6.I、P、B 帧
在视频编码序列中,主要有三种编码帧:I帧、P帧、B帧,如下图所示。
-
I帧即Intra-coded
picture(帧内编码图像帧),不参考其他图像帧,只利用本帧的信息进行编码
-
P帧即Predictive-codedPicture(预测编码图像帧),利用之前的I帧或P帧,采用运动预测的方式进行帧间预测编码
-
B帧即Bidirectionallypredicted
picture(双向预测编码图像帧),提供最高的压缩比,它既需要之前的图像帧(I帧或P帧),也需要后来的图像帧(P帧),采用运动预测的方式进行帧间双向预测编码
三种帧的说明
- I帧
I帧:帧内编码帧
,I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)
I帧特点:
1) 它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;
2) 解码时仅用I帧的数据就可重构完整图像;
3) I帧描述了图像背景和运动主体的详情;
4) I帧不需要参考其他画面而生成;
5) I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);
6) I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;
7) I帧不需要考虑运动矢量;
8) I帧所占数据的信息量比较大。
- P帧
P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)
P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧"某点"的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧"某点"的预测值并与差值相加以得到P帧"某点"样值,从而可得到完整的P帧。
P帧特点:
1) P帧是I帧后面相隔1~2帧的编码帧;
2) P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);
3) 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;
4) P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;
5) P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;
6) 由于P帧是参考帧,它可能造成解码错误的扩散;
7) 由于是差值传送,P帧的压缩比较高。
- B帧
B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况,但我这样说简单些),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。
B帧的预测与重构:B帧以前面的I或P帧和后面的P帧为参考帧,"找出"B帧"某点"的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中"找出(算出)"预测值并与差值求和,得到B帧"某点"样值,从而可得到完整的B帧。
B帧特点
1)B帧是由前面的I或P帧和后面的P帧来进行预测的;
2)B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;
3)B帧是双向预测编码帧;
4)B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;
5)B帧不是参考帧,不会造成解码错误的扩散。
I 帧、P 帧、B 帧的区别在于:
I 帧(Intracoded frames):I
帧图像采用帧内编码方式,即只利用了单帧图像内的空间相关性,而没有利用时间相关性。I
帧使用帧内压缩,不使用运动补偿,由于 I
帧不依赖其它帧,所以是随机存取的入点,同时是解码的基准帧。I
帧主要用于接收机的初始化和信道的获取,以及节目的切换和插入,I
帧图像的压缩倍数相对较低。I
帧图像是周期性出现在图像序列中的,出现频率可由编码器选择。
P 帧(Predictedframes):P 帧和 B
帧图像采用帧间编码方式,即同时利用了空间和时间上的相关性。P
帧图像只采用前向时间预测,可以提高压缩效率和图像质量。P
帧图像中可以包含帧内编码的部分,即 P
帧中的每一个宏块可以是前向预测,也可以是帧内编码。
B 帧(Bi-directionalpredicted frames):B
帧图像采用双向时间预测,可以大大提高压缩倍数。值得注意的是,由于 B
帧图像采用了未来帧作为参考,因此 MPEG-2
编码码流中图像帧的传输顺序和显示顺序是不同的。
也就是说,一个 I 帧可以不依赖其他帧就解码出一幅完整的图像,而 P 帧、B
帧不行。P 帧需要依赖视频流中排在它前面的帧才能解码出图像。B
帧则需要依赖视频流中排在它前面或后面的帧才能解码出图像。
在H264的概念中有一个帧称为IDR帧,那么IDR帧与I帧的区别是什么呢?
首先来看一下IDR的英文全称instantaneous decoding refresh
picture,因为H264采用了多帧预测,所以I帧之后的P帧有可能会参考I帧之前的帧,这就使得在随机访问的时候不能以找到I帧作为参考条件,因为即使找到I帧,I帧之后的帧还是有可能解析不出来,而IDR帧就是一种特殊的I帧,即这一帧之后的所有参考帧只会参考到这个IDR帧,而不会再参考前面的帧。在解码器中,一旦收到一个IDR帧,就会立即清理参考帧缓冲区,并将IDR帧作为被参考的帧。
0.7.GOP
在视频编码序列中,GOP即Group of
picture(图像组),指两个I帧之间的距离,Reference(参考周期)指两个P帧之间的距离。一个I帧所占用的字节数大于一个P帧,一个P帧所占用的字节数大于一个B帧。所以在码率不变的前提下,GOP值越大,P、B帧的数量会越多,平均每个I、P、B帧所占用的字节数就越多,也就更容易获取较好的图像质量;Reference越大,B帧的数量越多,同理也更容易获得较好的图像质量。需要说明的是,通过提高GOP值来提高图像质量是有限度的,在遇到场景切换的情况时,H.264编码器会自动强制插入一个I帧,此时实际的GOP值被缩短了。另一方面,在一个GOP中,P、B帧是由I帧预测得到的,当I帧的图像质量比较差时,会影响到一个GOP中后续P、B帧的图像质量,直到下一个GOP开始才有可能得以恢复,所以GOP值也不宜设置过大。同时,由于P、B帧的复杂度大于I帧,所以过多的P、B帧会影响编码效率,使编码效率降低。另外,过长的GOP还会影响Seek操作的响应速度,由于P、B帧是由前面的I或P帧预测得到的,所以Seek操作需要直接定位,解码某一个P或B帧时,需要先解码得到本GOP内的I帧及之前的N个预测帧才可以,GOP值越长,需要解码的预测帧就越多,seek响应的时间也越长。
0.8.DTS、PTS 的概念
DTS(Decoding Time
Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
PTS(Presentation Time
Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
需要注意的是:虽然 DTS、PTS
是用于指导播放端的行为,但它们是在编码的时候由编码器生成的。
当视频流中没有 B 帧时,通常 DTS 和 PTS 的顺序是一致的。但如果有 B
帧时,就回到了我们前面说的问题:解码顺序和播放顺序不一致了。
比如一个视频中,帧的显示顺序是:I B B P,现在我们需要在解码 B 帧时知道 P
帧中信息,因此这几帧在视频流中的顺序可能是:I P B
B,这时候就体现出每帧都有 DTS 和 PTS 的作用了。DTS
告诉我们该按什么顺序解码这几帧图像,PTS
告诉我们该按什么顺序显示这几帧图像。顺序大概如下:
PTS: 1 4 2 3
DTS: 1 2 3 4
Stream: I P B B
0.9.音视频的同步
上面说了视频帧、DTS、PTS
相关的概念。我们都知道在一个媒体流中,除了视频以外,通常还包括音频。音频的播放,也有
DTS、PTS 的概念,但是音频没有类似视频中 B
帧,不需要双向预测,所以音频帧的 DTS、PTS 顺序是一致的。
音频视频混合在一起播放,就呈现了我们常常看到的广义的视频。在音视频一起播放的时候,我们通常需要面临一个问题:怎么去同步它们,以免出现画不对声的情况。
要实现音视频同步,通常需要选择一个参考时钟,参考时钟上的时间是线性递增的,编码音视频流时依据参考时钟上的时间给每帧数据打上时间戳。在播放时,读取数据帧上的时间戳,同时参考当前参考时钟上的时间来安排播放。这里的说的时间戳就是我们前面说的
PTS。实践中,我们可以选择:同步视频到音频、同步音频到视频、同步音频和视频到外部时钟。
PAR ------ Pixel Aspect Ratio
像素横纵比。表示每个像素的宽度与长度的比值。可以认为每个像素不是正方形的。
DAR ------ Display Aspect Ratio
显示横纵比。最终显示的图像在长度单位上的横纵比。
SAR ------ Sample Aspect Ratio
采样横纵比。表示横向的像素点数和纵向的像素点数的比值。
0.10.Ffmpeg滤镜(Filters, filterchains,filtergraphs)
滤镜(Filters):在编码前,对原音视频使用libavfilter库中的滤镜进行处理,Ffmpeg内置了许多多媒体过滤器,可以通过多种方式组合它们。
分为两种滤镜:简单滤镜和复合滤镜
简单滤镜:
简单滤镜就是只有1个输入和输出的滤镜,使用-vf和-af分别对应视频和音频
复合滤镜:
复合滤镜就是那些不能简单的描述为一个线性处理过程应用到一个流的情况,例如包含多个输入输出。
复合滤镜使用-filter_complex进行设置
滤镜的使用一般是 滤镜名=由于冒号(隔开各个参数
滤镜链图(filtergraphs)是连接滤镜的有向图,它可以包含循环动作,也可以在多个滤镜间形成链路,每个链接都有一个连接到滤镜的输入和一个连接到滤镜的输出
一个滤镜链(filterchains)包含序列链接起来的滤镜,这个序列由","分隔各个滤镜
一个滤镜链图(filtergraphs)包含序列滤镜链,这个序列由";"分隔各个滤镜链
同一路的滤镜间用逗号(,)进行分割,不同路的滤镜间用分号进行分割(;)
https://blog.csdn.net/sinat_14826983/article/details/83043906
1.安装
首先登陆官网
{width="4.153543307086614in"
height="2.578740157480315in"}
选择中间的Window版本,然后看到有两个, 先讲讲第一个链接。
选择Windows builds from gyan.dev\
跳转到下载页面如下图:
{width="2.874015748031496in"
height="2.7559044181977255in"}
在页面中,选择release-full.7z下载。
再说说第二个链接
Windows builds by BtbN
点击后会跳转到github上面。如下图:
{width="3.0196850393700787in"
height="2.7913385826771653in"}
选择win64的gpl版本。然后下载下来。
添加系统环境变量。C:\ffmpeg-4.4-full_build\ffmpeg-4.4-full_build\bin(解压后文件夹地址),将该bin目录添加到系统环境变量中。在原有基础上添加新的变量前面要输入分号。步骤如图所示------
Win7
{width="2.7125984251968505in"
height="2.854330708661417in"}{width="2.7755905511811023in"
height="2.8622047244094486in"}
{width="2.7755905511811023in"
height="2.8622047244094486in"}{width="2.5984241032370954in"
height="2.866140638670166in"}
Win10
{width="3.2086614173228347in"
height="3.3779516622922134in"}
在PowerShell中输入:ffmpeg --version
{width="3.877952755905512in"
height="3.12992125984252in"}
出现上面的信息,则配置成功。
2.ffmpeg常用命令
2.0.查看视频信息
通过ffmpeg -i
input.mp4可以获取input.mp4的全部信息的文本。如果需要获取独立细节,可以通过------
1.获取视频时长
ffmpeg -i input.mp4 -hide_banner 2>&1 | findstr 'Duration'
其中-hide_banner选项是用来屏蔽 FFmpeg
标语和其它细节。另外,如果获取不到视频的时长信息,有可能是因为视频为直流数据,没有时间轴,可以通过-c
copy命令选项处理。
2.查看FFmpeg支持的所有格式
ffmpeg --formats
2.1.转换格式
1.默认转换ffmpeg -i input.flv output.mp4其他格式同理。
2.转换时保持源视频质量ffmpeg -i input.flv -qscale 0 output.mp4
2.2.从视频中提取音频
ffmpeg -i input.mp4 -vn output.mp3
2.3.调整视频分辨率
- 方式一
ffmpeg -i input.mp4 -filter:v scale=1280:720 -c:a copy output.mp4
- 方式二
ffmpeg -i input.mp4 -s 1280x720 -c:a copy output.mp4
调整视频的分辨率会比较耗时。
2.4.压缩视频文件
ffmpeg -i input.mp4 -vf scale=1280:-1 -c:v libx264 -preset veryslow -crf
24 output.mp4
2.5.从视频中提取图像
1.提取一帧ffmpeg -ss 50 -i input.mp4 -y -f image2 -vframes 1
output.jpg-ss后跟开始时间
2.提取所有关键帧到图片序列ffmpeg -i input.mp4 -r 1 -f image2
image-%2d.jpg
2.6.视频剪切
ffmpeg -ss 00:16:00 -t 00:01:00 -i input.mp4 -c:v copy -c:a copy
output.mp4
这里关于视频和音频的导出需要使用-c:v copy和-c:a
copy,不要使用-vcodec和-acodec。使用后者可能会导致视频在开头或是结尾的卡顿。
2.7.设置比特率
ffmpeg -i input.mp4 -b 1.5M output.mp4
设置比特率时,实验中使用-b 1.5M后,将38.6MB的原视频压缩到了13.8MB。
2.8.限制 cpu
ffmpeg -i input.flv -y -threads 1 output.mp4
如果想要降低对cpu的使用,-threads的值可以往小了给。
2.9.裁剪视频
ffmpeg -i input.mp4 -filter:v "crop=w:h❌y" output.mp4
-filter:v -- 表示视频过滤器。 crop -- 表示裁剪过滤器。\
w -- 我们想自源视频中裁剪的矩形的宽度。 \
h -- 矩形的高度。 \
x -- 我们想自源视频中裁剪的矩形的 x 坐标 。 \
y -- 矩形的 y 坐标。
2.10.视频播放速度
1.加速播放ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output.mp4
2.减速播放ffmpeg -i input.mp4 -vf "setpts=4.0*PTS" output.mp4
2.11.无损合并视频的多种方法
方法一:FFmpeg concat 协议
对于 MPEG 格式的视频,可以直接连接:
ffmpeg -i "concat:input1.mpg|input2.mpg|input3.mpg" -c copy
output.mpg
对于非 MPEG 格式容器,但是是 MPEG
编码器(H.264、DivX、XviD、MPEG4、MPEG2、AAC、MP2、MP3 等),可以包装进
TS 格式的容器再合并。在新浪视频,有很多视频使用 H.264
编码器,可以采用这个方法
ffmpeg -i input1.flv -c copy -bsf:v h264_mp4toannexb -f mpegts
input1.ts\
ffmpeg -i input2.flv -c copy -bsf:v h264_mp4toannexb -f mpegts
input2.ts\
ffmpeg -i input3.flv -c copy -bsf:v h264_mp4toannexb -f mpegts input3.ts
ffmpeg -i "concat:input1.ts|input2.ts|input3.ts" -c copy -bsf:a
aac_adtstoasc -movflags +faststart output.mp4
保存 QuickTime/MP4 格式容器的时候,建议加上 -movflags
+faststart。这样分享文件给别人的时候可以边下边看。
方法二:FFmpeg concat 分离器
这种方法成功率很高,也是最好的,但是需要 FFmpeg 1.1
以上版本。先创建一个文本文件 filelist.txt:
file 'input1.mkv'
file 'input2.mkv'
file 'input3.mkv'
然后:ffmpeg -f concat -i filelist.txt -c copy output.mkv
注意:使用 FFmpeg concat
分离器时,如果文件名有奇怪的字符,要在 filelist.txt 中转义。
方法三:Mencoder 连接文件并重建索引
这种方法只对很少的视频格式生效。幸运的是,新浪视频使用的 FLV
格式是可以这样连接的。对于没有使用 MPEG 编码器的视频(如 FLV1
编码器),可以尝试这种方法,或许能够成功。
mencoder -forceidx -of lavf -oac copy -ovc copy -o output.flv
input1.flv input2.flv input3.flv
方法四:使用 FFmpeg concat 过滤器重新编码(有损)
语法有点复杂,但是其实不难。这个方法可以合并不同编码器的视频片段,也可以作为其他方法失效的后备措施。\
ffmpeg -i input1.mp4 -i input2.webm -i input3.avi -filter_complex
'[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] concat=n=3:v=1:a=1
[v] [a]' -map '[v]' -map '[a]' <编码器选项> output.mkv
如你所见,上面的命令合并了三种不同格式的文件,FFmpeg concat
过滤器会重新编码它们。 注意这是有损压缩。[0:0] [0:1] [1:0]
[1:1] [2:0] [2:1]
分别表示第一个输入文件的视频、音频、第二个输入文件的视频、音频、第三个输入文件的视频、音频。
concat=n=3:v=1:a=1 表示有三个输入文件,输出一条视频流和一条音频流。
[v] [a] 就是得到的视频流和音频流的名字,注意在 bash 等 shell
中需要用引号,防止通配符扩展。
提示:
以上三种方法,在可能的情况下,最好使用第二种。第一种次之,第三种更次。第四种是后备方案,尽量避免。\
规格不同的视频合并后可能会有无法预测的结果。
有些媒体需要先分离视频和音频,合并完成后再封装回去。
对于 Packed B-Frames 的视频,如果封装成 MKV 格式的时候提示 Can't write
packet with unknown timestamp,尝试在 FFmpeg 命令的 ffmpeg 后面加上
-fflags +genpts
2.12.ffmpeg 视频实现各种特效
//渐入
ffmpeg i in.mp4 -vf fade=in:0:90 out.mp4
//黑白
ffmpeg i in.mp4 -vf lutyuv="u=128:v=128" out.mp4
//锐化
ffmpeg i in.mp4 -vf
unsharp=luma_msize_x=7:luma_msize_y=7:luma_amount=2.5 out.mp4
//反锐化
ffmpeg i in.mp4 -vf unsharp=7:7:-2:7:7:-2 out.mp4
//渐晕
ffmpeg i in.mp4 -vf vignette=PI/4 out.mp4
//闪烁渐晕
ffmpeg i in.mp4 -vf vignette='PI/4+random(1)*PI/50':eval=frame out.mp4
//视频颤抖
ffmpeg i in.mp4 -vf
crop="in_w/2:in_h/2:(in_w-out_w)/2+((in_w-out_w)/2)*sin(n/10):(in_h-out_h)/2+((in_h-out_h)/2)*sin(n/7)"
out.mp4
//色彩变幻
ffmpeg i in.mp4 -vf hue="H=2*PI*t:s=sin(2*PI*t)+1" out.mp4
//模糊处理
ffmpeg i in.mp4 -vf boxblur=5:1:cr=0:ar=0 out.mp4
//镜像翻转
ffmpeg i in.mp4 -vf
crop=iw/2:ih:0:0,split[left][tmp];[tmp]hflip[right];[left]pad=iw*2[a];[a][right]overlay=w
out.mp4
//水平翻转
ffmpeg i in.mp4 -vf geq=p(W-X\\,Y) out.mp4
//垂直翻转
ffmpeg i in.mp4 -vf vflip out.mp4
//浮雕效果
ffmpeg i in.mp4 -vf
format=gray,geq=lum_expr='(p(X,Y)+(256-p(X-4,Y-4)))/2' out.mp4
//均匀噪声
ffmpeg i in.mp4 -vf noise=alls=20:allf=t+u out.mp4
2.13.使用FFmpeg命令合并音视频(画幅)
- 合并音频和视频
ffmpeg -i video.mp4 -i audio.aac -c:v copy -c:a copy -bsf:a
aac_adtstoasc output.mp4
如果视频中已经包含了音频,替换视频中的音频,使用下面命令行
ffmpeg -i video.mp4 -i audio.aac -c:v copy -c:a copy -bsf:a
aac_adtstoascmap 0✌️0 -map 1🅰️0 output.mp4
- 横向合并视频
ffmpeg -i input1.mp4 -i input2.mp4 -lavfi hstack output.mp4
上面的命令虽然可以合并视频,两个视频可以正常播放,但是只保留了input1.mp4的音频。input1和input2必须同样的高度,如果不一样的高度可以使用-shortest参数来保证同样的高度。
合并多个视频,可以使用下面命令行:
ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 -lavfi hstack=inputs=3
output.mp4
其中input=3表示希望合并的视频的个数
- 纵向合并视频
ffmpeg -i input1.mp4 -i input2.mp4 -lavfi vstack output.mp4
- 网格合并视频
当多个视频时,还可以合并成网格状,比如2x2,3x3这种。但是视频个数不一定需要是偶数,如果是奇数,可以用黑色图片来占位。
ffmpeg -f lavfi -i color=c=black:s=1280x720 -vframes 1 black.png
该命令将创建一张1280*720的图片
然后就可以使用下面这个命令来合并成网格视频了,如果只有三个视频,可以选择上面创建的黑色图片替代。
ffmpeg -i top_left.mp4 -i top_right.mp4 -i bottom_left.mp4 -i
bottom_right.mp4 \ -lavfi
"[0:v][1:v]hstack[top];[2:v][3:v]hstack[bottom];[top][bottom]vstack"
-shortest 2by2grid.mp4
上面创建的是正规的2x2网格视频。想象一下,现在只有三个视频,我想把第一个视频摆放在第一行的中间,然后把第二、三个视频摆放在第二行。那么就可以使用下面两个命令了。
ffmpeg -f lavfi -i color=c=black:s=640x720 -vframes 1 black.png ffmpeg
-i black.png -i top_center.mp4 -i bottom_left.mp4 -i bottom_right.mp4
-lavfi
"[0:v][1:v][0:v]hstack=inputs=3[top];[2:v][3:v]hstack[bottom];[top][bottom]vstack"
-shortest 3_videos_2x2_grid.mp4
2.14.如何给视频添加字幕(ffmpeg-wiki翻译)
您可以使用以下两种过滤器之一来刻录文本字幕(硬字幕): subtitles或者
ass.
Subtitles 过滤器
使用 libass 库在输入视频之上绘制字幕。 此过滤器需要 ffmpeg编译
--enable-libass. 看到 [[subtitles video filter
documentation]{.underline}](http://ffmpeg.org/ffmpeg-filters.html#subtitles-1)的更多细节。
如果字幕是一个单独的文件,称为 subtitle.srt,你可以使用这个命令:
ffmpeg -i video.avi -vf subtitles=subtitle.srt out.avi
如果字幕嵌入在容器中 video.mkv, 你可以这样做:
ffmpeg -i video.mkv -vf subtitles=video.mkv out.avi
ass过滤器
与Subtitles过滤器相同,只是它不需要 libavcodec 和 libavformat 即可工作。
此过滤器需要 ffmpeg编译 --enable-libass. 在另一方面,它仅限于[[ASS
(Advanced Substation
Alpha)]{.underline}](http://en.wikipedia.org/wiki/SubStation_Alpha#Advanced_SubStation_Alpha)字幕文件。
见[[ass video filter
documentation]{.underline}](http://ffmpeg.org/ffmpeg-filters.html#ass)的更多细节。
ffmpeg -i video.avi -vf "ass=subtitle.ass" out.avi
如果你的副标题在 SubRip,
MicroDVD或任何其他支持的文本字幕,您必须在使用此过滤器之前将其转换为
ASS:
ffmpeg -i subtitle.srt subtitle.ass
Windows用户必须 [[setup font
paths]{.underline}](http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=10&t=318&start=20)
获得libass工作。
基于图片的字幕
你可以把 "基于图像的"字幕烧进一部电影中,通过使用[[overlay video
filter]{.underline}](http://ffmpeg.org/ffmpeg-filters.html#overlay-1)以覆盖图像。
例如,dvdsub 是一种基于图片的叠加字幕。 在单独的流中带有 dvdsub 字幕的
MKV 示例:
ffmpeg -i input.mkv -filter_complex "[0:v][0:s]overlay[v]" -map
"[v]" -map 0:a <output options> output.mkv
如果您有多个字幕流,您可以通过替换来选择使用哪一个 [0:s]和
[0:s:0]选择第一个字幕流或 [0:s:1]选择第二个字幕流,依此类推。
另请参见[[the official
documentation]{.underline}](http://ffmpeg.org/ffmpeg.html);
搜索"hardcode"。
有时,当输入文件有多个音频流并且其中一些可能有问题时,添加此过滤器会产生破坏编码的副作用;
在这种情况下,选择一个(或多个)音频流应该可以解决问题:
ffmpeg -i input.ts -filter_complex "[0:v][0:s]overlay[v]" -map
"[v]" -map 0🅰️0 <output options> output.mkv
Windows
需要注意的是在Windows上您可能必须采取适当措施,增加设置您的fontconfig等:[https://ffmpeg.zeranoe.com/forum/viewtopic.php?f=7&t=2554]{.underline}
3.ffplay常用命令和注意事项
3.1.预览或测试视频或音频文件
ffplay input.mp4\
类似地,音频文件也可以使用ffplay进行播放。\
ffplay input.mp3
注意事项: 在window7
64bit下安装了ffmpeg,然后用ffplay命令播放声音时发生这个错误:SDL_OpenAudio
(2 channels, 44100 Hz): WASAPI can't initialize audio client
那么只能播放视频图像而不能播放视频声音。
只要设置环境一个变量SDL_AUDIODRIVER=directsound或者winmm即可。
可在调用ffplay前输入set SDL_AUDIODRIVER=directsound。
或写一个start.bat加入下面代码:
SDL_AUDIODRIVER=directsound\
ffplay myVideo.mp4
3.2.过滤器
1、视频过滤器
1)视频旋转播放
ffplay test.mp4 -vf transpose=1
(0:逆时针旋转90°然后垂直翻转;;1:顺时针旋转90°;2:逆时针旋转90°;3:顺时针旋转90°然后水平翻转)
2)视频水平翻转播放
ffplay test.mp4 -vf hflip
3)视频垂直翻转播放
ffplay test.mp4 -vf vflip
4)视频水平翻转,并且再顺时针旋转90度播放
ffplay test.mp4 -vf transpose=1,hflip
2、音频过滤器
1)音频变速播放
ffplay test.mp4 -af atempo=2 (atempo的范围【0.5, 2】)
2)视频变速播放
ffplay test.mp4 -vf setpts=0.5 * PTS (setpts的范围是【0.25,4】)
3)音视频同时变速播放
ffplay test.mp4 -vf setpts=PTS/2 -af atempo=2
4.ffprobe常用命令
ffprobe常用的参数比较多,可以通过ffprobe --help来查看详细的帮助信息:
4.1.查看多媒体数据包信息
ffprobe -show_packets inuput.flv
通过show_packets查看的多媒体数据包信息使用PACKET标签括起来,其中包含信息主要如下表:
{width="6.673228346456693in"
height="2.783464566929134in"}
PACKET字段说明
4.2.分析多媒体的封装格式
ffprobe -show_format output.mp4
上述命令可以查看多媒体的封装格式,其使用FORMAT标签括起来显示:
{width="6.452755905511811in"
height="2.181101268591426in"}
format字段说明
4.3.查看视频文件中的帧信息
通过-show_frames参数可以查看每一帧的信息
ffprobe -show_frames inuput.flv\
查看视频文件中的帧信息,输出的帧信息使用FRAME标签括起来:
{width="5.881889763779528in"
height="3.625984251968504in"}
frame字段说明
4.4.查看多媒体文件中的流信息
ffprobe -show_streams inuput.flv
流的信息将使用STREAM标签括起来:
{width="6.551181102362205in"
height="3.547244094488189in"}
{width="6.291338582677166in"
height="1.5433070866141732in"}
stream字段说明
4.5.多种格式输出
- 通过以下得到XML输出格式命令如下:
ffprobe -of xml -show_streams inuput.xml
- 通过以下命令得到INI格式的输出:
ffprobe -of ini-show_streams inuput.flv
- 通过以下命令输出JSON格式:
ffprobe -of json -show_packets inuput.flv
这种格式的数据可以用在以JSON解析为主的业务中。
- 通过以下命令输出CSV格式:
fforobe -of csv -show_packets inuput.flv
CSV格式输出后可使用EXCEL打开表格形象
5.技术分享
5.1.实时生成字符画
示例图像帧文本:
h1ri . i3+i,
irrr;.;i+:i,
.5mBBmmBx3risi9:+:;.
.#mBmmmB&xGxGGG3hiiss::1G&
~xGGGG9!!9hsiiiii;ri:+;😒!
:x!si:&11!GBs9B~19!!G!&G1!!3
!3hshrssrsris1sr11r;ir5533
1h11sG1sG1sii1s19&&31rh,
9!~!sGshsiisGG&~x5ssi
- ;ri:. s;1sx!hsrriGGx&G5shhrr;
ri+ .sr+ -r; :.xsh51sr9!!55hshh11sr :i,.;i
:ssr;: :s1s, si. hhh&&!91G3995shhh11si ;r -
x5;,:rrrrrrrriirrrriiir:;;+. .rr+ . ~xGG3&~h3s9!G5sss1 .;r,
x9i, .-::-. .-1993:, .,:s1i .,+:,-&&&~3555GGh;+. :r5r,. ,;
G1- ,:155s+. ,:9!!!!3;,
,:9!i11r:::x#&x~xG&~hh~&&!93i-:G&! ;s31!3:,,:9
s: -rs3335h:,
.-9G!!993;-.-rx!!!hisr;h&!9&~~&G3x~&&&&5s:rG&~5s:rss1G!Gx:-:5
-139!9335s+ ,:G!!99r-,-1!!GG!!Bm#iiri;iiri;+:;;ir;::::;+:iir+.+h!GGGr-,:
.;539935h:. +s!933+...;GGGGGx#hG5hhirri;:++:;:::;::::;isi35s .:GG!G;. .
-s33355;, ,:!93+.
.+5GG!Gi#m&!G&&xG::iii:;iii;;:+i!&&xGs -s!G5-.
.:h333r- -s!i, ,;xG!:-rBmBG!!!r:;;:::;;;;;::;GGG!9!, ,:!!i,
,i551:. ,+r+ .+GG1-,Bm~93553:i;;::;;;;;;:::GGx933G .:9:
-ss;, ,;h+,.&~x!93+:::;;;:;ii;;;:+:+;xx~~9 .,.
.-+. .. ,~hh&x:;;;;;;;:;:;:::::::;h!&~~.
..hhh~&i:;irsrri::;;;:;:::::;hG&~:
B~h~!xGxGGsr;i;::+:::+++:::,xx&&G
~B&xx&&&&x111hs5G!x!ss9s;:. 1&~~9
使用ege demo就实现了类似的功能, 打开本程序, 按下空格键,
选择一个输出文本, 输入使用的分辨率, 再选择一个输入视频,
就可以看到美美的字符画啦~
百度网盘下载地址: http://pan.baidu.com/s/1mhKae3u
5.2.基于Ffmpeg实现屏幕录制
基于Ffmpeg实现屏幕录制
录制屏幕
为了实现对于Window桌面录制,有两种方式进行采集:
DirectShow 设备
Gdigrab设备
其基本命令行如下:
//Dshow设备
ffmpeg -f dshow -I video="screen-capture-recorder" output.mkv
//gdigrab设备 采集整个桌面
ffmpeg -f gdigrab -framerate 30 -I desktop output.mkv
这两个命令默认都是采用x264
进行编码,在本地CPU不是足够高的情况下,录制的视频画面根本看不清楚,这是因为编码效率太低导致;
为了提高录制效果,我们可以采用无损编码+提高编码速度方式进行录制,具体命令如下:
ffmpeg -framerate 30 -f gdigrab -I desktop -c:v libx264rgb -crf 0
-preset ultrafast output.mkv
或者
ffmpeg -framerate 30 -f gdigrab -I desktop -c:v libx264rgb -preset:v
ultrafast -tune:v zerolatency output.mkv
关于Ffmpeg屏幕采集可以参考
https://trac.ffmpeg.org/wiki/Capture/Desktop文章
关于H264编码方面的知识可以参考https://trac.ffmpeg.org/wiki/Encode/H.264文章
录制声音
在上面提到过录制屏幕除了采用gdigrab外,还可以采用dshow方式;它们的区别就是:gdigrab设置仅支持截取屏幕信息,对声音的录制是不支持的,而show方式可以支持录制屏幕和声音。
这个dshow软件的下载信息如下:
1、编译好的下载地址是:
http://sourceforge.net/projects/screencapturer/
2、源码地址是:
https://github.com/rdp/screen-capture-recorder-to-video-windows-free
为了使系统能识别出dshow设备,我们首先需要进行注册,为了去掉不必要的文件,我们只提取四个dll:
Screen-capture-recorder.dll
Screen-capture-recorder-x64.dll
Audio_sniffer-x64.dll
Audio_sniffer.dll
注册命令行如下:
//注册屏幕录制设备(我们采用32位的ffmpeg,可以不用注册带x64的dll)
Regsvr32 /s screen-capture-recorder.dll
//注册虚拟音频设备
Regsvr32 /s audio_sniffer.dll
注册成功后,可以采用以下命令进行检查是否注册成功
ffmpeg -list_devices true -f dshow -I dummy
系统输出大致如下:{width="5.708333333333333in"
height="1.5520833333333333in"}
"screen-capture-recorder" 这个就是桌面捕获设备,用于录制屏幕
"virtual-audio-capturer" 这个是音频捕获设备,用于录制声音
-f dshow -I audio="virtual-audio-capturer"
这代表声音从"virtual-audio-capturer"音频设备获取
为了能够同时录制声音和画面,我们可以使用以下命令进行采集:
ffmpeg -framerate 30 -f gdigrab -I desktop -f dshow -I
audio="virtual-audio-capturer" -c:v libx264rgb -preset:v ultrafast
-tune:v zerolatency output.mp4
用vlc打开录制文件,可以看书画面显示正常以及声音正常被播放处理,截图如下:
{width="7.59166447944007in"
height="4.324305555555555in"}
以上就是关于ffmpeg录制window桌面的全部过程了,欢迎大家交流~
参阅
FFmpeg 音视频处理入门基础概念
https://blog.csdn.net/sinat_14826983/article/details/83043906
Windows安装ffmpeg,使用ffmpeg从视频中的抽取图像
FFMpeg无损合并视频的多种方法
通过 ffmpeg 无损剪切与拼接视频方法
利用FFMPEG进行视频分割
ffmpeg视频压缩速度_使用ffmpeg修改视频速度
ffplay播放没有声音SDL_OpenAudio (2 channels, 44100 Hz): WASAPI can't
initialize audio client
ffmpeg批量处理(图片文字水印批量处理)
https://blog.csdn.net/qq_45753908/article/details/102568691
ffmpeg 视频实现各种特效
http://m.mamicode.com/info-detail-2635863.html
使用FFmpeg命令合并音视频
https://blog.csdn.net/qq_33349051/article/details/104061448
ffmpeg 硬压字幕的实现
https://blog.csdn.net/ternence_hsu/article/details/108437008
使用 FFMPEG 命令为视频嵌入字幕
https://blog.csdn.net/weixin_33929309/article/details/94308779
可移除的方式嵌入字幕
https://www.cnblogs.com/freedom-try/p/15200670.html
ffmpeg 提取音频,音频转换,添加字幕
通过ffmpeg和opencv生成视频的缩略图。
https://github.com/ximikang/ffmpegThumbnail
关于实现视频预览缩略图功能
https://blog.csdn.net/printf_scnaf/article/details/108256985
ffprobe常用命令总结
https://blog.51cto.com/u_12204415/3804327
使用ege+ffmpeg解码+播放视频, 实时生成字符画
https://xege.org/ege_ffmpeg_char_movie.html
基于Ffmpeg实现屏幕录制
https://blog.csdn.net/c_base_jin/article/details/106773589
Ffmpeg 支持的所有格式列表
https://blog.csdn.net/ustcxiangchun/article/details/6981914
《Ffmpeg从入门到精通》读书笔记(一)