专栏名称: 网易云信
开发
目录
相关文章推荐
大佳的投资笔记  ·  吊打97%的权益基金!实操详解:如何利用de ... ·  11 小时前  
大佳的投资笔记  ·  吊打97%的权益基金!实操详解:如何利用de ... ·  11 小时前  
法询金融固收组  ·  境外城投债收益加速下行! ·  昨天  
金融早实习  ·  2月7日-实习日报|尼尔森+天健+招商信诺+ ... ·  昨天  
程序员小灰  ·  疯了!下载 DeepSeek 最高判20年! ·  4 天前  
OSC开源社区  ·  DeepSeek-V3满血版在国产沐曦GPU ... ·  3 天前  
51好读  ›  专栏  ›  网易云信

Android短视频中如何实现720P磨皮美颜录制?

网易云信  · 掘金  ·  · 2018-09-11 04:13

正文

阅读 18

Android短视频中如何实现720P磨皮美颜录制?

视频中磨皮、美颜功能已成为刚需,那么如何在Android短视频中实现720P磨皮美颜录制?本篇文章中, 网易云信 资深开发工程师将向大家介绍具体的操作方法。

相关阅读推荐

短视频技术详解:Android端的短视频开发技术

如何快速实现移动端短视频功能?

在Android上要实现一个录制功能,需要有几个方面的知识储备:自定义相机的开发、视频数据格式的了解、编码相关知识以及视频合成技术,同时如果需要美颜、磨皮等滤镜操作还需要一定的openGL的知识。如果有需要深入音视频方面开发的同学建议先了解下上述的基本知识点。

既然要实现720P、30帧,同时又要对视频数据进行滤镜处理的录制,那我们首先就要确定一个正确的实现方案。如果方案选错了,那即使实现了录制功能,但性能达不到30帧或是CPU消耗太大手机发烫那就不好了。

视频的编码录制主要是软编和硬编两种方案:

软编即采用CPU对相机采集的原始数据进行编码后再和音频一起合并成一个MP4等格式的文件。

优点是技术相对成熟,网上开源的编码以及合成库很多,实现相对较快,同时兼容性比较好。

缺点是CPU暂用率高,性能差的手机无法达到720P的30帧,同时引用了大量的第三方库,导致包很大。

软编的具体实现方案如下图所示,流程相对清晰简单:


硬编即采用手机提供的硬编接口,利用硬件芯片直接进行编码合成。

优点是速度快、效率高、CPU占用极少,即使长时间高清录制也不会发烫,同时由于使用系统API,库相对较小。

缺点是某些奇葩机型需要处理兼容性问题,同时Android上的硬编跟Surface以及openGL关系比较密切,网上相关知识较少,需要自己摸索踩坑。

硬编的主要流程如下图所示,可以看到所有的数据,从采集、编码、显示以及合成都在GPU里面进行流转。


结合上面分析的两种方案我们可以看到,在Android这类移动平台上,使用第二种硬编的方式是比较合适的。由于短视频的本地录制不像直播等场景对带宽的要求比较大,需要动态调节编码器码率帧率的情况,本地录制可以将编码器的码率设置的比较高,也不需要动态改变分辨率。因此采用硬件编码的方式既可以省CPU的性能又可以实现720P的高效编码。

确定了方案之后,我们就着重讲一下硬编方案的各个步骤的实现方式。

自定义相机的开发

我们知道根据Android的系统Camera API,可以通过setPreviewDisplay接口给Camera设置一个SurfaceView的SurfaceHolder就可以让Camera采集的数据显示到SurfaceView上了。这个接口的好处是系统帮我们处理了相机采集的各种角度同时进行了绘制,如果只是简单的录制可以这么使用,但我们需要对相机采集的数据进行滤镜处理,那这个接口就不合适了。

因此我们需要用到另外一个接口 setPreviewTexture:


通过给Camera设置一个SurfaceTexture,可以将Camera采集的数据先映射到这个SurfaceTexture上,然后我们根据创建这个SurfaceTexture的TextureID来获取GPU上的Camera数据

滤镜以及本地绘制

我们通过SurfaceTexture绑定的TextureID可以获取到Camera采集到GPU上的视频数据。然后可以将TextureID送给一些第三方滤镜库进行美颜滤镜或是自己编写Shader进行磨皮和美白。自己编写Shader需要opengl以及图像算法方面的知识,通常需要专门的开发人员,这里就不做详细的展开了(当然最简单的就是接入网易云短视频SDK了,里面实现了磨皮、美颜和多款滤镜)。

本地绘制主要靠openGL进行绘制,我们需要先在Camera的采集回调线程上创建一个EGLContext以及EGLDisplay和EGLSurface, 其中EGLContext是openGL在该线程上的上下文,EGLDisplay是一块GPU中的虚拟显示区,主要用于缓存GPU上的视频数据,EGLSurface为具体显示的View到openGL上的映射,是真正绘制到View上的工具。当接受到Camera采集回调的一帧数据后,我们先通过SurfaceTexture.updateTexImage()方法,将Camera采集的数据映射到SurfaceTexture。然后根据glsl语言将TextureID对应的数据绘制到EGLDisplay上,这里需要注意的是,Camera采集是有角度的,横竖屏下角度不同,可以通过SurfaceTexture的getTransformMatrix方法获取角度矩阵,然后把矩阵传给EGLDisplay进行旋转。EGLDisplay旋转绘制完成后通过eglSwapBuffers方法就可以将EGLDisplay上的数据拷贝到EGLSurface上进行显示了。Android 系统中的GLSurfaceView最后就是通过eglSwapBuffers将数据显示到我们看到的屏幕上的。







请到「今天看啥」查看全文