真牛!字節(jié)跳動又一開源力作發(fā)布
前幾日,字節(jié)跳動發(fā)送郵件,宣布將給予員工發(fā)放獎金。金額為2020年8月固定薪酬的 50%。
這波福利猿妹只能默默的感嘆一句:又是別人家的公司。不過今天猿妹不想和大家探討這項福利,今天要和大家分享字節(jié)跳動的一項開源神器。
前不久,字節(jié)跳動的技術(shù)團(tuán)隊在Github上開源了一個視頻動畫特效SDK,可以通過制作Alpha通道分離的視頻素材,再在客戶端上通過OpenGL ES重新實現(xiàn)Alpha通道和RGB通道的混合,從而實現(xiàn)在端上播放帶透明通道的視頻。
AlphaPlayer已經(jīng)在Github上標(biāo)星270,累計分支 28 個(Github地址:https://github.com/bytedance/AlphaPlayer)
目前,抖音、抖音火山版、西瓜小視頻、今日頭條已經(jīng)接入。
這套方案對設(shè)計師而言明顯降低了特效的制作成本,對于客戶端而言有著更可靠的性能和穩(wěn)定性,且相比cocos2d引擎有著更低的入門門檻和維護(hù)成本,為復(fù)雜動畫的實現(xiàn)提供了一種全新的方式,新的復(fù)雜動畫開發(fā)將會變得更加簡單高效。
運(yùn)行效果如下:
項目結(jié)構(gòu)&基本原理
AlphaPlayer主要有兩個核心部分,一個是MediaPlayer,負(fù)責(zé)視頻每一幀的解碼,支持接入方自行實現(xiàn);另一個是VideoRenderer,負(fù)責(zé)將解析出來的每一幀畫面進(jìn)行alpha通道混合,再輸出到Surface上。View使用的是GLSurfaceView,性能相對TextureView更優(yōu),但層級限制在最頂層。
AlphaPlayer內(nèi)部是通過Render渲染紋理畫面的,設(shè)計師導(dǎo)出的視頻資源會包含兩部分內(nèi)容——透明遮罩畫面和原視頻畫面兩部分,然后通過shader進(jìn)行alpha值的混合,詳細(xì)可以看 frag.sh和vertex.sh。
快速接入
- allprojects {
- repositories {
- ...
- maven { url 'https://jitpack.io' }
- }
- }
- dependencies {
- implementation 'com.github.bytedance:AlphaPlayer:1.0.3'
- }
添加依賴
- val config = Configuration(context, lifecycleOwner)
- // 支持GLSurfaceView&GLTextureView, 默認(rèn)使用GLSurfaceView
- config.alphaVideoViewType = AlphaVideoViewType.GL_TEXTURE_VIEW
- // 也可以設(shè)置自行實現(xiàn)的Player, demo中提供了基于ExoPlayer的實現(xiàn)
- val playerController = PlayerController.get(config, DefaultSystemPlayer())
- playerController.setPlayerAction(object: IPlayerAction {
- override fun onVideoSizeChanged(videoWidth: Int, videoHeight: Int, scaleType: ScaleType) {
- }
- override fun startAction() {
- }
- override fun endAction() {
- }
- })
- playController.setMonitor(object: IMonitor {
- override fun monitor(result: Boolean, playType: String, what: Int, extra: Int, errorInfo: String) {
- }
- })
初始化PlayerController
- playerController.attachAlphaView(mVideoContainer)
將PlayerController綁定到ViewGroup
- fun startVideoAnimation() {
- val baseDir = "your video file base dir"
- val portraitFileName = "portrait.mp4"
- val portraitScaleType = 2
- val landscapeFileName = "landscape.mp4"
- val landscapeScaleType = 2
- val dataSource = DataSource().setBaseDir(baseDir)
- .setPortraitPath(portraitFileName, portraitScaleType)
- .setLandscapePath(landscapeFileName, landscapeScaleType)
- if (dataSource.isValid()) {
- playerController.start(dataSource)
- }
- }
播放動畫視頻
- fun releasePlayerController() {
- playerController.detachAlphaView(mVideoContainer)
- playerController.release()
- }