欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【冬察冬见】FFmpeg系列学习笔记

程序员文章站 2022-03-04 10:09:02
...

【冬察冬见】FFmpeg系列学习笔记

综述

FFmpeg是领先的多媒体框架, 能够解码、 编码、 转码、 混流、 解密、 流媒体、 过滤和播放人类和机器创造的几乎任何东西。

FFmpeg的名称来自MPEG视频编码标准,前面的“FF”代表“Fast Forward”,FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。可以轻易地实现多种视频格式之间的相互转换。

FFmpeg支持多种格式,涵盖最隐晦的古代格式和最前沿格式。 不管这些音视频是由哪个标准委员会、 社区或公司设计的, 它都能处理。

FFmpeg具有很高的可移植性。FFmpeg可以在各种构建环境、 机器体系结构和配置下, 能跨Linux、 Mac OS X、 Microsoft Windows、 BSDs、 Solaris等编译、 运行并通过我们的测试基础结构。

FFmpeg包含可由应用程序使用的libavcodec、 libavutil、 libavformat、 libavfilter、 libavdevice、 libswscale和libswresample。 以及ffmpeg、 ffplay和ffprobe, 可供最终用户转码和播放。

FFmpeg项目试图为应用程序开发人员和最终用户提供最好的技术解决方案。 为了实现这一点, FFmpeg结合了最好的*软件选项可用,保持对其他lib的依赖性较低, 并最大限度地实现FFmpeg部分之间的代码共享。

作为开源代码,FFmpeg欢迎所有人来做出贡献,如漏洞补丁、 代码拉取请求、错误报告、捐款或任何其他类型的贡献。

当然,安全性是一个高度优先事项, 代码审查总是在考虑安全性的情况下进行的。 尽管由于涉及不可信数据的大量代码, 安全问题是不可避免的, 因此当发现新的安全问题时,FFmpeg社区会尽可能快地更新最新的稳定版本。

FFmpeg的组成

1)ffmpeg
命令行工具。 能够在多媒体文件的多种格式间转换。
2)ffplay
基于SDL和FFmpeg库的简易媒体播放器
3)ffprobe
一种简单的多媒体流分析器

面向开发人员的FFmpeg库

1)libavutil是一个库, 包含用于简化编程的函数, 包括随机数生成器、 数据结构、 数学例程、 核心多媒体实用程序等等。

2)libavcodec是一个库, 包含用于音频 / 视频编解码器的解码器和编码器。

3)libavformat是一个包含用于多媒体容器格式的解复用器和复用器的库。

4)libavdevice是一个包含输入和输出设备的库, 用于从许多常见的多媒体输入 / 输出软件框架( 包括Video4Linux、 Video4Linux2、 VfW和ALSA) 中获取和呈现这些设备。

5)libavfilter是一个包含媒体过滤器的库。

6)libswscale是一个执行高度优化的图像缩放和颜色空间 / 像素格式转换操作的库。

7)libswresample是一个执行高度优化的音频重采样、 重采样和采样格式转换操作的库。

 

基本概念

媒体流(Stream):表示时间轴上的一段连续数据,如一段声音数据、一段视频数据或一段字幕数据,可以是压缩的,也可以是非压缩的,压缩的数据需要关联特定的编解码器

数据帧/数据包(Frame/Packet):通常,一个媒体流是由大量的数据帧组成的,对于压缩数据,帧对应着编解码器的最小处理单元,分属于不同媒体流的数据帧交错存储于容器之中。

一般情况下:
Frame对应压缩前的数据,Packet对应压缩后的数据。
编解码器(Codec):以帧为单位实现压缩数据和原始数据之间的相互转换的

复用(mux):把不同的流按照某种容器的规则放入容器,这种行为叫做复用(mux)
如字母、音频、视频的合成

解复用(demux):把不同的流从某种容器中解析出来,这种行为叫做解复用(demux)
如字母、音频、视频的分拆

容器/文件(Conainer/File):即特定格式的多媒体文件,比如mp4、flv、mkv等。

帧率:帧率也叫帧频率,帧率是视频文件中每一秒的帧数,肉眼想看到连续移动图像至少需要15帧。

码率:比特率(也叫码率,数据率)是一个确定整体视频/音频质量的参数,秒为单位处理的位数,码率和视频质量成正比,在视频文件中中比特率用bps来表达。

码率和帧率是视频文件的最重要的基本特征,对于他们的特有设置会决定视频质量。如果我们知道码率和时长那么可以很容易计算出输出文件的大小。

FFMPEG环境搭建

FFMPEG命令行环境搭建如下:
1)到ffmpeg官方下载已经编译好的Windows shared库;

