在Android中,是否可以从视频URL生成缩略图?

32

我正在开发一款视频应用,从服务器链接中流式传输一个视频,是否有可能在不下载视频的情况下从该URL生成视频缩略图。


这是一个YouTube视频吗? - Karthik
9个回答

82

您可以使用以下代码生成视频缩略图,而无需下载视频:

public static Bitmap retriveVideoFrameFromVideo(String videoPath) throws Throwable
{
    Bitmap bitmap = null;
    MediaMetadataRetriever mediaMetadataRetriever = null;
    try
    {
        mediaMetadataRetriever = new MediaMetadataRetriever();
        if (Build.VERSION.SDK_INT >= 14)
            mediaMetadataRetriever.setDataSource(videoPath, new HashMap<String, String>());
        else
            mediaMetadataRetriever.setDataSource(videoPath);
   //   mediaMetadataRetriever.setDataSource(videoPath);
        bitmap = mediaMetadataRetriever.getFrameAtTime();
    } catch (Exception e) {
        e.printStackTrace();
        throw new Throwable("Exception in retriveVideoFrameFromVideo(String videoPath)" + e.getMessage());

    } finally {
        if (mediaMetadataRetriever != null) {
            mediaMetadataRetriever.release();
        }
    }
    return bitmap;
}

注意:视频以Intra和非Intra(画面帧)的形式存储,getFrameAtTime将返回最接近的非Intra帧作为位图。因此,它不会下载整个视频。


1
@lostintranslation 视频以Intra和非Intra(图片帧)的形式存储,getFrameAtTime将返回最接近的非Intra帧作为位图。因此,它基本上不会下载整个视频。希望你得到了答案。 - KishuDroid
2
谢谢@KishuDroid,我做到了,但是这个挑战的问题在于,在Lollipop 5上加载太慢了,难道没有任何很酷的库可以将URL视频加载到RecyclerView中吗? - Lutaaya Huzaifah Idris
1
如果您从服务器获取视频链接,那么您也可以向服务器请求视频的缩略图,然后将其加载到recyclerview中。这是加载视频的简单快速方法。 - KishuDroid
@KishuDroid,“String videoPath”是视频的URL吗? - ken
1
@KishuDroid 我使用了你的代码,它工作得很好。但是有一个问题,当视频很短时,有时缩略图不会出现,只是空白。 - ken
显示剩余8条评论

15

我尝试了使用Glide,它起作用了,Glide版本为4.3.1

    GlideApp.with(context)
                .asBitmap()
                .load(FILE_URL)
                .diskCacheStrategy(DiskCacheStrategy.DATA)
                .into(iv_picture);

编辑:Glide 对我来说运行缓慢

排名第一的答案对某些视频没有结果,这是我做的方法

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
 //give YourVideoUrl below
retriever.setDataSource("YourVideoUrl", new HashMap<String, String>());
// this gets frame at 2nd second
Bitmap image = retriever.getFrameAtTime(2000000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); 
//use this bitmap image

retriever.release() -> 我认为在完成后需要释放MediaMetadataRetriver。 - Hadi Ahmadi
你的第二个解决方案可行...谢谢,继续保持。 - Pir Fahim Shah

13

无法从流媒体链接创建缩略图,必须从服务器上显示。最好在视频上传时一并上传缩略图。 使用以下代码生成缩略图

Bitmap bitmap = ThumbnailUtils.createVideoThumbnail("picturePath", MediaStore.Video.Thumbnails.MINI_KIND);

该方法已被弃用。 - famfamfam

5

嗨,我能够从录制的视频中创建缩略图。但是在流式传输时是否可能? - DKV

4

您可以像下面所示从服务器URL生成缩略图

RequestOptions requestOptions = new RequestOptions();
requestOptions.isMemoryCacheable();
requestOptions.override(70,70);             
Glide.with(context).setDefaultRequestOptions(requestOptions).load(model.getMediaURL()).into(myViewHolder.imageView);

1
Bitmap bitmap = ThumbnailUtils.createVideoThumbnail("VIDEO FILE ADDRESS", MediaStore.Video.Thumbnails.MINI_KIND);

1
此方法已被弃用。 - famfamfam

0

这个方法可以为您的手机中的所有视频文件生成缩略图... 如有任何问题,请随时提问

public static Bitmap[] getThumbnail(Context context){
        Uri uri=MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        String[] projection=new String[] { MediaStore.Video.Thumbnails._ID };
        Cursor ca = context.getContentResolver().query(uri, projection, null, null, null);
        Bitmap[] b=new Bitmap[ca.getCount()];
        int i=0;
        ca.moveToFirst();
        while(i<ca.getCount()) {
            int id = ca.getInt(ca.getColumnIndex(MediaStore.Video.Thumbnails._ID));
            b[i++]=MediaStore.Video.Thumbnails.getThumbnail(context.getContentResolver(),id, MediaStore.Images.Thumbnails.MINI_KIND, null );
            ca.moveToNext();
        }
        ca.close();
        return b;
    }

0

这里是最佳解决方案

"https://img.youtube.com/vi/" + videoID + "/0.jpg"

在这里,videoID是从YouTube网址中获取的。


-2
我们在Android手机中获取所有视频。http://sunilkmrnishad.blogspot.in/2017/03/read-files-apps-photos-media-from.html
public class ThumbnailExtract extends AsyncTask<String, long[], Bitmap> {

    private final String videoUrl;
    private final ImageView mThumbnail;
    private final boolean mIsVideo;
    private MediaMetadataRetriever mmr;

    public ThumbnailExtract(String videoLocalUrl, ImageView thumbnail, boolean isVideo) {
        this.videoUrl = videoLocalUrl;
        mThumbnail = thumbnail;
        mIsVideo = isVideo;
        if (!isVideo) {
            mmr = new MediaMetadataRetriever();
        }
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        if (!mIsVideo) {
            return getBitmap(videoUrl);
        } else {
            return ThumbnailUtils.createVideoThumbnail(videoUrl,
                    MediaStore.Images.Thumbnails.MINI_KIND);
        }
    }

    @Override
    protected void onPostExecute(Bitmap thumb) {
        if (thumb != null) {
            mThumbnail.setImageBitmap(thumb);
        }
    }

    private Bitmap getBitmap(String fileUrl) {
        mmr.setDataSource(fileUrl);
        byte[] data = mmr.getEmbeddedPicture();
        Bitmap bitmap = null;
        // convert the byte array to a bitmap
        if (data != null) {
            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

        }
        return bitmap != null ? ScalingUtilities.createScaledBitmap(bitmap, 40, 40, ScalingUtilities.ScalingLogic.FIT) : bitmap;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接