[Android, Kotlin] 영상/비디오 Thumbnail을 Bitmap으로 추출하기

설렁탕S.L.T·2021년 9월 4일
0

Kotlin

목록 보기
1/1

운영하는 서비스 개발 중 URI를 통한 영상/비디오의 Thumbnail(썸네일)을 추출하여 준비시켜놓아야 했기에 MediaMetaDataRetriever를 통해 썸네일 추출 방법을 찾아보고 적용해보았다.

1. MediaMetaDataRetriever를 통한 URI 영상/비디오 썸네일 추출

1) MediaMetaDataRetriever란?

구글 공식 문서에서는 'MediaMetadataRetriever 클래스는 입력 된 미디어 파일로부터 프레임 메타 데이터를 검색하기위한 통일 된 인터페이스를 제공한다.'라고 설명하고 있다.

미디어 파일에는 영상 혹은 이미지의 사이즈, 크기, 회전 여부 등 다양한 MetaData가 내재되어 있는데, MediaMetaDataRetriever는 이러한 정보를 꺼내주는 역할을 하는 것이다.

실제로, 운영중인 서비스에서 영상의 길이, bitrate, 사이즈 등을 확인하기 위해 MediaMetaDataRetriever를 사용하였다.

2) Thumbnail을 Bitmap으로 추출하기

백문이 불여일견이라고 바로 코드를 확인해보자

class VideoThumbnailUtil {
    //영상의 1초 시간의 사진을 가져옴
    val thumbnailTime = 1

    fun getWebVideoThumbnail(uri : Uri) : Bitmap? {
        val retriever = MediaMetadataRetriever()

        try {
            retriever.setDataSource(uri.toString(), HashMap<String,String>())
            return retriever.getFrameAtTime((thumbnailTime * 1000000).toLong(), MediaMetadataRetriever.OPTION_CLOSEST)
        } catch (e : IllegalArgumentException){
            e.printStackTrace()
        } catch (e : RuntimeException){
            e.printStackTrace()
        } finally {
            try {
                retriever.release()
            } catch (e : RuntimeException){
                e.printStackTrace()
            }
        }
        return null
    }
}

영상 추출을 위해 우선 MediaMetadataRetriever(val retriever)를 생성해주고, retriever에 추출할 영상의 URI을 담아준다.

  • setDataSource(uri: String!, headers: MutableMap<String!, String!>!)

그 후 retriever에 getFrameAtTime을 사용하여 원하는 부분의 마이크로세컨드(백만분의 1초, 10^-6)를 지정하면 원하는 부분의 Bitmap을 얻을 수 있다.

  • MediaMetadataRetriever.OPTION_CLOSEST: This option is used with getFrameAtTime(long,int) to retrieve a frame (not necessarily a key frame) associated with a data source that is located closest to or at the given time.

2. 추출된 Bitmap을 Background Thread에서 ImageView에 담아주기(Coil 라이브러리 활용)

1) RX Kotlin을 활용하여 Bitmap을 ImageView에 비동기적으로 담아주기

한편, 비디오 썸네일 추출은 당연하게도 작업 시간이 걸리기 때문에 많은 양을 Main Thread에서 작업할 경우 화면이 멈추거나 느려지는 현상을 겪을 수 있다. 그렇기 때문에 여러 영상의 썸네일을 추출하기 위해선 Background Thread에서 작업하도록 제어해야한다.

videoThumbnailDisposable = Observable.just("${영상 url}")
            .subscribeOn(Schedulers.io())
            .subscribe {
                binding.ivVideoThumbnail.load(
                    VideoThumbnailUtil().getWebVideoThumbnail(Uri.parse("${영상 url}"))}

RX Kotlin으로 Background Thread(Schedulers.io())에서 binding.ivVideoThumbnail이라는 ImageView에 Coil 라이브러리를 활용하여 결과물인 bitmap을 담아주었다.

profile
안드로이드 개발!

1개의 댓글

comment-user-thumbnail
2021년 10월 15일

좋은 글 감사합니다!! 질문좀 드리고 싶은데 가능할까요?.?ㅜㅜ

답글 달기