여러 개의 영상을 Exoplayer로 순차 재생하기
What is ExoPlayer?
ExoPlayer는 Google의 오픈 소스 라이브러리로 Android의 MediaPlayer보다 더 많은 기능을 지원해주는 미디어 재생 라이브러리입니다. 로컬 파일은 물론 인터넷에서 가져오는 오디오 및 비디오를 재생할 수 있으며 쉽게 사용할 수 있고 커스텀이 가능합니다. 자세한 설명은 아래 공식 홈페이지를 참조해보시면 됩니다.
제가 구현해야 하는 기능은 하나의 화면에 여러 개의 영상이 있고, 그 중 사용자가 재생 버튼을 눌렀을 때 영상이 재생되도록 하는 것이었습니다. 마치 페이스북의 비디오 타임라인처럼 만드는 것이 목표였는데 이를 구현하기 위해 ExoPlayer를 이용했습니다. 이를 위해 XML 파일로 exo_player_control_view
와 exo_player_view
를 만들어 id를 각 PlayerView
의 id와 매핑해주어 사용했습니다. (이렇게 사용하면 자동으로 PlayerView
가 XML을 인식하여 뷰를 inflate
하지 않아도 사용이 가능합니다.)
⚠️ 문제점
저는 ExoPlayer를 사용하여 영상을 재생시키기 위해 PlayerView
를 상속받은 커스텀 뷰를 구현하였고 커스텀 뷰 안에서는 SimpleExoPlayer
인스턴스를 init
블록에서 생성해주었습니다.
생성한 인스턴스를 PlayerView
의 player
에 넣어주고 재생하는 식으로 사용했는데 이 때 문제가 발생했습니다. ExoPlayer 공식 홈페이지를 보면 player
를 사용한 후 반드시 release()
메소드를 통해 리소스를 해제해주라고 설명되어 있습니다. 하지만 어떤 이유에서인지 리소스가 제대로 해제되지 않았고 핸드폰 기종에 따라 1~7개의 영상을 재생한 후 다음 영상을 재생하려 할 때 영상을 재생할 수 없었습니다. 해당 이슈에 대한 해결책을 구하기 위해 ExoPlayer 깃허브에서 관련 이슈를 찾아보았으나 확실한 솔루션을 구하지 못했습니다.😭
✨ 해결책
위 문제는 핸드폰의 기종에 따라 최대 인스턴스의 생성 갯수가 제한되어 있었기때문(메모리 문제) 이었습니다. 그래서 저는 따로 player
를 관리해주는 클래스(VideoManager
)를 만들어 SimpleExoPlayer
인스턴스를 싱글톤으로 하나만 만들어 사용해주도록 하였습니다. 원리는 간단합니다. 커스텀 뷰의 init
블록에서 VideoManager
에 커스텀 뷰의 해시코드와 뷰를 넘기고 VideoManager
에 해시맵 변수를 하나 두어 전달받은 해시코드와 뷰를 관리하도록 하게 하였습니다. 그리고 exo_player_view
의 exo_sutter
를 id로 가진 FrameLayout
에 가짜 재생 버튼을 하나 만들어서 넣고 이 버튼을 클릭할 경우 VideoManager
의 currentHashCode
변수와 현재 재생 중인 뷰의 해시코드를 비교하여 다를 경우 PlayerView.switchTargetView()
메소드를 사용하여 싱글톤으로 만든 SimpleExoPlayer
인스턴스와 해시맵에 저장된 뷰를 사용하여 플레이어를 사용할 뷰를 교체해주면 됩니다. 가짜 재생 버튼을 exo_sutter
를 id로 가진 FrameLayout
안에 만들어준 이유는 FrameLayout
은 현재 PlayerView
의 player
가 null
인 경우에 보여지는 레이아웃이기 때문에 여기에 가짜 재생 버튼을 만들어 이 버튼을 눌렀을 경우 SimpleExoPlayer
인스턴스를 교체해준 후 재생시키도록 하기 위함입니다.
결론
해결책에는 여러가지 방법이 있을 수 있지만 저는 인스턴스를 싱글톤으로 관리하는 방법을 적용하여 페이스북과 비슷한 비디오 타임라인을 구현하였습니다. 구글에서 좋은 해결책을 던져주길 바라며 혹시나 더 좋은 해결책이 있다면 댓글로 남겨주시면 감사드리겠습니다.