一、背景
最近Blurrr新版本需求出來了,需要iOS客戶端可以保存帶Alpha通道視頻。 那什么是帶Alpha通道的視頻呢?舉個(gè)栗子:
在視頻編輯中,我們常常會將文字增加各種效果,然后和圖片、視頻等合成一個(gè)視頻。
比如:

你想在上面圖片上增加一個(gè)文字:世界和平 并合成一個(gè)新的視頻。
你想要的效果應(yīng)該是這樣的吧:

但是如果世界和平是不帶Alpha通道的,那就會是這樣的:

你會發(fā)現(xiàn),世界都沒了,世界和平就是一句空話。
在我們之前的產(chǎn)品中,一直對保存帶Alpha通道的視頻有非常強(qiáng)烈的需求。但是之前一直沒有特別好的解決方案,加上之前的產(chǎn)品規(guī)劃調(diào)整,這個(gè)技術(shù)瓶頸也就一致沒有解決。最近新版本需求中,對alpha通道視頻的依賴非常嚴(yán)重,如果無法解決,會導(dǎo)致我們產(chǎn)品重點(diǎn)功能無法完成,產(chǎn)品完善度大大降低。
因此,就有了接下來的故事。
二、方案探索
接收到需求后,在和Unity組 @CC老師 討論后,暫時(shí)制定了兩種實(shí)現(xiàn)方案:
1.修改編碼方式,使得視頻輸出支持Alpha通道
2.Unity除現(xiàn)有的視頻渲染流程外,還需要再開啟一個(gè)流程專門渲染Alpha圖像,然后再由iOS客戶端將兩個(gè)結(jié)果疊加產(chǎn)生一幀圖像。
方案二相比方案一在實(shí)現(xiàn)成本上會高很多,不僅工作量大,并且還需要降低渲染性能。
目前的技術(shù)方案使用AVAssetWirter采用H264編碼方式生成視頻。經(jīng)過資料查找發(fā)現(xiàn)H264的特點(diǎn)就是編碼輸出的視頻是不帶有Alpha通道的。本著用最低成本和最高性能實(shí)現(xiàn),并且基于AVAssetWirter編碼及AVAssetReader解碼,那么最簡單的就是AVAssetWirter編碼支持Alpha通道。所以就需要尋找其它編碼方式。
正當(dāng)我在查找資料卻久久無果時(shí),關(guān)鍵人物 -- @章哥,出現(xiàn)了。

章哥在了解相關(guān)情況后,通過查閱資料,發(fā)現(xiàn)蘋果在2019的WWDC中,展示了iOS13后蘋果新提供的新能力,可以基于HEVC編碼的視頻,保存帶Alpha通道的視頻的技術(shù)方案。
HEVC是High Efficiency Video Coding的縮寫,是一種新的視頻壓縮標(biāo)準(zhǔn),用來替代H.264/AVC編碼標(biāo)準(zhǔn),2013年1月26號,HEVC正式成為國際標(biāo)準(zhǔn)。
蘋果在iOS11后支持了HEVC編碼能力,然后在iOS13上正式推出了HEVC.withAlpha。正好,我們Blurrr就是從iOS13開始適配的。那么接下來要做的就是實(shí)際論證了。
三、方案實(shí)現(xiàn)
HEVC編碼方案實(shí)現(xiàn)帶Apha通道視頻的原理如下:

是不是有點(diǎn)熟悉,和@CC老師提出的方案一樣,也是將一個(gè)圖像層疊加上透明圖層,得到最終的帶Alpha的圖層。不過,這里蘋果幫我們做了封裝,讓我們方便直接使用。
官方Demo展示了三種不同的使用場景:
使用
AVAssetWirter,將視頻幀寫入到視頻文件中;使用
AVExportSession導(dǎo)出視頻;使用
VideoToolBox將視頻幀轉(zhuǎn)換為SampleBuffer;
我們今天主要介紹第一種,也是我們目前使用的解決方案。對其它兩種解決方案有興趣的同學(xué)可以點(diǎn)擊文末鏈接詳細(xì)了解。
編碼原理如下:

在獲取到帶Alpha通道的視頻幀后,我們再通過AVAssetWriter就可以將其寫入到mov格式的文件中了。
接下來,就是代碼環(huán)節(jié)了。
H264編碼設(shè)置如下:
let outPath = "demo.mov"
do {
try assetWriter = AVAssetWriter(url: outPath, fileType: AVFileType.mp4)
} catch {
MSLog.info("--MSVideoEncoder create writer failed: \(error)")
}
let outputSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.h264,
AVVideoWidthKey: outWidth,
AVVideoHeightKey: outHeight,
AVVideoCompressionPropertiesKey: [
AVVideoAverageBitRateKey: bitRate,
AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel
]
]
HEVC編碼設(shè)置如下:
let outPath = "demo.mov"
do {
try assetWriter = AVAssetWriter(url: outPath, fileType: AVFileType.mov)
} catch {
MSLog.info("--MSVideoEncoder create writer failed: \(error)")
}
let outputSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.hevcWithAlpha,
AVVideoWidthKey: outWidth,
AVVideoHeightKey: outHeight,
AVVideoCompressionPropertiesKey:
[kVTCompressionPropertyKey_AverageBitRate: bitRate,
kVTCompressionPropertyKey_TargetQualityForAlpha: 1]
]
let videoWriterInput = AVAssetWriterInput(mediaType: AVMediaType.video, outputSettings: outputSettings)
前后對比,可以看出其中就三個(gè)關(guān)鍵設(shè)置項(xiàng):
- 初始化
AVAssetWriter時(shí),需要設(shè)置fileType為AVFileType.mov - 初始化
AVAssetWriterInput的outputSettings字典中,設(shè)置為AVVideoCodecKey為AVVideoCodecType.hevcWithAlpha - 初始化
AVAssetWriterInput的outputSettings字典中,使用了VideoToolBox將AVVideoCompressionPropertiesKey設(shè)置為[kVTCompressionPropertyKey_AverageBitRate: bitRate, kVTCompressionPropertyKey_TargetQualityForAlpha: 1]
經(jīng)過上面編碼參數(shù)修改,最終生成的視頻就是帶有Alpha通道的視頻了。
還是以上面的世界和平為例,基于H264編碼和HEVC生成的視頻視頻對比。因?yàn)槎嗔艘粋€(gè)Alpha圖層,體積確實(shí)有所增大。

但是,由于HEVC是在H264基礎(chǔ)上升級的,蘋果也做了支持。編碼速度上幾乎沒有差別,但是在解碼速度上,HEVC還是會比H264快大概10%的樣子。
以上就是本期全部內(nèi)容了,下期再見!
特別感謝:@章哥,@CC 兩位大佬鼎力支持。
參考資料:
https://developer.apple.com/videos/play/wwdc2019/506/
https://www.bilibili.com/video/av68104093