一、背景
最近Blurrr
新版本需求出来了,需要iOS客户端可以保存带Alpha通道视频。 那什么是带Alpha通道的视频呢?举个栗子:
在视频编辑中,我们常常会将文字增加各种效果,然后和图片、视频等合成一个视频。
比如:
你想在上面图片上增加一个文字:世界和平 并合成一个新的视频。
你想要的效果应该是这样的吧:
但是如果世界和平是不带Alpha通道的,那就会是这样的:
你会发现,世界都没了,世界和平就是一句空话。
在我们之前的产品中,一直对保存带Alpha通道的视频有非常强烈的需求。但是之前一直没有特别好的解决方案,加上之前的产品规划调整,这个技术瓶颈也就一致没有解决。最近新版本需求中,对alpha通道视频的依赖非常严重,如果无法解决,会导致我们产品重点功能无法完成,产品完善度大大降低。
因此,就有了接下来的故事。
二、方案探索
接收到需求后,在和Unity组 @CC
老师 讨论后,暂时制定了两种实现方案:
1.修改编码方式,使得视频输出支持Alpha通道
2.Unity除现有的视频渲染流程外,还需要再开启一个流程专门渲染Alpha图像,然后再由iOS客户端将两个结果叠加产生一帧图像。
方案二相比方案一在实现成本上会高很多,不仅工作量大,并且还需要降低渲染性能。
目前的技术方案使用AVAssetWirter
采用H264
编码方式生成视频。经过资料查找发现H264
的特点就是编码输出的视频是不带有Alpha通道的。本着用最低成本和最高性能实现,并且基于AVAssetWirter
编码及AVAssetReader
解码,那么最简单的就是AVAssetWirter
编码支持Alpha通道。所以就需要寻找其它编码方式。
正当我在查找资料却久久无果时,关键人物 -- @章哥
,出现了。
章哥在了解相关情况后,通过查阅资料,发现苹果在2019的WWDC中,展示了iOS13后苹果新提供的新能力,可以基于HEVC
编码的视频,保存带Alpha通道的视频的技术方案。
HEVC
是High Efficiency Video Coding
的缩写,是一种新的视频压缩标准,用来替代H.264/AVC
编码标准,2013年1月26号,HEVC
正式成为国际标准。
苹果在iOS11后支持了HEVC
编码能力,然后在iOS13上正式推出了HEVC.withAlpha
。正好,我们Blurrr
就是从iOS13开始适配的。那么接下来要做的就是实际论证了。
三、方案实现
HEVC编码方案实现带Apha通道视频的原理如下:
是不是有点熟悉,和@CC
老师提出的方案一样,也是将一个图像层叠加上透明图层,得到最终的带Alpha的图层。不过,这里苹果帮我们做了封装,让我们方便直接使用。
官方Demo展示了三种不同的使用场景:
使用
AVAssetWirter
,将视频帧写入到视频文件中;使用
AVExportSession
导出视频;使用
VideoToolBox
将视频帧转换为SampleBuffer
;
我们今天主要介绍第一种,也是我们目前使用的解决方案。对其它两种解决方案有兴趣的同学可以点击文末链接详细了解。
编码原理如下:
在获取到带Alpha通道的视频帧后,我们再通过AVAssetWriter
就可以将其写入到mov
格式的文件中了。
接下来,就是代码环节了。
H264编码设置如下:
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编码设置如下:
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)
前后对比,可以看出其中就三个关键设置项:
- 初始化
AVAssetWrite
r时,需要设置fileType
为AVFileType.mov
- 初始化
AVAssetWriterInput
的outputSettings
字典中,设置为AVVideoCodecKey
为AVVideoCodecType.hevcWithAlpha
- 初始化
AVAssetWriterInput
的outputSettings
字典中,使用了VideoToolBox
将AVVideoCompressionPropertiesKey
设置为[kVTCompressionPropertyKey_AverageBitRate: bitRate, kVTCompressionPropertyKey_TargetQualityForAlpha: 1]
经过上面编码参数修改,最终生成的视频就是带有Alpha通道的视频了。
还是以上面的世界和平为例,基于H264
编码和HEVC
生成的视频视频对比。因为多了一个Alpha图层,体积确实有所增大。
但是,由于HEVC
是在H264
基础上升级的,苹果也做了支持。编码速度上几乎没有差别,但是在解码速度上,HEVC
还是会比H264
快大概10%的样子。
以上就是本期全部内容了,下期再见!
特别感谢:@章哥
,@CC
两位大佬鼎力支持。
参考资料:
https://developer.apple.com/videos/play/wwdc2019/506/
https://www.bilibili.com/video/av68104093