關(guān)于 iOS 中的視頻壓縮

原文地址

最近在開發(fā)過程中涉及到了視頻壓縮的需求,那么在 iOS 上怎么實現(xiàn)自定義碼率和分辨率的視頻壓縮呢?

1. 傳統(tǒng)壓縮方式

產(chǎn)品需求:不管原視頻的清晰度如何,壓縮后的視頻碼率和分辨率是一樣的。首先,iOS在AVFoundation中已經(jīng)提供了簡單的視頻壓縮方法,示例代碼如下:

正常情況下這段代碼不會出現(xiàn)任何問題,但是大家可以用下面的視頻做個測試,鏈接: https://pan.baidu.com/s/1wLVbDFtzROVPo8T1qw6MXA 密碼: ij7d。結(jié)果會發(fā)現(xiàn)原視頻分辨率1080x608,大小 90M,經(jīng)過上面的代碼壓縮后變成了分辨率960x540, 大小147M!雖然分辨率降低,但文件大小增加了!

2. 壓縮參數(shù)分析

可以使用 mediainfo 工具查看壓縮前后兩個視頻的詳細參數(shù)信息。

原視頻參數(shù):

壓縮視頻參數(shù):

碼率:bit rate,是指單位時間內(nèi)處理的數(shù)據(jù)位數(shù),單位是 b/s 。碼率=視頻文件大小/視頻時長。
幀率:frame rate,是指每秒鐘有多少個畫面,單位 f/s 。視頻畫面幀率高于16 時大腦就會把圖片連貫成動畫,高于24大腦就認為是非常流暢了。因此,24FPS是視頻行業(yè)的標(biāo)準。
分辨率:通常我們了解的分辨率是指圖像的高/寬像素值,嚴格意義上的分辨率是指單位長度內(nèi)的有效像素值ppi(每英寸像素Pixel per inch)。差別是,圖像的高/寬像素值和尺寸無關(guān),但單位長度內(nèi)的有效像素值ppi和尺寸就有關(guān)了。比如,同樣Width x Height的圖片,尺寸越大ppi越小。

3. 視頻編碼標(biāo)準

根據(jù)上面的概念得出,幀率相同的情況下(壓縮前后都是30FPS),分辨率越高碼率越大,但是截圖的中的參數(shù)顯示碼率大的分辨率低。仔細對比兩個視頻的參數(shù)會發(fā)現(xiàn)唯一有區(qū)別的是 Format profile,這個參數(shù)才是問題的根源。

在介紹這個參數(shù)之前需要了解另一個概念,H264視頻編碼。所謂視頻編碼方式就是指通過特定的壓縮技術(shù),將某個視頻格式的文件轉(zhuǎn)換成另一種視頻格式文件的方式。

如果視頻不編碼會出現(xiàn)什么后果?我們來計算一下,以原視頻為例,每秒鐘包含了30張1080x600的圖片,那一秒鐘的視頻大小應(yīng)該是 1080x60030/(102410248) = 2.3 MB. 這個視頻有3分42秒 ,文件大小應(yīng)該是 2.3222 = 510MB 遠超過95M。既然編碼是必須的那編碼標(biāo)準有哪些呢?

國際上制定視頻編解碼技術(shù)的組織有兩個,一個是“國際電聯(lián)(ITU-T)”,它制定的標(biāo)準有H.261、H.263、H.263+等,另一個是“國際標(biāo)準化組織(ISO)”它制定的標(biāo)準有MPEG-1、MPEG-2、MPEG-4等。

而H.264則是由兩個組織聯(lián)合組建的聯(lián)合視頻組(JVT)共同制定的新數(shù)字視頻編碼標(biāo)準,所以它既是ITU-T的H.264,又是ISO/IEC的MPEG-4高級視頻編碼(Advanced Video Coding,AVC)的第10 部分。所以大家在用不同工具查看同一個視頻時有時候會顯示AVC有時候會顯示H.264實際是同一種編碼方式。

4. H264 編碼詳解

而H264最大的優(yōu)勢就是低碼率情況下提供高質(zhì)量的視頻圖像,有興趣的同學(xué)新一代視頻壓縮編碼標(biāo)準 — H.264/AVC

總的來說編碼流程可以分為五部分:幀間和幀內(nèi)預(yù)測(Estimation)、變換(Transform)和反變換、量化(Quantization)和反量化、環(huán)路濾波(Loop Filter)、熵編碼(Entropy Coding)。而H264為了滿足不同設(shè)備不同場景的需要(比如直播注重實時性,存儲注重壓縮比)定義了多種編碼層次也就是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 的基礎(chǔ)上增加了8x8內(nèi)部預(yù)測、自定義量化、 無損視頻編碼和更多的YUV 格式;

大家對里面的術(shù)語可能不太理解,簡單介紹下。

視頻壓縮很重要的一個就是幀間預(yù)測,也就是視頻相鄰的幾幀有很大的相關(guān)性,變化不會太大,所以存在很多冗余信息,壓縮要做的就是去除這些冗余信息。幀類型主要有以下幾種

1)I幀表示關(guān)鍵幀,這一幀保留完整的畫面數(shù)據(jù),解碼時只需要本幀數(shù)據(jù)就可以完成

2)P幀,前向預(yù)測幀,表示的是這一幀跟之前的一個關(guān)鍵幀(或P幀)的差別,解碼時需要用之前的畫面疊加上本幀定義的差別,生成最終畫面。

3)B幀是雙向預(yù)測幀,也就是B幀記錄的是本幀與前后幀的差別,要解碼B幀,不僅要取得之前的畫面,還要解碼之后的畫面,通過前后畫面的與本幀數(shù)據(jù)的疊加取得最終的畫面。B幀壓縮率高,但是解碼時比較耗費CPU 。

總結(jié)起來就是Profile 越高,壓縮比就越高,但是編碼、解碼時要求的設(shè)備性能也就越高,編碼、解碼的效率也就越低。

5. Profile 與 Level 詳解

回到之前的兩個視頻信息,profile分別是main@L3.1,high@L3.1, 現(xiàn)在我們搞清楚了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規(guī)定的最高標(biāo)準如下:

6. iOS 設(shè)備對 Profile 和 level 的支持情況

了解完視頻的profile和level之后,大家會有疑問,既然每種profile對設(shè)備性能的要求不同,蘋果的不同機型對各種profile支持程度是怎樣的?可以參照下面的列表:

iPhone 3GS 和更早的設(shè)備支持 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
  • 降低幀率
  • 適當(dāng)降低分辨率

最終來獲取更低的碼率。 問題來了,文章最開始的壓縮方式不支持指定profile,幀率和碼率,所以只有通過其他方式來實現(xiàn)。在相機錄像時需要將拍攝的每一幀sampleBuffer(音頻或者視頻)傳給assetWriter,并制定壓縮參數(shù)。

而視頻壓縮不是錄像,怎么辦?思路很簡單,先通過assetReader取出每一幀sampleBuffer(音頻或視頻),然后指定壓縮參數(shù)后將每一幀傳給assetWriter最終實現(xiàn)自定義壓縮的目的。具體的流程如下:

代碼實現(xiàn)

1)初始化 reader,writer,video/audio track, video/audio input, video/audio output

2)指定音視頻的壓縮碼率,profile,幀率等關(guān)鍵參數(shù)信息

3)開始讀寫

4)視頻逐幀寫入

image

5)音頻逐幀寫入

6)完成壓縮

壓縮效果如下:

最終自定義的視頻壓縮方案有了,其實逐幀寫入還可以做添加水印,濾鏡等動作。

原文地址

感謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容