Android:是否可以显示视频缩略图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1334694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:56:27  来源:igfitidea点击:

Android: Is it possible to display video thumbnails?

android

提问by Niko Gamulin

I created a video recording application with library dialog. The library dialog displays the list of recorded videos where each item consists of icon, video title, tags and location information the following way:

我创建了一个带有库对话框的视频录制应用程序。库对话框显示录制的视频列表,其中每个项目都包含图标、视频标题、标签和位置信息,方式如下:

alt text

替代文字

Does anyone know whether it is possible to replace icons with video thumbnails (single frame preview)?

有谁知道是否可以用视频缩略图(单帧预览)替换图标?

Thanks!

谢谢!

采纳答案by Greg Zimmers

If you are using API 2.0 or newer this will work.

如果您使用的是 API 2.0 或更高版本,这将起作用。

int id = **"The Video's ID"**
ImageView iv = (ImageView ) convertView.findViewById(R.id.imagePreview);
ContentResolver crThumb = getContentResolver();
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap curThumb = MediaStore.Video.Thumbnails.getThumbnail(crThumb, id, MediaStore.Video.Thumbnails.MICRO_KIND, options);
iv.setImageBitmap(curThumb);

回答by Damien Praca

if you don't or cannot go through cursor and if you have only paths or File objects, you can use since API level 8 (2.2) public static Bitmap createVideoThumbnail (String filePath, int kind)

如果你没有或不能通过光标,如果你只有路径或文件对象,你可以使用自 API 级别 8 (2.2) public static Bitmap createVideoThumbnail (String filePath, int kind)

Android documentation

安卓文档

The following code runs perfectly:

以下代码完美运行:

Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);

回答by Jorgesys

Using the class:

使用类:

import android.provider.MediaStore.Video.Thumbnails;

We can get two preview thumbnail sizes from the video:

我们可以从视频中获得两种预览缩略图大小:

Thumbnails.MICRO_KINDfor 96 x 96

Thumbnails.MICRO_KIND96 x 96

Thumbnails.MINI_KINDfor 512 x 384 px

Thumbnails.MINI_KIND为 512 x 384 像素

This is a code example:

这是一个代码示例:

String filePath = "/sdcard/DCIM/Camera/my_video.mp4"; //change the location of your file!

ImageView imageview_mini = (ImageView)findViewById(R.id.thumbnail_mini);
ImageView imageview_micro = (ImageView)findViewById(R.id.thumbnail_micro);

Bitmap bmThumbnail;

//MICRO_KIND, size: 96 x 96 thumbnail
bmThumbnail = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MICRO_KIND);
imageview_micro.setImageBitmap(bmThumbnail);

// MINI_KIND, size: 512 x 384 thumbnail 
bmThumbnail = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MINI_KIND);
imageview_mini.setImageBitmap(bmThumbnail);

回答by Amir

Currently I Use following code :

目前我使用以下代码:

Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);

But I found better solution with Glidelibrary with following code ( It also cache your image and have better performance than previous approach )

但是我找到了使用以下代码的Glide库更好的解决方案(它还可以缓存您的图像并且比以前的方法具有更好的性能)

Glide.with(context)
                .load(uri)
                .placeholder(R.drawable.ic_video_place_holder)
                .into(imageView);

回答by Edouard Brèthes

I really suggest you to use the Glidelibrary. It's among the most efficient way to generate and display a video thumbnail for a local video file.

我真的建议你使用Glide库。这是为本地视频文件生成和显示视频缩略图的最有效方法之一。

Just add this line to your gradle file :

只需将此行添加到您的 gradle 文件中:

compile 'com.github.bumptech.glide:glide:3.7.0'

And it will become as simple as :

它将变得如此简单:

String filePath = "/storage/emulated/0/Pictures/example_video.mp4";

Glide  
    .with( context )
    .load( Uri.fromFile( new File( filePath ) ) )
    .into( imageViewGifAsBitmap );

You can find more informations here : https://futurestud.io/blog/glide-displaying-gifs-and-videos

你可以在这里找到更多信息:https: //futurestud.io/blog/glide-displaying-gifs-and-videos

Cheers !

干杯!

回答by Abandoned Cart

This solution will work for any version of Android. It has proven to work in 1.5 and 2.2 This is not another "This is for Android 2.0+" solution. I found this through an email message board collection page and cannot find the original link. All credit goes to the original poster.

