从视频中获取多个缩略图 [英] Get multiple thumbnails from video

查看:129
本文介绍了从视频中获取多个缩略图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MediaMetadataRetriever来检索视频中特定时间的缩略图.这就是我实现此目标的方法:

I'm using MediaMetadataRetriever to retrieve thumbnails at a specific time in video. This is how I achieve this:

MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
    try {
        metadataRetriever.setDataSource(MainActivity.this, Uri.parse("android.resource://packageName/raw/"+"test"));
        String duration=metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        long time = Long.valueOf(duration)/3;
        Bitmap bitmap1 = metadataRetriever.getFrameAtTime(time,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
        imgone.setImageBitmap(bitmap1);

    }catch (Exception ex) {
        Toast.makeText(MainActivity.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
        }

这将按预期返回位图/缩略图,问题在于,如果我想在视频中的不同时间获取多个缩略图,如下所示:

This returns a bitmap/thumbnail as expected, the problem is that if I want to get multiple thumbnails at different times in the video like this:

MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
    try {
        metadataRetriever.setDataSource(MainActivity.this, Uri.parse("android.resource://packageName/raw/"+"test"));
        String duration=metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        long time = Long.valueOf(duration)/3;
        long time2 = time+time;
        long time3 = time+time+time;
        Bitmap bitmap1 = metadataRetriever.getFrameAtTime(time,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
        Bitmap bitmap2 = metadataRetriever.getFrameAtTime(time2,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
        Bitmap bitmap3 = metadataRetriever.getFrameAtTime(time3,MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
        imgone.setImageBitmap(bitmap1);
        imgtwo.setImageBitmap(bitmap2);
        imgthree.setImageBitmap(bitmap3);

    }catch (Exception ex) {
        Toast.makeText(MainActivity.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
        }

然后它仍然只返回相同的缩略图,我不确定是否是因为该视频只有一个缩略图可用,但是我尝试了具有相同结果的不同视频文件.

Then it still only returns the same thumbnail, I'm not sure if it is because there is only one thumbnail available for the video or what, but I've tried different video files with the same result.

我尝试将MediaMetadataRetriever.OPTION_CLOSEST_SYNC更改为所有可用选项,但结果仍然相同.

I've tried changing MediaMetadataRetriever.OPTION_CLOSEST_SYNC to all the available options but still the same result.

不确定FFMPEG是否会是更好的选择吗?

Im not sure if FFMPEG would be a better option for this?

推荐答案

正好一年后,我注意到我从未提供答案.

Exactly a year later, I noticed that I never provided an answer.

在最初的问题中,我想检索3个缩略图,最终检索到5个.我还提到我不确定FFmpeg是否适合使用,这正是我所使用的.

In the original question I wanted to retrieve 3 thumbnails, I ended up retrieving 5. I also mentioned that I'm not sure if FFmpeg will be a suitable option, that's exactly what I used.

因此,在OnCreate中,我确保支持FFmpeg,然后执行以下操作:

So, in OnCreate, I make sure that FFmpeg is supported and then I do the following:

if (FFmpeg.getInstance(getApplication()).isSupported()) {
      @SuppressLint("SimpleDateFormat")
      //ffmpeg expects the time format to be "00:00:00"
      Format formatter = new SimpleDateFormat("00:" + "mm:ss.SS");
      //Get the duration of the video
      long duration = player.getDuration();
      //Since I want 5 thumbnails, I divide the duration by 6 to get the first thumbnail position 
      long img1 = duration / 6;
      //I format the first thumbnail time since ffmpeg expects "00:00:00" format
      String firstTumbTime = formatter.format(img1);

      //Scale the size of the thumbnail output (this can be improved/changed to your liking)
      String scaledSize = displayMetrics.widthPixels / 7 + ":" + displayMetrics.heightPixels / 7;
      //Set ffmpeg command (notice that I set vframes to one, since I only want 1 thumbnail/image)
      String[] a = {"-ss", firstTumbTime, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb1.bmp"};
      //start ffmpeg asynctask for the first thumbnail
      ExecuteThumbFFMPEG(a);

}  else {
     Toast.makeText(TestNewPlayer.this, "Your device doesn't support FFMPEG...", Toast.LENGTH_SHORT).show();
}

上面代码中的注释说明了所有内容,现在是我的ExecuteThumbFFMPEG方法.

The comments in the code above explains everything, now here is my ExecuteThumbFFMPEG method.

public void ExecuteThumbFFMPEG(String[] command) {

    ffmpegImages = FFmpeg.getInstance(this).execute(command, new ExecuteBinaryResponseHandler() {

        @Override
        public void onStart() {
            //ffmpeg started
        }

        @Override
        public void onProgress(String message) {
            //get ffmpeg progress
        }

        @Override
        public void onFailure(String message) {
            //ffmpeg failed
        }

        @Override
        public void onSuccess(String message) {
            //first thumbnail saved successfully, now to get the other 4

            //Scale the thumbnail output (Same as above)
            String scaledSize = displayMetrics.widthPixels / 7 + ":" + displayMetrics.heightPixels / 7;

            try {
                //I first set the path/name for each thumbnail, this will also be used to check if the thumbnail is available or if we should get it
                String imgPath1 = imageThumbsDirectory + "/" + "thumb1.bmp";
                String imgPath2 = imageThumbsDirectory + "/" + "thumb2.bmp";
                String imgPath3 = imageThumbsDirectory + "/" + "thumb3.bmp";
                String imgPath4 = imageThumbsDirectory + "/" + "thumb4.bmp";
                String imgPath5 = imageThumbsDirectory + "/" + "thumb5.bmp";

                //Set the format again (same as above)
                @SuppressLint("SimpleDateFormat")
                Format formatter = new SimpleDateFormat("00:" + "mm:ss.SS");

                //Get the length of the video
                long duration = Player.getDuration();

                //Divide the length of the video by 6 (same as above)
                long time = duration / 6;

                //Since I want 5 thumbnails evenly distributed throughout the video
                //I use the video length divided by 6 to accomplish that
                long img2 = time + time;
                long img3 = time + time + time;
                long img4 = time + time + time + time;
                long img5 = time + time + time + time + time;

                //Format the time (calculated above) for each thumbnail I want to retrieve
                String Img2Timeformat = formatter.format(img2);
                String Img3Timeformat = formatter.format(img3);
                String Img4Timeformat = formatter.format(img4);
                String Img5Timeformat = formatter.format(img5);

                //Get reference to the thumbnails (to see if they have been created before)
                File fileimgPath1 = new File(imgPath1);
                File fileimgPath2 = new File(imgPath2);
                File fileimgPath3 = new File(imgPath3);
                File fileimgPath4 = new File(imgPath4);
                File fileimgPath5 = new File(imgPath5);

                //If thumbnail 1 exist and thumbnail 2 doesn't then we need to get thumbnail 2
                if (fileimgPath1.exists() && !fileimgPath2.exists()) {
                    //Get/decode bitmap from the first thumbnail path to be able to set it to our ImageView that should hold the first thumbnail
                    Bitmap bmp1 = BitmapFactory.decodeFile(imgPath1);
                    //Set the first thumbnail to our first ImageView
                    imgone.setImageBitmap(bmp1);
                    //Set the ffmpeg command to retrieve the second thumbnail
                    String[] ffmpegCommandForThumb2 = {"-ss", Img2Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb2.bmp"};
                    //Start ffmpeg again, this time we will be getting thumbnail 2
                    ExecuteThumbFFMPEG(ffmpegCommandForThumb2);
                }

                //If thumbnail 2 exist and thumbnail 3 doesn't then we need to get thumbnail 3
                if (fileimgPath2.exists() && !fileimgPath3.exists()) {
                    //Get/decode bitmap from the second thumbnail path to be able to set it to our ImageView that should hold the second thumbnail
                    Bitmap bmp2 = BitmapFactory.decodeFile(imgPath2);
                    //Set the second thumbnail to our second ImageView
                    imgTwo.setImageBitmap(bmp2);
                    //Set the ffmpeg command to retrieve the third thumbnail
                    String[] ffmpegCommandForThumb3 = {"-ss", Img3Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb3.bmp"};
                    //Start ffmpeg again, this time we will be getting thumbnail 3
                    ExecuteThumbFFMPEG(ffmpegCommandForThumb3);
                }

                ////If thumbnail 3 exist and thumbnail 4 doesn't then we need to get thumbnail 4
                if (fileimgPath3.exists() && !fileimgPath4.exists()) {
                    //Get/decode bitmap from the third thumbnail path to be able to set it to our ImageView that should hold the third thumbnail
                    Bitmap bmp3 = BitmapFactory.decodeFile(imgPath3);
                    //Set the third thumbnail to our third ImageView
                    imgThree.setImageBitmap(bmp3);
                    //Set the ffmpeg command to retrieve the fourth thumbnail
                    String[] ffmpegCommandForThumb4 = {"-ss", Img4Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb4.bmp"};
                    //Start ffmpeg again, this time we will be getting thumbnail 4
                    ExecuteThumbFFMPEG(ffmpegCommandForThumb4);
                }

                ////If thumbnail 4 exist and thumbnail 5 doesn't then we need to get thumbnail 5
                if (fileimgPath4.exists() && !fileimgPath5.exists()) {
                    //Get/decode bitmap from the first fourth path to be able to set it to our ImageView that should hold the fourth thumbnail
                    Bitmap bmp4 = BitmapFactory.decodeFile(imgPath4);
                    //Set the fourth thumbnail to our fourth ImageView
                    imgFour.setImageBitmap(bmp4);
                    //Set the ffmpeg command to retrieve the last thumbnail
                    String[] ffmpegCommandForThumb5 = {"-ss", Img5Timeformat, "-i", mStringFilePath, "-vframes", "1", "-s", scaledSize, imageThumbsDirectory + "/" + "thumb5.bmp"};
                    //Start ffmpeg again, this time we will be getting thumbnail 5
                    ExecuteThumbFFMPEG(ffmpegCommandForThumb5);
                }

                //If thumbnail 5 exist, then we are done and we need to set it to our ImageView
                if (fileimgPath5.exists()) {
                    Bitmap bmp5 = BitmapFactory.decodeFile(imgPath5);
                    imgFive.setImageBitmap(bmp5);
                }


            } catch (Exception ex) {
                Toast.makeText(Player.this, String.valueOf(ex), Toast.LENGTH_SHORT).show();
            }

        }

        @Override
        public void onFinish() {
            //ffmpeg is done
        }


    });

}

当调用从ActivityOnDestroy中退出的用户时,应删除所有缩略图,我可以通过调用以下方法来做到这一点:

When the user back out of the Activity or OnDestroy gets called, all the thumbnails should be deleted, I do this by calling the following method:

DeleteThumbs.deleteAllThumbnails(getBaseContext());

这是DeleteThumbs类,用于删除所有缩略图/图像

Here is the DeleteThumbs class for deleting all the thumbnails/images

class DeleteThumbs {

    @SuppressWarnings("unused")
    static void deleteAllThumbnails(Context baseContext){
        //Directory where all the thumbnails are stored
        File imageThumbsDirectory = baseContext.getExternalFilesDir("ThumbTemp");
        //Path to each thumbnail
        File f1 = new File(imageThumbsDirectory + "/" + "thumb1.bmp");
        File f2 = new File(imageThumbsDirectory + "/" + "thumb2.bmp");
        File f3 = new File(imageThumbsDirectory + "/" + "thumb3.bmp");
        File f4 = new File(imageThumbsDirectory + "/" + "thumb4.bmp");
        File f5 = new File(imageThumbsDirectory + "/" + "thumb5.bmp");

        boolean d1 = f1.delete();
        boolean d2 = f2.delete();
        boolean d3 = f3.delete();
        boolean d4 = f4.delete();
        boolean d5 = f5.delete();
    }

}

由于我们知道每个缩略图的名称,因此很容易一次将它们全部删除.

Since we know the name of each thumbnail, it's easy to delete them all at once.

这为我提供了5张缩略图,这些缩略图按比例缩放以减少加载到ImageView的时间.因为我将视频的时长除以6,所以我得到了5张在整个视频中均匀分布"的图像.

This provides me with 5 thumbnail images that are scaled to reduce loading time into the ImageView's. Because I divided the duration of the video by 6, I get 5 images that are evenly "distributed" throughout the video.

注意:

这可以通过将图像缓存到内存中或使用像Picasso或glide这样的库为我们处理图像加载来改善.

This can be improved by caching the images into memory or using a library like picasso or glide to handle the image loading for us.

这篇关于从视频中获取多个缩略图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