2) 将执行文件ffmpeg.exe ffplay.exe ffprobe.exe拷贝到C:\Windows\ffmpeg;

3) 将相应的动态库拷贝到C:\Windows\ffmpeg;

  1. 在命令行窗口输入ffmpeg -version 查看版本,以却确定环境是否搭建成功。

简介

FFmpeg命令是在ffmpeg.exe可执行文件环境下执行,ffmpeg.exe用于音视频的转码,加水印,去水印,视频剪切,提取音频,提取视频,码率控制等等功能。

命令行语法如下
ffmpeg [global_options] {[input_file_options] -i input_url} … {[output_file_options] output_url} …

命令说明

ffmpeg是一个非常快速的视频和音频转换器,也可以从现场音频/视频源抓取。
它还可以在任意采样率之间转换,并通过高质量的多相滤波器动态调整视频大小。

ffmpeg读取由-i选项指定的任意数量的输入“文件”(可以是常规文件、管道、网络流、抓取设备等),
并写入由普通输出url指定的任意数量的输出“文件”。
在命令行中找到的任何不能解释为选项的内容都将被视为输出url。

原则上,每个输入或输出url都可以包含任意数量的不同类型的流(视频/音频/字幕/附件/数据)。
允许的流的数量和/或类型可以由容器格式限制。
选择哪些流,从哪些输入将进入哪些输出是自动完成或与-map选项。

要引用选项中的输入文件,必须使用它们的索引(基于0)。例如,第一个输入文件是0,第二个输入文件是1,等等。类似地,文件中的流通过它们的索引来引用。例如,2:3表示第三个输入文件中的第四个流。

通常,选项应用于下一个指定的文件。因此,顺序很重要,您可以在命令行上多次使用相同的选项。然后将每个引用应用于下一个输入或输出文件。此规则的例外情况是全局选项(例如详细级别),应该首先指定全局选项。

不要混合输入和输出文件–首先指定所有输入文件,然后指定所有输出文件。也不要混用属于不同文件的选项。所有选项仅应用于下一个输入或输出文件,并在文件之间重置。

举个栗子
将输出文件的视频比特率设置为64 kbit/s
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.avi

要强制输出文件的帧速率为24 fps,请执行以下操作:
ffmpeg -i input.avi -r 24 output.avi

要将输入文件的帧速率(仅对原始格式有效)强制为1 fps,将输出文件的帧速率强制为24 fps:
ffmpeg -r 1 -i input.m2v -r 24 output.avi

获取封面
ffmpeg -ss 00:00:10 -i test1.flv -f image2 -y test1.jpg

参数介绍

-i ffmpmg -i pingcap-xxx.mp4 输入您要处理的视频文件路径

-b:v k−bufsizek -b:v 64k -bufsize 64k 要将输出文件的视频比特率设置为64 kbit / s

-r ffmpeg -i input.avi -r 24 output.avi 要强制输出文件的帧频为24 fps

-c:v -c:v libx264 ffmpeg -i input -c:v libx264 -preset slow -crf 22-c:a copy output.mkv

-L license

-h 帮助

-fromats 显示可用的格式,编解码的,协议的。。。

-f fmt 强迫采用格式fmt

-I filename 输入文件

-y 覆盖输出文件

-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持

-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持

-title string 设置标题

-author string 设置作者

-copyright string 设置版权

-comment string 设置评论

-target type 设置目标文件类型(vcd,svcd,dvd) 所有的格式选项(比特率,编解码以及缓冲区大小)自动设置 ,只需要输入如下的就可以了:
ffmpeg -i myfile.avi -target vcd /tmp/vcd.mpg

-hq 激活高质量设置

-itsoffset offset 设置以秒为基准的时间偏移,该选项影响所有后面的输入文件。该偏移被加到输入文件的时戳,定义一个正偏移意味着相应的流被延迟了 offset秒。 [-]hh:mm:ss[.xxx]的格式也支持

视频选项
-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 包括了模块名和参数,用空格分开

音频选项
-ab bitrate 设置音频码率

-ar freq 设置音频采样率

-ac channels 设置通道 缺省为1

-an 不使能音频纪录

-acodec codec 使用codec编解码

音视频捕获选项
-vd device 设置视频捕获设备。比如/dev/video0

-vc channel 设置视频捕获通道 DV1394专用

-tvstd standard 设置电视标准 NTSC PAL(SECAM)

-dv1394 设置DV1394捕获

-av device 设置音频设备 比如/dev/dsp

高级选项
-map file:stream 设置输入流映射

-debug 打印特定调试信息

-benchmark 为基准测试加入时间

-hex 倾倒每一个输入包

-bitexact 仅使用位精确算法 用于编解码测试

