最近接到一個需求:要播放影片,並且對影片做模糊處理。
9102年都快過了,好ExoPlayer不玩嗎?
廢話不多,先上GitHub:
https://github.com/AndyAWD/ExoPlayerBlur
用ExoPlayer播影片並不是什麼難事,上面的GitHub有基本顯示的實作方法,而且還是2.10.5最新版的寫法,別的地方應該還找不到,但影片模糊處理就有點麻煩,最早我用"exoplayer blur"當關鍵字找到一篇用OpenGL的寫法。
基於exoplayer播放器的高斯模糊視頻濾鏡
https://blog.csdn.net/liosen/article/details/83896721
他的寫法是把整個ExpPlayer抓下來壓成aar檔,複製其中的某些類別手動新增模糊的ArrayList,但這樣的問題是以後無法升級ExoPlayer的版本,我程度不夠用繼承改寫也失敗。
不過他的寫法也發現ExoPlayer可以將影像傳到TextureView上,TextureView也能用監聽的方式取得影片每一幀的Bitmap,再對Bitmap做特效處理後顯示在ImageView上,一切都是那麼美好。
簡單教學:
第一步,建立Xml,Blogger貼Xml會有問題,只好貼圖請見諒,PlayerView要額外設定surface_type="texture_view":
第二步,初始化ExoPlayer然後和TextureView建立關連:
private var textureView: TextureView? = null
private var imageView: ImageView? = null
private var simpleExoPlayer: SimpleExoPlayer? = null
private fun initExoPlayer() {
val videoTrackSelectionFactory: TrackSelection.Factory = AdaptiveTrackSelection.Factory()
val trackSelector: TrackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
val loadControl = DefaultLoadControl()
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(applicationContext, trackSelector, loadControl)
simpleExoPlayer?.prepare(mediaSource("VideoUrl"))
simpleExoPlayer?.addListener(this)
simpleExoPlayer?.playWhenReady = true
simpleExoPlayer?.repeatMode = Player.REPEAT_MODE_ALL
textureView.alpha = 0.0f //把TextureView設為透明,這樣模糊失敗的話也看不到影片
}
private fun mediaSource(uri: Uri): ProgressiveMediaSource {
val defaultBandwidthMeter: DefaultBandwidthMeter = DefaultBandwidthMeter.Builder(applicationContext).build()
val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(applicationContext, Util.getUserAgent(applicationContext, resources.getString(R.string.app_name)), defaultBandwidthMeter)
val extractorsFactory: ExtractorsFactory = DefaultExtractorsFactory()
return ProgressiveMediaSource.Factory(dataSourceFactory,extractorsFactory).setLoadErrorHandlingPolicy(this).createMediaSource(uri)
}
第三步,監聽TextureView,把處理後的圖片顯示出來:
這邊我偷懶直接用別人寫好的模糊第三方EasyBlur,他的模糊可以在1~25調整,如果覺得不夠可以再調整壓縮比讓圖片更霧,如果要自己寫的話要記得先壓縮得到的Bitmap,不然還沒處理模糊就會oom
textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener { override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) { return } override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) { //使用EasyBlur處理Bitmap val bitmapBlur = EasyBlur.with(EBApplication.context()).bitmap(textureView.bitmap).scale(10).radius(25).blur() imageView.setImageBitmap(bitmapBlur) } override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean { return false } override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) { simpleExoPlayer.setVideoSurface(Surface(surface)) } }
後記:
寫完這篇後我不小心在GitHub上用"ExoPlayer Filter"去找,結果找到一篇用OpenGL寫好的ExoPlayer第三方套件ExoPlayerFilter,所以說寫程式英文真的很重要,直接影響Google的基本能力
沒有留言:
張貼留言