在《如何快速实现移动端短视频功能?》中,咱们主要介绍了当前短视频的大热趋势以及开发一个短视频应用所涉及到的功能和业务。在本篇文章中,咱们主要谈一谈短视频在Android端上的具体实现技术。
《如何快速实现移动端短视频功能》docker
短视频业务主要包含:“视频录制”以及 “视频编辑”这两个核心功能。缓存
其中视频录制又包括:视频采集、实时美颜、自定义码率、摄像头切换、变焦、对焦、曝光度调节以及滤镜等功能。ide
视频编辑包括:视频裁剪、视频拼接、混音、视频动画效果、动态贴图等功能。性能
咱们先来讲说视频录制:优化
视频录制的大体实现流程就如上图所示,先由Camera、AudioRecord进行最原始的相机画面以及声音的采集,而后将采集的数据进行滤镜、降噪等前处理,处理完成后由MediaCodec进行硬件编码,最后采用MediaMuxer生成最终的MP4文件。动画
这个方案的优势在于,因为全程采用了GPU以及硬件编码,基本上不涉及CPU上的操做,所以可实如今高帧率(30fps)、高分辨率(720P)以及高码率的状况下CPU暂用率也很是低,即便在性能较差的手机上也能很好的运行。但同时这个方案的难点也在于此。ui
作过音视频的同窗都知道,一般状况下咱们所说的对音视频的处理,主要是对视频的 YUV、H264 音频的PCM、AAC这类数据格式进行操做,这类操做都有相关的RFC技术也比较成熟,实现起来比较容易,出了问题也更容易定位,一般状况下在PC等设备上也都是这么处理的。编码
但这样的方案在对于手机端状况就不一样了,虽然手机这几年的性能大大增强了,不少旗舰手机基本都是8核的CPU了,但要操做如此大量的图片数据并进行浮点运算对CPU的消耗仍是很大的。CPU暂用率高就会引发手机发烫,手机发烫就会致使Camera采集的掉帧,甚至在一些小米等厂商下,手机发烫还会引发CPU降频,CPU一降频那APP所暂用的CPU比例就更高了,同时CPU暂用率高电量消耗就快。 3d
所以上面的方案是目前Android上比较适合短视频录制的方案。
既然肯定了技术方案,咱们就来看看具体的实现。这里首先须要知道几个概念:
咱们知道在一些简单的自定义相机应用中,要实现一个相机,只须要将一个SurfaceHolder设置给Camera,Android系统就会自动的帮咱们把Camera采集的数据绘制到屏幕上。但因为在短视频中咱们须要对相机采集的数据进行前处理加工好比滤镜等,并且还要作到可见即所得的效果,所以必需要求咱们将相机采集的数据先缓存起来,前处理完后本身再绘制到屏幕上,这时候就须要用到SurfaceTexture了。按照Android官方文档的介绍,SurfaceTexture就是这样一块用于接收Camera采集的数据,同时又不可见的画布。这块画布是存在于GPU内存中的。
纹理ID,主要用来标识每一块纹理在GPU内存中的内存地址,相似于C语言中的内存指针。每一块GPU的纹理(能够理解为一块用于显示图片的画布)都有对应的一个TextureID进行标识。上述的SurfaceTexture在建立也一样须要绑定一个纹理ID进行惟一标识。
知道了这两个概念,咱们就知道了Camera采集的数据具体存在于GPU的哪一个位置了。接下来就能够对原始的数据进行前处理编码了。
这里有一个须要注意的地方,Android的camera采集到SurfaceTexture上的纹理是GL_TEXTURE_EXTERNAL_OES 类型的纹理,而目前市面的不少滤镜算法,如开源的GPUImage中不少的滤镜都是基于GL_TEXTURE_2D类型的纹理进行图像处理的。
所以在进行咱们在基于开源滤镜算法或自研算法时须要先将GL_TEXTURE_EXTERNAL_OES类型的纹理转化为GL_TEXTURE_2D的纹理,或者在GPU Shader中加入 "#extension GL_OES_EGL_image_external: require" 来代表该纹理是OES纹理,同时编写基于OES纹理的图像处理算法。
目前网易这边是先将OES转化为TEXTURE_2D在进行前处理,这样便于与iOS端算法统一以及更好的接入一些开源的滤镜算法。
解决了SurfaceTexture的问题,接下来的MediaCodec以及MediaMuxer就比较容易了。Android中的MediaCodec天生支持将GPU中的纹理绘制到MediaCodec的Surface中,而后对Surface中的图像直接进行硬件编码,图像数据始终是在GPU空间中进行流转,而没有涉及到CPU。
这里须要注意的是MediaCodec以及MediaMuxer须要在API 18及以上才能使用。同时须要注意MediaCodec在不一样设备上的兼容性。
最后对于视频编辑的功能,目前Android上没有很好的系统API即硬件处理方式,主要仍是利用ffmpeg进行相应的叠加、裁剪混音等后期处理。能够优化的一个点是,先将原始的MP4视频进行解码,而后将解码后的YUV数据映射到GPU的纹理上进行亮度、饱和度等参数的调节,作到文件编辑的所见即所得,而后将调好的参数配置为ffmpeg进行编辑处理。
想要获取更多产品干货、技术干货,记得关注网易云信博客。