原文地址
最近在开发过程中涉及到了视频压缩的需求,那么在 iOS 上怎么实现自定义码率和分辨率的视频压缩呢?
1. 传统压缩方式
产品需求:不管原视频的清晰度如何,压缩后的视频码率和分辨率是一样的。首先,iOS在AVFoundation中已经提供了简单的视频压缩方法,示例代码如下:
正常情况下这段代码不会出现任何问题,但是大家可以用下面的视频做个测试,链接: https://pan.baidu.com/s/1wLVbDFtzROVPo8T1qw6MXA 密码: ij7d。结果会发现原视频分辨率1080x608,大小 90M,经过上面的代码压缩后变成了分辨率960x540, 大小147M!虽然分辨率降低,但文件大小增加了!
2. 压缩参数分析
可以使用 mediainfo 工具查看压缩前后两个视频的详细参数信息。
原视频参数:
压缩视频参数:
码率:bit rate,是指单位时间内处理的数据位数,单位是 b/s 。码率=视频文件大小/视频时长。
帧率:frame rate,是指每秒钟有多少个画面,单位 f/s 。视频画面帧率高于16 时大脑就会把图片连贯成动画,高于24大脑就认为是非常流畅了。因此,24FPS是视频行业的标准。
分辨率:通常我们了解的分辨率是指图像的高/宽像素值,严格意义上的分辨率是指单位长度内的有效像素值ppi(每英寸像素Pixel per inch)。差别是,图像的高/宽像素值和尺寸无关,但单位长度内的有效像素值ppi和尺寸就有关了。比如,同样Width x Height的图片,尺寸越大ppi越小。
3. 视频编码标准
根据上面的概念得出,帧率相同的情况下(压缩前后都是30FPS),分辨率越高码率越大,但是截图的中的参数显示码率大的分辨率低。仔细对比两个视频的参数会发现唯一有区别的是 Format profile,这个参数才是问题的根源。
在介绍这个参数之前需要了解另一个概念,H264视频编码。所谓视频编码方式就是指通过特定的压缩技术,将某个视频格式的文件转换成另一种视频格式文件的方式。
如果视频不编码会出现什么后果?我们来计算一下,以原视频为例,每秒钟包含了30张1080x600的图片,那一秒钟的视频大小应该是 1080x60030/(102410248) = 2.3 MB. 这个视频有3分42秒 ,文件大小应该是 2.3222 = 510MB 远超过95M。既然编码是必须的那编码标准有哪些呢?
国际上制定视频编解码技术的组织有两个,一个是“国际电联(ITU-T)”,它制定的标准有H.261、H.263、H.263+等,另一个是“国际标准化组织(ISO)”它制定的标准有MPEG-1、MPEG-2、MPEG-4等。
而H.264则是由两个组织联合组建的联合视频组(JVT)共同制定的新数字视频编码标准,所以它既是ITU-T的H.264,又是ISO/IEC的MPEG-4高级视频编码(Advanced Video Coding,AVC)的第10 部分。所以大家在用不同工具查看同一个视频时有时候会显示AVC有时候会显示H.264实际是同一种编码方式。
4. H264 编码详解
而H264最大的优势就是低码率情况下提供高质量的视频图像,有兴趣的同学新一代视频压缩编码标准 — H.264/AVC。
总的来说编码流程可以分为五部分:帧间和帧内预测(Estimation)、变换(Transform)和反变换、量化(Quantization)和反量化、环路滤波(Loop Filter)、熵编码(Entropy Coding)。而H264为了满足不同设备不同场景的需要(比如直播注重实时性,存储注重压缩比)定义了多种编码层次也就是Profile,官方给Profile的定义是:
The standarddefines a set of capabilities, which are referred to as profiles,targeting specific classes of applications. These are declared as a profilecode (profile_idc) and a set of constraints applied in the encoder. This allowsa decoder to recognize the requirements to decode that specific stream.
Profiles可以细分为十几种,实际使用的主要有以下四种,
1)BaslineProfile:支持I/P 帧,只支持无交错(Progressive)和CAVLC
2)Extended Profile:支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC
3)MainProfile:提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced),也支持CAVLC 和CABAC
4)High Profile:在mainProfile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;
大家对里面的术语可能不太理解,简单介绍下。
视频压缩很重要的一个就是帧间预测,也就是视频相邻的几帧有很大的相关性,变化不会太大,所以存在很多冗余信息,压缩要做的就是去除这些冗余信息。帧类型主要有以下几种
1)I帧表示关键帧,这一帧保留完整的画面数据,解码时只需要本帧数据就可以完成
2)P帧,前向预测帧,表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前的画面叠加上本帧定义的差别,生成最终画面。
3)B帧是双向预测帧,也就是B帧记录的是本帧与前后帧的差别,要解码B帧,不仅要取得之前的画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时比较耗费CPU 。
总结起来就是Profile 越高,压缩比就越高,但是编码、解码时要求的设备性能也就越高,编码、解码的效率也就越低。
5. Profile 与 Level 详解
回到之前的两个视频信息,profile分别是[email protected],[email protected], 现在我们搞清楚了main和high是profile,L3.1是什么?这个是profile的码流级别,同样给出官方的定义:
As the term is used in the standard, a "level" is aspecified set of constraints that indicate a degree of required decoderperformance for a profile. For example, a level of support within a profilespecifies the maximum picture resolution, frame rate, and bit rate that adecoder may use. A decoder that conforms to a given level must be able todecode all bitstreams encoded for that level and all lower levels.
简单的说level就是对每个profile的能力细分。
而3.1规定的最高标准如下:
6. iOS 设备对 Profile 和 level 的支持情况
了解完视频的profile和level之后,大家会有疑问,既然每种profile对设备性能的要求不同,苹果的不同机型对各种profile支持程度是怎样的?可以参照下面的列表:
iPhone 3GS 和更早的设备支持 Baseline Profile level 3.0 及更低的级别;
iPhone 4S 支持 High Profile level 4.1 及更低的级别;
iPhone 5C 支持 High Profile level 4.1 及更低的级别;
iPhone 5S 支持 High Profile level 4.1 及更低的级别;
iPad 1 支持 Main Profile level 3.1 及更低的级别;
iPad 2 支持 Main Profile level 3.1 及更低的级别;
iPad with Retina display 支持 High Profile level 4.1 及更低的级别;
iPad mini 支持 High Profile level 4.1 及更低的级别。
7. 自定义视频压缩方案
获得最大的视频压缩率采取的最好办法就是:
- 指定highprofile
- 降低帧率
- 适当降低分辨率
最终来获取更低的码率。 问题来了,文章最开始的压缩方式不支持指定profile,帧率和码率,所以只有通过其他方式来实现。在相机录像时需要将拍摄的每一帧sampleBuffer(音频或者视频)传给assetWriter,并制定压缩参数。
而视频压缩不是录像,怎么办?思路很简单,先通过assetReader取出每一帧sampleBuffer(音频或视频),然后指定压缩参数后将每一帧传给assetWriter最终实现自定义压缩的目的。具体的流程如下:
代码实现
1)初始化 reader,writer,video/audio track, video/audio input, video/audio output
2)指定音视频的压缩码率,profile,帧率等关键参数信息
3)开始读写
4)视频逐帧写入
5)音频逐帧写入
6)完成压缩
压缩效果如下:
最终自定义的视频压缩方案有了,其实逐帧写入还可以做添加水印,滤镜等动作。
原文地址
感谢!