音视频的编码格式与封装格式是两个不同的概念,视频封装格式常见的有:mp4,rmvb,avi,mkv,mov,mpg,vob,3gp,asf,rmvb,wmv,divx,flv,ts/ps,rm,webm,dat,mpeg,ogg,这些视频封装格式是包裹了音视频编码数据的容器,把特定编码标准编码的视频流和音频流混在一起。在移动端一般将视频封装为mp4格式,mp4支持H.264, H.265等视频编码和acc,mp3等音频编码。
封装简单来说就是将已经编码压缩好的视频轨和音频轨按照一定格式放在一个文件中。
封装格式也被称作多媒体容器,将已处理好的视频和音频或字幕都包装到一个文件容器内,这个过程就叫封装。封装会按照一定的规则把音视频、字幕等数据组织起来,播放器就可以按照这些信息来匹配解码器、同步音视频。
不同的封装格式支持的音视频编码格式是不一样的,如mkv封装格式支持的音视频编码比较多,rmvb则较少。封装格式并不会影响视频的画质,影响画面质量的是视频的编码格式,一个完整的视频文件是由视频、音频、字幕等组成的。用专业的术语来讲,像mp4,ts,flv等封装格式将视频、音频、字幕等合成一个文件,这里的合成就是复用器,示意图如下:
音视频封装的流程:
- 编码好的视频、音频数据:利用给定的YUV数据编码得到某种视频编码格式(如H.264,H.265等)的数据,同亲利用同样的方法得到音频编码格式(如AAC)的数据
- 根据封装格式(如mp4,ts等)选择特定的封装器,获取输出文件格式添加视频、音频及对格式的头信息进行设置
- 最后利用封装器进行将已设置好的视频、音频、头信息等进行封装。最终得到个视频文件
解封装就是上面的逆过程,专业术语叫解复用,示意如下:
解复用的过程如下:
1.初始化解复用器:对输入文件(容器,mpv,flv等)、输出文件(video,audio)进行处理
2.将输入的封装格式文件传输到解复用器内,打开文件,并分析格式上下文参数,获得流信息
3.利用解复用器对输入文件进行解封装,打开视频、音频编码器,针对视频数据分配图像(Image)和帧(Frame)结构,然后初始化数据包(AVPacket),从输入文件中读取AVFrame信息,并进行解码,最后释放各种分配的数据信息
提取音频流
//-vn 表示过滤掉视频流,ffmpeg默认将音频流存储为ADTS格式的aac文件
ffmpeg -i input.mp4 -vn -acodec copy output.aac
这里要注意,如果input.mp4中包含的音频流的编码格式不是AAC、H.264,则提取出来的音频文件就不能够存储为.aac,.h264的格式。
AAC是一种音频有损压缩技术,一种高压缩比的音频压缩算法,mp4
视频中音频数据大多采用这AAC压缩技术。AAC格式分为两种:一种是音频数据交换格式(Audio Data Interchange Format,ADIF),另一种是音频数据传输流(Audio Data Transport Stream,ADTS)。
ADIF常用须磁盘文件中,只有一个统一的头,所以必须得到所有数据后才能解码。
ADTS是一个有同步字的比特流,解码可以在这个流中的任意位置开始,它可以在任意帧解码,它的每个帧都头信息,目前编码后音频流一般采用ADTS。
提取视频流
//-an 表示过滤掉音频流,ffmpeg默认将音频流存储为ADTS格式的aac文件
ffmpeg -i input.mp4 -an -vcodec copy output.h264
H.264简介
H.264的目标是使用提取的文件有高视频压缩比和良好的网络亲和性,为了实现这两个目标,H.264的解决方案将系统架构分为两层:视频编码层、网络抽象层
关于H.264的重要概念
1.SoDB(String of Data Bit)数据比特串,这是由编码器直接输出的原始编码数据,称为VCL数据,
2.RBSP(Raw Byte Sequence Payload)原始字节序列载荷,这是在SoDB编码后的原始数据后面增加若干结尾比特(具体为1个为1的比特和若干为0的比特)使用SoDB的长度为整数字节。
3.EBSP(Extension Byte Sequence Payload)扩展字节序列载荷,这是RBSP的基础上增加了校验字节(0x03)
4.NALU(Nal Unit)NAL单元,由1个NAL Header和1个RBSP(或EBSP)组成。
H.264分为AVC1和H264 编码
H264即FOURCC H264(H264 bitstream with start codes)也被称为AnnexB格式,它是一种带有起始码的格式,它一般用于无线发射、有线广播或HD-DVD,这些数据流都有一个起始码0x000001或0x00000001. NALU是NAL网络适配层以网络所要求的恰当方式对数据进行打包和发送的基本单元,这种方式非常适合流式传输。NALU简单来说就是H.264格式中最基本的单元(数据包)。
AVC1,即FOURCC AVC1(H264 bitstream without start codes)是一种不带起始码的格式,主要存储在.mp4,.flv格式文件中,它的数据流的开始是1,2或4字节,表示长度数据。
FOURCC全称Four Character Codes,代表四字符代码,它是一个32位的标识,是一种独立标识视频数据流格式的四字符代码,视频播放软件通过查询FOURCC代码并且寻找与FOURCC代码相关联的视频解码器来播放特定的视频流。如:
DIV3 = DivX Low-Motion
DIV4 = DivX Fast-Motion
DIVX = DivX4
FFDS = FFDShow等。
常见的FOURCC代码:
1.I420: YUV编码,视频格式为.avi
2.PIM1: MPEG-1编码,视频格式为.avi
3.XVID:MPEG-4编码,视频格式为.avi
4.THEO: Ogg Vorbis,视频格式为.ogv
5.FLV1: Flash视频编码,视频格式为.flv
6.AVC1: H.264编码,视频格式为.mp4
7.DIV3: MPEG-4.3编码
8.DIVX: MPEG-4编码
9.MP42: MPEG-4.2编码
10.MJPG:motion-jpeg编码
11.U263: H.263编码
11.I263: H.263I编码
将视频流和音频流合成mp4文件
// -c copy 用于直接复制音视频流,不用重新编码
ffmpeg -i output.h264 -i output.aac -c copy -y hello.mp4
新生成的hello.mp4文件,封装格式为MP4,有视频流AVC和音频流AAC。
将多个mp4文件合成一个mp4文件
准备好多个mp4视频文件,它们的音视频参数需要一致,如帧率、码率等方面要一致,然后依次记录到一个txt文件中,如mp4list.txt,内容如下:
mp4list.txt:
file ‘1.mp4’
file ‘2.mp4’
file ‘3.mp4‘
// -c copy 用于直接复制音视频流,不用重新编码
ffmpeg -f concat -i mp4list.txt -c copy output.mp4
封装格式之间的转换
在前面我们已经描述得非常清楚了,封装格式就是音视频容器,将音频、视频、字幕等一起封装成一个视频文件。这个视频文件或用于存储或用于传输编码数据。封装格式的转换,不会影响画面质量,因为我们只是换一个容器也放编码好的音频、视频和字幕等内容,除非在换容器时,也使用新的编码。以下列出了一些常见的封装格式:
- mpg:是mpeg编码采用的容器(封装格式),这个容器具有流的特性,它分PS和TS,PS用于DVD存储,TS用于HDTV。
- vob:是dvd编码采用的容器,这个容器支持多视频、多音轨、多字幕等
- mp4: mpeg编码采用的容器,这个容器是基于quick time mov开发的。
- avi:这是音视频交互存储常见的容器,它支持非常多的音视频编码
- mov:这个是quick time的容器,据说是至今最强大的容器,它支持虚拟现实技术等。mp4容器是mov的变体。
将mp4转换为flv
// -vcodec copy视频的编解码处理方式为直接复制
// -acodec copy音频的编解码处理方式为直接复制
// -f flv 强制指定封装格式
ffmpeg -i input.mp4 -vcodec copy -acodec copy -f flv output.flv
将mp4转换为avi
// -vcodec copy视频的编解码处理方式为直接复制
// -acodec copy音频的编解码处理方式为直接复制
ffmpeg -i input.mp4 -vcodec copy -acodec copy output.avi
下面这个在转换封装格式的同时也会发生编码转换,因为如果没有像上面那样指定音视频编解码的处理方式,会使用相应容器的编码重新编码,如下面视频编码由H.264转换成MPEG4,音频编码由AAC转换成MP3.
ffmpeg -i input.mp4 output.avi
并不是容器(封装格式)都支持所有的编码,如:
// -c copy 用于直接复制音视频流,不用重新编码
// 这个转换会失败,因为avi里封装了aac,而mpg无法封装aac
ffmpeg -i input.avi -c copy output.mpg
上面这个转换可以下面这个来完成:
// 这个重新编码,所以不会有错
ffmpeg -i input.avi output.mpg