Getting a thumbnail for a remote video without downloading it completely

64 Views Asked by At

I have a list of links to video files located on a server on the network.

I need to display this list with thumbnails for each video. The first frame of this video would suit me.

How can I show a thumbnail without downloading the entire file?

Glide, Coil download the entire file.

FFmpegMediaMetadataRetriever increases the app APK file size by 40+ MB.

What are the possible solutions? I looked towards the ExoPlayer, but I can’t extract one frame with it.

2

There are 2 best solutions below

3
Ammar On

Have a look at the below code it's via native MediaMetadataRetriever

import android.content.Context
import android.graphics.Bitmap
import android.media.MediaMetadataRetriever
import android.net.Uri
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

fun Context.getVideoThumbnail(url: String): Bitmap? {

    val retriever = MediaMetadataRetriever()
    retriever.setDataSource(this, Uri.parse(Uri.encode(url)))

    val timeUs = 3*1000000L // The frame at which seconds you need as thubmnail
    val thumbnailBitmap = retriever.getFrameAtTime(timeUs)

    retriever.release()
    return thumbnailBitmap
}

@Preview(showSystemUi = true)
@Composable
fun VideoThubnailLoading() {
    val context = LocalContext.current
    val bitmp = remember { mutableStateOf<Bitmap?>(null) }

    LaunchedEffect(Unit) {
        bitmp.value =
            context.getVideoThumbnail("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
    }
    Column {
        Text("Hello Video Thumbail loading")

        bitmp.value?.let {
            Image(
                bitmap = it.asImageBitmap(),
                contentDescription = null,
                modifier = Modifier
                    .fillMaxSize()
                    .padding(16.dp) 
            )
        }
    }

}

here's what it'll look like: enter image description here

0
usr153.K On

I guess it's working in progress.

According to exoplayer commit, actual thoumbnails are put on the same media server. I guess dash encoder generates thumbnails and app side downloads thumbnail tiles and crops its frame image.

Here is a demo dash file.

However, I think the easiest way is

  1. Create thumbnails from ffmpeg. Create thumbnail from video using ffmpeg
  2. Put thumbnails on the same resource server and app downloads it simply.