-ps size 设置包大小,以bits为单位

-re 以本地帧频读数据,主要用于模拟捕获设备

-loop 循环输入流。只工作于图像流,用于ffserver测试

更多复杂栗子

ffmpeg命令 提取音视频数据 保留封装格式
ffmpeg -i test.mp4 -acodec copy -vn audio.mp4
ffmpeg -i test.mp4 -vcodec copy -an video.mp4

提取视频
保留编码格式:ffmpeg -i test.mp4 -vcodec copy -an test_copy.h264
强制格式:ffmpeg -i test.mp4 -vcodec libx264 -an test.h264

提取音频
保留编码格式:ffmpeg -i test.mp4 -acodec copy -vn test.aac
强制格式:ffmpeg -i test.mp4 -acodec libmp3lame -vn test.mp3

ffmpeg命令提取像素格式和PCM数据
ffmpeg命令提取像素格式

提取YUV
提取3秒数据,分辨率和源视频一致
ffmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p yuv420p_orig.yuv

提取3秒数据,分辨率转为320x240
ffmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p -s 320x240 yuv420p_320x240.yuv

提取RGB
提取3秒数据,分辨率转为320x240
ffmpeg -i test.mp4 -t 3 -pix_fmt rgb24 -s 320x240 rgb24_320x240.rgb

RGB和YUV之间的转换
ffmpeg -s 320x240 -pix_fmt yuv420p -i yuv420p_320x240.yuv -pix_fmt rgb24 rgb24_320x240_2.rgb

提取PCM
ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -f s16le 48000_2_s16le.pcm

ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -sample_fmt s16 out_s16.wav

ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -codec:a pcm_s16le out2_s16le.wav

ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -f f32le 48000_2_f32le.pcm

ffmpeg -i test.mp4 -t 10 -vn -ar 48000 -ac 2 -f f32le 48000_2_f32le_2.pcm

ffmpeg命令转封装
保持编码格式:

ffmpeg -i test.mp4 -vcodec copy -acodec copy test_copy.ts

ffmpeg -i test.mp4 -codec copy test_copy2.ts

改变编码格式:
ffmpeg -i test.mp4 -vcodec libx265 -acodec libmp3lame out_h265_mp3.mkv

修改帧率:
ffmpeg -i test.mp4 -r 15 -codec copy output.mp4 (错误命令)
ffmpeg -i test.mp4 -r 15 output2.mp4

修改视频码率:
ffmpeg -i test.mp4 -b 400k output_b.mkv (此时音频也被重新编码)

修改视频码率:
ffmpeg -i test.mp4 -b:v 400k output_bv.mkv

修改音频码率:
ffmpeg -i test.mp4 -b:a 192k output_ba.mp4
如果不想重新编码video,需要加上-vcodec copy

修改音视频码率:
ffmpeg -i test.mp4 -b:v 400k -b:a 192k output_bva.mp4

修改视频分辨率:
ffmpeg -i test.mp4 -s 480x270 output_480x270.mp4

修改音频采样率:
ffmpeg -i test.mp4 -ar 44100 output_44100hz.mp4

ffmpeg命令过滤器
生成测试文件
找三个不同的视频每个视频截取10秒内容
ffmpeg -i 沙海02.mp4 -ss 00:05:00 -t 10 -codec copy 1.mp4

ffmpeg -i 复仇者联盟3.mp4 -ss 00:05:00 -t 10 -codec copy 2.mp4

ffmpeg -i 红海行动.mp4 -ss 00:05:00 -t 10 -codec copy 3.mp4

如果音视频格式不统一则强制统一为 -vcodec libx264 -acodec aac

将上述1.mp4/2.mp4/3.mp4转成ts格式

ffmpeg -i 1.mp4 -codec copy -vbsf h264_mp4toannexb 1.ts

ffmpeg -i 2.mp4 -codec copy -vbsf h264_mp4toannexb 2.ts

ffmpeg -i 3.mp4 -codec copy -vbsf h264_mp4toannexb 3.ts

转成flv格式

ffmpeg -i 1.mp4 -codec copy 1.flv

ffmpeg -i 2.mp4 -codec copy 2.flv

ffmpeg -i 3.mp4 -codec copy 3.flv

分离某些封装格式(例如MP4/FLV/MKV等)中的H.264的时候,需要首先写入SPS和PPS,否则会导致分离出来的数据没有SPS、PPS而无法播放。H.264码流的SPS和PPS信息存储在AVCodecContext结构体的extradata中。需要使用ffmpeg中名称为“h264_mp4toannexb”的bitstream filter处理

开始拼接文件

以MP4格式进行拼接

方法1:ffmpeg -i “concat:1.mp4|2.mp4|3.mp4” -codec copy out_mp4.mp4

