文章目录
一、概念
容器
视频文件本身其实是一个容器(container),里面包括了视频和音频,也可能有字幕等其他内容。
常见的容器格式有以下几种。一般来说,视频文件的后缀名反映了它的容器格式。
- MP4
- MKV
- WebM
- AVI
下面的命令查看 FFmpeg 支持的容器
$ ffmpeg -formats
编码格式
视频和音频都需要经过编码,才能保存成文件。不同的编码格式(CODEC),有不同的压缩率,会导致文件大小和清晰度的差异。常用的视频编码格式如下:
H.262
H.264
H.265
上面的编码格式都是有版权的,但是可以免费使用。此外,还有几种无版权的视频编码格式。
VP8
VP9
AV1
常用的音频编码格式如下:
MP3
AAC
上面所有这些都是有损的编码格式,编码后会损失一些细节,以换取压缩后较小的文件体积。无损的编码格式压缩出来的文件体积较大,这里就不作介绍了。
下面的命令可以查看 FFmpeg 支持的编码格式,视频编码和音频编码都在内。
$ ffmpeg -codecs
编码器
编码器(encoders)是实现某种编码格式的库文件。只有安装了某种格式的编码器,才能实现该格式视频/音频的编码和解码。
以下是一些 FFmpeg 内置的视频编码器。
- libx264:最流行的开源 H.264 编码器
- NVENC:基于 NVIDIA GPU 的 H.264 编码器
- libx265:开源的 HEVC 编码器
- libvpx:谷歌的 VP8 和 VP9 编码器
- libaom:AV1 编码器
音频编码器如下: - libfdk-aac
- aac
下面的命令可以查看 FFmpeg 已安装的编码器
$ ffmpeg -encoders
媒体流
一个容器(比如MP4文件)中可以有多个流。下面是音视频领域中一些常见的媒体流
- 视频流
- 音频流
- 字幕流
复用器与解复用器
- 复用器:把多路原始流按一定的规则组成成一个新的音视频文件(例如:把一个纯视频流、一个纯音频流和一个纯字幕流组合成一个mp4文件);
- 解复用器:把一个新的音视频文件按一定的规则拆分成多路原始流(例如:把一个mp4文件,拆分成纯视频流、纯音频流和纯字幕流)。
二、Ffmpeg命令使用格式
FFmpeg 的命令行参数非常多,可以分成五个部分。
$ ffmpeg {1} {2} -i {3} {4} {5}
上面命令中,五个部分的参数解释:
- 全局参数
- 输入文件参数
- 输入文件
- 输出文件参数
- 输出文件
如果参数太多的时候,为了便于查看,ffmpeg 命令可以写成多行。
$ ffmpeg \
[全局参数] \
[输入文件参数] \
-i [输入文件] \
[输出文件参数] \
[输出文件]
三、FFmpeg库介绍
Ffmpeg常用的库:
-
libavutil
核心工具库,例如log模块。在ffmpeg中很多功能模块都会依赖avutil库作一些基本的音视频操作。 -
libavformat
文件格式和协议库,该模块是最重要的模块之一,封装了Protocol层和Demuxer、Muxer层。 -
libavcodec
编解码库,封装了一些基本的Codec层。但是一些Codec是具备自己的License的,所以ffmpeg是没有默认把这类的库添加进来的,例如:libx264,FDK-AAC等库。ffmpeg就像一个平台一样,可以将第三方的Codec以插件的方式添加进来,然后为开发者提供统一的接口,进行使用。 -
libswresample
该模块用于音频重采样,可以对数字音频进行声道数、数据格式、采样率等多种基本信息进行转换。例如:把一段音频的声道由双声道转换成单声道的数据,就可以通过该库进行操作。 -
libswscale
该模块提供了将图像进行格式信息转换的模块。例如:可以将YUV数据转换成RGB数据,可以将1280720的尺寸的数据缩放尺寸至800480的数据。 -
libavfilter
音视频滤镜库,该库提供了音频和视频特效的处理功能。 -
libavdevice
输入输出设备库。编译时需要先编译SDL,因为此库是以来SDL的,该设备模块库播放声音与播放视频使用的都是SDL库。 -
libpostproc
该年模块用于后期处理,与libavfilter库配合使用。
四、Ffmpeg常用函数
关于初始化和注册相关的函数
- av_register_all():注册所有的组建,4.0及以上版本已经弃用了
- avdevice_register_all():对设备进行注册,如果我们要捕捉屏幕进行录制屏幕,捕捉摄像头进行录制视频,捕捉麦克风录制麦克风声音时,就需要使用到该函数,首先进行注册。例如(windows下的dshow,Linux下的V4L2等);
- avformat_network_init():初始化网络库以及网络加密协议相关的库,我们在推流或者拉流时就会使用到。
封装格式相关函数
- avformat_alloc_context():负责申请一个AVFormatContext上下文结构体的内存,并进行简单的初始化,以提供给其他函数使用;
- avformat_free_context():释放不使用的AVFormatContext;
- avformat_close_input():关闭解复用器。如果使用该函数进行关闭的话,就可以不使用avformat_free_context()进行释放;
- avformat_open_input():打开输入视频文件;
- avformat_find_stream_info():获取视频文件信息;
- av_read_frame():读取音视频包;
- avformat_seek_file():根据时间戳定位文件的位置;例如我们托方播放器的进度条进行快近和快退时,就可以使用此函数进行定位播放;
- av_seek_frame():根据流的大小定位文件的位置;
封装格式步骤:
- 分配解复用器上下文
avformat_alloc_context();
- 根据url打开本地文件或网络流
avformat_open_input()
- 读取媒体的数据包,查找流信息
avformat_find_stream_info()
- 遍历数据
1 从文件中读取数据包 av_read_frame();
2 或者定位文件位置进行遍历(avformat_seek_file()、av_seek_frame();
- 关闭解复用器
avformat_close_input()
解码相关函数
- avcodec_alloc_context3():分配解码器上下文;
- avcodec_find_decoder():根据ID查找解码器;
- avcodec_find_decoder_by_name():根据解码器名字查找解码器;
- avcodec_open2();打开编解码器;
- avcodec_send_packet():发送编码数据包;
- avcodec_receive_frame():接受解码后的数据;
- avcodec_free_context():释放解码器上下文,此函数包含了avcodec_close();
- avcodec_close();关闭解码器;
五、Ffmpeg常用数据结构
- AVFormatContext:封装格式上喜爱文结构体,统领全局的结构体,保存了视频文件封装格式等相关信息;
- AVInputFormat:输入的format;封装格式(例如:FLV、MP4),每个封装格式都对应一个该结构体;
- AVOutputFormat:输出的format,例如:输出到网络流,输出到文件等;
- AVStream:一个视频容器(即文件)中存在多路流数据,每路流都对应一个该结构体,例如:视频流、音频流、字幕流等;
- AVCodecContext: 编解码器上下文结构体,保存了音视频编解码相关的信息;
- AVCodec:每一种音视频编解码器(例如:H.264解码器)都对应一个该结构体;
- AVPacket:存储一帧压缩编码数据;
- AVFrame:存储一帧解码后的数据(可以是视频解码后的像素数据,也可以是音频采样后的数据);