LANGUAGES, METHODLOGY/Kotlin

[안드로이드 | ExoPlayer] EventListener를 활용해 여러개의 동영상 연달아 재생하기

언제나중수 2019. 11. 11. 15:40

ExoPlayer를 동영상 재생에 쓰던 중에

 

여러개의 영상을 연달아 보여줘야 하는 요구사항이 생겼다.

 

이를 위해 일전에 에셋을 리스트 형태로 만들어 다른 용도로 썼던 것을 떠올려 구현을 해보기로 했다.

 

 


 

< 차례 >

 

1. ExoPlayer Initialize

2. 비디오 에셋 resourceList 설정

3. ProgressiveMediaSource ArrayList에 차례대로 resourceList를 로딩해 add

4. Player.EventListener Initialize

5. ExoPlayer에 listener add

6. ExoPlayer.setShutterBackgroundColor(Color.TRANSPARENT)

7. 영상을 차례대로 재생하는 플레이어 감상

 

< 단계별 설명 >

 

- 기본 설정 -

  • 먼저 ExoPlayer를 위한 기본 implementation을 마친 상태
  • 뷰를 가져오는 데 Data binding을 사용하였음.
  • Kotlin 기반
  • Data binding을 쓰지 않는다면, exoPlayerView를 참조하는 과정만 findViewById로 대체해 사용하면 무방함.

1. ExoPlayer Initialize

val player = ExoPlayerFactory.newSimpleInstance(context)

player.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
binding.exoPlayerView.player = player
binding.exoPlayerVIew.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL

 - scalingMode나 resizeMode의 경우 View에 꽉 찬 영상을 보여주기 위해 설정해주었음.

 

 

2. 비디오 에셋 resourceList 설정

val resourceList = listOf(
  R.raw.sample_01,
  R.raw.sample_02,
  R.raw.sample_03
)

 

3. ProgressiveMediaSource ArrayList에 차례대로 resourceList를 로딩해 add

val dataSoruceFactory = DefaultDataSourceFactory(context, 
                          Util.getUserAgent(context, "앱이름"))

val videoResourceList = ArrayList()

var tempSource: RawResourceDataSource

for (i in resourceList.indices) {
    tempSource = RawResoruceDataSource(context)
    tempSource.open(DataSpec(RawResourceDataSource
                    .buildRawResourceUri(resourceList[i])
    videoResourceList.add(ProgressiveMediaSource.Factory(dataSourceFactory)
              .createMediaSource(rawDataSource.uri)
 }

 - 비디오 리소스를 만들기 위해 별도로 dataSourceFactory를 생성해야 하며, 생성에는 인자로 context와 앱 이름을 필요로 함.

 

4. Player.EventListener Initialize

val eventListener : Player.EventListener

var videoIndex = 0

eventListener = object: Player.EventListener {
   
    override fun onPlayerStateChanged(playWhenReady: Boolean, playBackState: Int) {
          if (playBackState == Player.STATE_ENDED) { 
              player.prepare(videoResourceList[videoIndex])
          }
          
          videoIndex++
          
    }
    
    super.onPlayerStateChanged(playWhenReady, playBackState)
}

- EventListener의 onPlayerStateChanged를 사용해 ExoPlayer가 한개의 영상 재생을 마칠 때(player.STATE_ENDED)

다음 영상을 로딩하도록 구성.

 

** 여기에서 super.onPlayerStateChanged 를 수행하면서

 

... interfaces are prohibited in JVM target 1.6. ..  라는식의  컴파일 오류가 발생했고

 

이를 해결하기 위해 app레벨의 gradle에 아래 옵션을 추가하였음.

android {

...

kotlinOptions {     
     jvmTarget = '1.8'
}

...

}

 

5. ExoPlayer에 listener add

player.addListener(eventListener)

 

6. ExoPlayer.setShutterBackgroundColor(Color.TRANSPARENT)

binding.exoPlayerView.userController = false
binding.exoPlayerView.setShutterBackgroundColor(Color.TRANSPARENT)

- 컨트롤러를 필요로 하지 않았기 때문에 userController를 false로 설정

- 동영상이 바뀔 때 플레이어의 화면이 까맣게 깜박이는 현상이 있었고, 이를 제거하기 위해 setShutterBackgroundColor를 투명으로 설정.

 

7. 영상을 차례대로 재생하는 플레이어 감상

 

 

< 참조 >

 

https://github.com/google/ExoPlayer/issues/2843 

 

Provide option to keep the last frame of a previous source visible when switching sources · Issue #2843 · google/ExoPlayer

First of all, congrats on the io'17 ExoPlayer presentation! Issue description I would like to implement a "hold picture" (or freeze) functionality in the app, where a player would hol...

github.com

https://stackoverflow.com/questions/48601549/why-kotlin-gradle-plugin-cannot-build-with-1-8-target

 

Why kotlin gradle plugin cannot build with 1.8 target?

I have the simplest gradle project configured using intellij for kotlin 1.2.10. Here is my build.gradle file: buildscript { ext.kotlin_version = '1.2.10' repositories { mavenCentr...

stackoverflow.com