此解决方案适用于任何版本的 Android。它已被证明适用于 1.5 和 2.2 这不是另一个“适用于 Android 2.0+”的解决方案。我是通过电子邮件留言板收藏页面找到的,但找不到原始链接。所有功劳归于原始海报。

In your app you would use this by calling:

在您的应用程序中,您可以通过调用来使用它:

Bitmap bm = getVideoFrame(VideoStringUri);

Somewhere in it's own function (outside the OnCreate, ect), you would need:

在它自己的函数中的某个地方(在 OnCreate 之外,等等),你需要:

private Bitmap getVideoFrame(String uri) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
            retriever.setDataSource(uri);
            return retriever.captureFrame();
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        } catch (RuntimeException ex) {
            ex.printStackTrace();
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException ex) {
            }
        }
        return null;
    }

In your src folder, you need a new subdirectory android/media which will house the class (copied from the android source itself) which allows you to use this function. This part should not be changed, renamed, or placed anywhere else. MediaMetadataRetriever.java needs to be under android.media in your source folder for this all to work.

在您的 src 文件夹中,您需要一个新的子目录 android/media 来存放允许您使用此功能的类(从 android 源代码本身复制)。这部分不应更改、重命名或放置在其他任何地方。MediaMetadataRetriever.java 需要在源文件夹中的 android.media 下才能正常工作。

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;

/**
 * MediaMetadataRetriever class provides a unified interface for retrieving
 * frame and meta data from an input media file. {@hide}
 */
public class MediaMetadataRetriever {
    static {
        System.loadLibrary("media_jni");
        native_init();
    }

    // The field below is accessed by native methods
    private int mNativeContext;

    public MediaMetadataRetriever() {
        native_setup();
    }

    /**
     * Call this method before setDataSource() so that the mode becomes
     * effective for subsequent operations. This method can be called only once
     * at the beginning if the intended mode of operation for a
     * MediaMetadataRetriever object remains the same for its whole lifetime,
     * and thus it is unnecessary to call this method each time setDataSource()
     * is called. If this is not never called (which is allowed), by default the
     * intended mode of operation is to both capture frame and retrieve meta
     * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY). Often,
     * this may not be what one wants, since doing this has negative performance
     * impact on execution time of a call to setDataSource(), since both types
     * of operations may be time consuming.
     * 
     * @param mode
     *            The intended mode of operation. Can be any combination of
     *            MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY: 1.
     *            MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: For neither
     *            frame capture nor meta data retrieval 2.
     *            MODE_GET_METADATA_ONLY: For meta data retrieval only 3.
     *            MODE_CAPTURE_FRAME_ONLY: For frame capture only 4.
     *            MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: For both
     *            frame capture and meta data retrieval
     */
    public native void setMode(int mode);

    /**
     * @return the current mode of operation. A negative return value indicates
     *         some runtime error has occurred.
     */
    public native int getMode();

    /**
     * Sets the data source (file pathname) to use. Call this method before the
     * rest of the methods in this class. This method may be time-consuming.
     * 
     * @param path
     *            The path of the input media file.
     * @throws IllegalArgumentException
     *             If the path is invalid.
     */
    public native void setDataSource(String path)
            throws IllegalArgumentException;

    /**
     * Sets the data source (FileDescriptor) to use. It is the caller's
     * responsibility to close the file descriptor. It is safe to do so as soon
     * as this call returns. Call this method before the rest of the methods in
     * this class. This method may be time-consuming.
     * 
     * @param fd
     *            the FileDescriptor for the file you want to play
     * @param offset
     *            the offset into the file where the data to be played starts,
     *            in bytes. It must be non-negative
     * @param length
     *            the length in bytes of the data to be played. It must be
     *            non-negative.
     * @throws IllegalArgumentException
     *             if the arguments are invalid
     */
    public native void setDataSource(FileDescriptor fd, long offset, long length)
            throws IllegalArgumentException;

    /**
     * Sets the data source (FileDescriptor) to use. It is the caller's
     * responsibility to close the file descriptor. It is safe to do so as soon
     * as this call returns. Call this method before the rest of the methods in
     * this class. This method may be time-consuming.
     * 
     * @param fd
     *            the FileDescriptor for the file you want to play
     * @throws IllegalArgumentException
     *             if the FileDescriptor is invalid
     */
    public void setDataSource(FileDescriptor fd)
            throws IllegalArgumentException {
        // intentionally less than LONG_MAX
        setDataSource(fd, 0, 0x7ffffffffffffffL);
    }