方法2:ffmpeg -f concat -i mp4list.txt -codec copy out_mp42.mp4

以TS格式进行拼接

方法1:ffmpeg -i “concat:1.ts|2.ts|3.ts” -codec copy out_ts.mp4

方法2:ffmpeg -f concat -i tslist.txt -codec copy out_ts2.mp4

以FLV格式进行拼接

方法1:ffmpeg -i “concat:1.flv|2.flv|3.flv” -codec copy out_flv.mp4

方法2:ffmpeg -f concat -i flvlist.txt -codec copy out_flv2.mp4

方法1只适用部分封装格式,比如TS

建议:

(1)使用方法2进行拼接

(2)转成TS格式再进行拼接

fmpeg命令图片与视频互转​
截取一张图片

ffmpeg -i test.mp4 -y -f image2 -ss 00:00:02 -vframes 1 -s 640x360 test.jpg

ffmpeg -i test.mp4 -y -f image2 -ss 00:00:02 -vframes 1 -s 640x360 test.bmp

-i 输入

-y 覆盖

-f 格式 image2 一种格式

-ss 起始值

-vframes 帧 如果大于1 那么 输出加%03d test%03d.jpg

-s 格式大小size

转换视频为图片(每帧一张图):

ffmpeg -i test.mp4 -t 5 -s 640x360 -r 15 frame%03d.jpg

图片转换为视频:

ffmpeg -f image2 -i frame%03d.jpg -r 25 video.mp4

从视频中生成GIF图片

ffmpeg -i test.mp4 -t 5 -r 1 image1.gif

ffmpeg -i test.mp4 -t 5 -r 25 -s 640x360 image2.gif

将 GIF 转化为 视频

ffmpeg -f gif -i image2.gif image2.mp4

命令原理详细说明

ffmpeg中每个输出的转码过程可以通过下图来描述:
【冬察冬见】FFmpeg系列学习笔记
            
    
    博客分类: 技术总结  
图1

ffmpeg调用libavformat库(包含解复用器)读取输入文件并从中获取包含编码数据的数据包。当有多个输入文件时,ffmpeg试图通过跟踪任何活动输入流上的最低时间戳来保持它们的同步。
编码的数据包随后被传递给解码器(除非为流选择了streamcopy,请参阅进一步的描述)。解码器产生未压缩的帧(原始视频/PCM音频/…),可通过滤波进一步处理(见下一节)。过滤之后,帧被传递给编码器,编码器对帧进行编码并输出编码包。最后,这些数据被传递给muxer,muxer将编码的数据包写入输出文件。

过滤
在编码之前,ffmpeg可以使用libavfilter库中的过滤器处理原始音频和视频帧。几个链式过滤器形成一个过滤器图。ffmpeg区分了两种类型的filtergraphs:简单和复杂。

简单滤波器图
简单的filtergraphs是那些只有一个输入和输出,两个都是相同类型的。在上图中,它们可以通过在解码和编码之间插入一个附加步骤来表示:
【冬察冬见】FFmpeg系列学习笔记
            
    
    博客分类: 技术总结  
图2

简单的filtergraphs配置了per-stream-filter选项(视频和音频分别使用-vf和-af别名)。视频的简单filtergraph可以如下所示:
【冬察冬见】FFmpeg系列学习笔记
            
    
    博客分类: 技术总结  
图3

复合过滤图
复杂过滤图不能简单地描述为应用于一个流的线性处理链。例如,当图形有多个输入和/或输出时,或者当输出流类型不同于输入时,就是这种情况。它们可以用下图表示
【冬察冬见】FFmpeg系列学习笔记
            
    
    博客分类: 技术总结  

使用-filter\u Complex选项配置复杂filtergraphs。注意,这个选项是全局的,因为一个复杂的filtergraph,就其性质而言,不能明确地与一个流或文件相关联。

-lavfi选项相当于-filter\u complex。

复杂filtergraph的一个小例子是叠加滤波器,它有两个视频输入和一个视频输出,其中一个视频叠加在另一个视频上。它的音频对应物是amix滤波器。

流拷贝
流复制是通过向-codec选项提供copy参数来选择的模式。它使得ffmpeg省略了特定流的解码和编码步骤,因此只进行解复用和muxing。它对于更改容器格式或修改容器级别元数据非常有用。在这种情况下,上述图表将简化为:
【冬察冬见】FFmpeg系列学习笔记
            
    
    博客分类: 技术总结  
图5

由于没有解码或编码,所以速度非常快,没有质量损失。然而,由于许多因素,在某些情况下,它可能无法工作。应用过滤器显然也是不可能的,因为过滤器可以处理未压缩的数据。