android 视频美颜,Android短视频中如何实现720P磨皮美颜录制?
視頻中磨皮、美顏功能已成為剛需,那么如何在Android短視頻中實現(xiàn)720P磨皮美顏錄制?本篇文章中,網(wǎng)易云信資深開發(fā)工程師將向大家介紹具體的操作方法。
相關(guān)閱讀推薦
在Android上要實現(xiàn)一個錄制功能,需要有幾個方面的知識儲備:自定義相機的開發(fā)、視頻數(shù)據(jù)格式的了解、編碼相關(guān)知識以及視頻合成技術(shù),同時如果需要美顏、磨皮等濾鏡操作還需要一定的openGL的知識。如果有需要深入音視頻方面開發(fā)的同學(xué)建議先了解下上述的基本知識點。
既然要實現(xiàn)720P、30幀,同時又要對視頻數(shù)據(jù)進行濾鏡處理的錄制,那我們首先就要確定一個正確的實現(xiàn)方案。如果方案選錯了,那即使實現(xiàn)了錄制功能,但性能達不到30幀或是CPU消耗太大手機發(fā)燙那就不好了。
視頻的編碼錄制主要是軟編和硬編兩種方案:
[if !supportLists]·????????[endif]軟編即采用CPU對相機采集的原始數(shù)據(jù)進行編碼后再和音頻一起合并成一個MP4等格式的文件。
優(yōu)點是技術(shù)相對成熟,網(wǎng)上開源的編碼以及合成庫很多,實現(xiàn)相對較快,同時兼容性比較好。
缺點是CPU暫用率高,性能差的手機無法達到720P的30幀,同時引用了大量的第三方庫,導(dǎo)致包很大。
軟編的具體實現(xiàn)方案如下圖所示,流程相對清晰簡單:
硬編即采用手機提供的硬編接口,利用硬件芯片直接進行編碼合成。
優(yōu)點是速度快、效率高、CPU占用極少,即使長時間高清錄制也不會發(fā)燙,同時由于使用系統(tǒng)API,庫相對較小。
缺點是某些奇葩機型需要處理兼容性問題,同時Android上的硬編跟Surface以及openGL關(guān)系比較密切,網(wǎng)上相關(guān)知識較少,需要自己摸索踩坑。
硬編的主要流程如下圖所示,可以看到所有的數(shù)據(jù),從采集、編碼、顯示以及合成都在GPU里面進行流轉(zhuǎn)。
結(jié)合上面分析的兩種方案我們可以看到,在Android這類移動平臺上,使用第二種硬編的方式是比較合適的。由于短視頻的本地錄制不像直播等場景對帶寬的要求比較大,需要動態(tài)調(diào)節(jié)編碼器碼率幀率的情況,本地錄制可以將編碼器的碼率設(shè)置的比較高,也不需要動態(tài)改變分辨率。因此采用硬件編碼的方式既可以省CPU的性能又可以實現(xiàn)720P的高效編碼。
確定了方案之后,我們就著重講一下硬編方案的各個步驟的實現(xiàn)方式。
自定義相機的開發(fā)
我們知道根據(jù)Android的系統(tǒng)Camera API,可以通過setPreviewDisplay接口給Camera設(shè)置一個SurfaceView的SurfaceHolder就可以讓Camera采集的數(shù)據(jù)顯示到SurfaceView上了。這個接口的好處是系統(tǒng)幫我們處理了相機采集的各種角度同時進行了繪制,如果只是簡單的錄制可以這么使用,但我們需要對相機采集的數(shù)據(jù)進行濾鏡處理,那這個接口就不合適了。
因此我們需要用到另外一個接口 setPreviewTexture:
通過給Camera設(shè)置一個SurfaceTexture,可以將Camera采集的數(shù)據(jù)先映射到這個SurfaceTexture上,然后我們根據(jù)創(chuàng)建這個SurfaceTexture的TextureID來獲取GPU上的Camera數(shù)據(jù)
濾鏡以及本地繪制
我們通過SurfaceTexture綁定的TextureID可以獲取到Camera采集到GPU上的視頻數(shù)據(jù)。然后可以將TextureID送給一些第三方濾鏡庫進行美顏濾鏡或是自己編寫Shader進行磨皮和美白。自己編寫Shader需要opengl以及圖像算法方面的知識,通常需要專門的開發(fā)人員,這里就不做詳細的展開了(當(dāng)然最簡單的就是接入網(wǎng)易云短視頻SDK了,里面實現(xiàn)了磨皮、美顏和多款濾鏡)。
本地繪制主要靠openGL進行繪制,我們需要先在Camera的采集回調(diào)線程上創(chuàng)建一個EGLContext以及EGLDisplay和EGLSurface, 其中EGLContext是openGL在該線程上的上下文,EGLDisplay是一塊GPU中的虛擬顯示區(qū),主要用于緩存GPU上的視頻數(shù)據(jù),EGLSurface為具體顯示的View到openGL上的映射,是真正繪制到View上的工具。當(dāng)接受到Camera采集回調(diào)的一幀數(shù)據(jù)后,我們先通過SurfaceTexture.updateTexImage()方法,將Camera采集的數(shù)據(jù)映射到SurfaceTexture。然后根據(jù)glsl語言將TextureID對應(yīng)的數(shù)據(jù)繪制到EGLDisplay上,這里需要注意的是,Camera采集是有角度的,橫豎屏下角度不同,可以通過SurfaceTexture的getTransformMatrix方法獲取角度矩陣,然后把矩陣傳給EGLDisplay進行旋轉(zhuǎn)。EGLDisplay旋轉(zhuǎn)繪制完成后通過eglSwapBuffers方法就可以將EGLDisplay上的數(shù)據(jù)拷貝到EGLSurface上進行顯示了。Android 系統(tǒng)中的GLSurfaceView最后就是通過eglSwapBuffers將數(shù)據(jù)顯示到我們看到的屏幕上的。
硬件編碼
Android上的硬件編碼主要靠MediaCodeC API實現(xiàn)的,下面是MediaCodeC比較經(jīng)典的一張數(shù)據(jù)處理圖。
從圖中我們看到,MediaCodeC主要處理流程就是:
創(chuàng)建并配置一個?MediaCodec?對象
循環(huán)直到完成:
如果輸入緩沖區(qū)就緒,讀取一個輸入塊,并復(fù)制到輸入緩沖區(qū)中如果輸出緩沖區(qū)就緒,復(fù)制輸出緩沖區(qū)的數(shù)據(jù)
釋放?MediaCodec?對象
從Android的官方文檔我們看到,MediaCodeC支持ByteBuffers和Surface兩種輸入方式,文檔也指明了Surface方式可以提高編碼效率,而且我們上面的Camera數(shù)據(jù)也是采集到的SurfaceTexture,因此我們這里使用Surface方式作為輸入源。
我們在上面顯示部分提到EGLSurface是作為真正輸出顯示的模塊,MediaCodec也是。我們先通過MediaCodec創(chuàng)建一個Surface,然后將這個Surface綁定到一個EGLSurface,當(dāng)Camera采集的數(shù)據(jù)回調(diào)時,我們只要重復(fù)一次繪制模塊的操作,將Camera采集到SurfaceTexture上的數(shù)據(jù)swapBuffers到EGLSurface 上就可以了。然后循環(huán)MediaCodec輸出緩沖區(qū),MediaCodec就會將編碼后的數(shù)據(jù)返回給我們了。這樣做的好處就是將顯示和編碼完全分離了,即使我們沒有UI View的情況下也可以進行編碼,比如在不同Activity之間切換也不會影響我們的正常編碼。
視頻合成
Android上視頻合成主要通過MediaMuxer API實現(xiàn)。MediaMuxer類相對比較簡單,特別是配合MediaCodec使用。 我們只需要通過 addTrack 來添加視頻和音頻通道接口。AddTrack 接口需要傳入一個MediaFormat對象,MediaFormat即媒體格式類,用于描述媒體的格式參數(shù),如視頻幀率、音頻采樣率等。還好我們使用了MediaCodeC,MediaCodeC會返回MediaFormat給我們,如果是使用軟編然后用MediaMuxer進行合并的話,這里有一個比較大的坑,如果手動創(chuàng)建MediaFormat對象的話,一定要記得設(shè)置"csd-0"和"csd-1"這兩個參數(shù):其中"csd-0"和"csd-1"對應(yīng)的是視頻的sps和pps,對于AAC音頻的話,對應(yīng)的是ADTS。不設(shè)置的話會崩潰的。設(shè)置完這些之后,只要編碼器來一幀數(shù)據(jù),我們送到MediaMuxer中可以出來MP4了。
最后大體的流程圖就是:
以上就是在Android短視頻中實現(xiàn)720P磨皮美顏錄制的分享。
另外,想要獲取更多產(chǎn)品干貨、技術(shù)干貨,記得關(guān)注網(wǎng)易云信博客。
總結(jié)
以上是生活随笔為你收集整理的android 视频美颜,Android短视频中如何实现720P磨皮美颜录制?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【ES7(2016)】幂运算符**
- 下一篇: python创建django项目_搭建P