    /**
     * Sets the data source as a content Uri. Call this method before the rest
     * of the methods in this class. This method may be time-consuming.
     * 
     * @param context
     *            the Context to use when resolving the Uri
     * @param uri
     *            the Content URI of the data you want to play
     * @throws IllegalArgumentException
     *             if the Uri is invalid
     * @throws SecurityException
     *             if the Uri cannot be used due to lack of permission.
     */
    public void setDataSource(Context context, Uri uri)
            throws IllegalArgumentException, SecurityException {
        if (uri == null) {
            throw new IllegalArgumentException();
        }

        String scheme = uri.getScheme();
        if (scheme == null || scheme.equals("file")) {
            setDataSource(uri.getPath());
            return;
        }

        AssetFileDescriptor fd = null;
        try {
            ContentResolver resolver = context.getContentResolver();
            try {
                fd = resolver.openAssetFileDescriptor(uri, "r");
            } catch (FileNotFoundException e) {
                throw new IllegalArgumentException();
            }
            if (fd == null) {
                throw new IllegalArgumentException();
            }
            FileDescriptor descriptor = fd.getFileDescriptor();
            if (!descriptor.valid()) {
                throw new IllegalArgumentException();
            }
            // Note: using getDeclaredLength so that our behavior is the same
            // as previous versions when the content provider is returning
            // a full file.
            if (fd.getDeclaredLength() < 0) {
                setDataSource(descriptor);
            } else {
                setDataSource(descriptor, fd.getStartOffset(),
                        fd.getDeclaredLength());
            }
            return;
        } catch (SecurityException ex) {
        } finally {
            try {
                if (fd != null) {
                    fd.close();
                }
            } catch (IOException ioEx) {
            }
        }
        setDataSource(uri.toString());
    }

    /**
     * Call this method after setDataSource(). This method retrieves the meta
     * data value associated with the keyCode.
     * 
     * The keyCode currently supported is listed below as METADATA_XXX
     * constants. With any other value, it returns a null pointer.
     * 
     * @param keyCode
     *            One of the constants listed below at the end of the class.
     * @return The meta data value associate with the given keyCode on success;
     *         null on failure.
     */
    public native String extractMetadata(int keyCode);

    /**
     * Call this method after setDataSource(). This method finds a
     * representative frame if successful and returns it as a bitmap. This is
     * useful for generating a thumbnail for an input media source.
     * 
     * @return A Bitmap containing a representative video frame, which can be
     *         null, if such a frame cannot be retrieved.
     */
    public native Bitmap captureFrame();

    /**
     * Call this method after setDataSource(). This method finds the optional
     * graphic or album art associated (embedded or external url linked) the
     * related data source.
     * 
     * @return null if no such graphic is found.
     */
    public native byte[] extractAlbumArt();

    /**
     * Call it when one is done with the object. This method releases the memory
     * allocated internally.
     */
    public native void release();

    private native void native_setup();

    private static native void native_init();

    private native final void native_finalize();

    @Override
    protected void finalize() throws Throwable {
        try {
            native_finalize();
        } finally {
            super.finalize();
        }
    }

    public static final int MODE_GET_METADATA_ONLY = 0x01;
    public static final int MODE_CAPTURE_FRAME_ONLY = 0x02;

    /*
     * Do not change these values without updating their counterparts in
     * include/media/mediametadataretriever.h!
     */
    public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
    public static final int METADATA_KEY_ALBUM = 1;
    public static final int METADATA_KEY_ARTIST = 2;
    public static final int METADATA_KEY_AUTHOR = 3;
    public static final int METADATA_KEY_COMPOSER = 4;
    public static final int METADATA_KEY_DATE = 5;
    public static final int METADATA_KEY_GENRE = 6;
    public static final int METADATA_KEY_TITLE = 7;
    public static final int METADATA_KEY_YEAR = 8;
    public static final int METADATA_KEY_DURATION = 9;
    public static final int METADATA_KEY_NUM_TRACKS = 10;
    public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11;
    public static final int METADATA_KEY_CODEC = 12;
    public static final int METADATA_KEY_RATING = 13;
    public static final int METADATA_KEY_COMMENT = 14;
    public static final int METADATA_KEY_COPYRIGHT = 15;
    public static final int METADATA_KEY_BIT_RATE = 16;
    public static final int METADATA_KEY_FRAME_RATE = 17;
    public static final int METADATA_KEY_VIDEO_FORMAT = 18;
    public static final int METADATA_KEY_VIDEO_HEIGHT = 19;
    public static final int METADATA_KEY_VIDEO_WIDTH = 20;
    public static final int METADATA_KEY_WRITER = 21;
    public static final int METADATA_KEY_MIMETYPE = 22;
    public static final int METADATA_KEY_DISCNUMBER = 23;
    public static final int METADATA_KEY_ALBUMARTIST = 24;
    // Add more here...
}

回答by Marc Climent

Android 1.5 and 1.6 do not offer this thumbnails, but 2.0 does, as seen on the official release notes:

Android 1.5 和 1.6 不提供此缩略图,但 2.0 提供,如官方发行说明所示

Media

  • MediaScanner now generates thumbnails for all images when they are inserted into MediaStore.
  • New Thumbnail API for retrieving image and video thumbnails on demand.

媒体

  • MediaScanner 现在为所有图像插入 MediaStore 时生成缩略图。
  • 用于按需检索图像和视频缩略图的新缩略图 API。

回答by karan brahmaxatriya

Try this it's working for me

试试这个它对我有用

RequestOptions requestOptions = new RequestOptions();
 Glide.with(getContext())
      .load("video_url")
      .apply(requestOptions)
      .thumbnail(Glide.with(getContext()).load("video_url"))
      .into("yourimageview");

回答by Mudassir Khan

I am answering this question late but hope it will help the other candidate facing same problem.

我很晚才回答这个问题,但希望它能帮助面临同样问题的其他候选人。

I have used two methods to load thumbnail for videos list the first was

我使用了两种方法来加载视频列表的缩略图,第一种是

    Bitmap bmThumbnail;
    bmThumbnail = ThumbnailUtils.createVideoThumbnail(FILE_PATH
                    + videoList.get(position),
            MediaStore.Video.Thumbnails.MINI_KIND);

    if (bmThumbnail != null) {
        Log.d("VideoAdapter","video thumbnail found");
        holder.imgVideo.setImageBitmap(bmThumbnail);
    } else {
        Log.d("VideoAdapter","video thumbnail not found");
    }

its look good but there was a problem with this solution because when i scroll video list it will freeze some time due to its large processing.

它看起来不错,但此解决方案存在问题,因为当我滚动视频列表时,由于处理量大,它会冻结一段时间。

so after this i found another solution which works perfectly by using Glide Library.

所以在此之后,我找到了另一个使用 Glide 库完美运行的解决方案。

 Glide
            .with( mContext )
            .load( Uri.fromFile( new File( FILE_PATH+videoList.get(position) ) ) )
            .into( holder.imgVideo );

I recommended the later solution for showing thumbnail with video list . thanks

我推荐了后来的解决方案,用于显示带有视频列表的缩略图。谢谢

回答by Chirag

This is code for live Video thumbnail.

这是实时视频缩略图的代码。

public class LoadVideoThumbnail extends AsyncTask<Object, Object, Bitmap>{

        @Override
        protected Bitmap doInBackground(Object... params) {try {

            String mMediaPath = "http://commonsware.com/misc/test2.3gp";
            Log.e("TEST Chirag","<< thumbnail doInBackground"+ mMediaPath);
            FileOutputStream out;
            File land=new File(Environment.getExternalStorageDirectory().getAbsoluteFile()
                            +"/portland.jpg");

                Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(mMediaPath, MediaStore.Video.Thumbnails.MICRO_KIND);
                        ByteArrayOutputStream stream = new ByteArrayOutputStream();
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                        byte[] byteArray = stream.toByteArray();

                        out=new  FileOutputStream(land.getPath());
                        out.write(byteArray);
                        out.close();
                 return bitmap;

            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        return null;
            }
        @Override
        protected void onPostExecute(Bitmap result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            if(result != null){
                 ((ImageView)findViewById(R.id.imageView1)).setImageBitmap(result);
            }
            Log.e("TEST Chirag","====> End");
        }

    }