Я создал приложение для записи видео с диалогом библиотеки. В диалоговом окне библиотеки отображается список записанных видео, каждый элемент которого состоит из значка, названия видео, тегов и информации о местоположении следующим образом:
Кто-нибудь знает, можно ли заменить иконки на миниатюры видео (покадровый превью)?
Благодарность!
Ответы:
Если вы используете 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);
источник
id
?если вы не используете или не можете пройти через курсор, и если у вас есть только пути или объекты File, вы можете использовать общедоступное статическое Bitmap уровня API 8 (2.2), начиная с уровня API 8 (2.2) createVideoThumbnail (String filePath, int kind)
Документация Android
Следующий код работает отлично:
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
источник
t have my video ID. For better quality use
MediaStore.Video.Thumbnails.FULL_SCREEN_KIND`Используя класс:
import android.provider.MediaStore.Video.Thumbnails;
Из видео мы можем получить два размера миниатюр предварительного просмотра:
Thumbnails.MICRO_KIND
для 96 x 96Thumbnails.MINI_KIND
для 512 x 384 пикселейЭто пример кода:
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);
источник
В настоящее время я использую следующий код:
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
Но я нашел лучшее решение с библиотекой Glide со следующим кодом (он также кеширует ваше изображение и имеет лучшую производительность, чем предыдущий подход)
Glide.with(context) .load(uri) .placeholder(R.drawable.ic_video_place_holder) .into(imageView);
источник
Я действительно предлагаю вам использовать библиотеку Glide . Это один из наиболее эффективных способов создания и отображения эскизов видео для локального видеофайла.
Просто добавьте эту строку в свой файл gradle:
compile 'com.github.bumptech.glide:glide:3.7.0'
И станет так просто:
String filePath = "/storage/emulated/0/Pictures/example_video.mp4"; Glide .with( context ) .load( Uri.fromFile( new File( filePath ) ) ) .into( imageViewGifAsBitmap );
Вы можете найти дополнительную информацию здесь: https://futurestud.io/blog/glide-displaying-gifs-and-videos
Ура!
источник
Попробуй, это работает для меня
RequestOptions requestOptions = new RequestOptions(); Glide.with(getContext()) .load("video_url") .apply(requestOptions) .thumbnail(Glide.with(getContext()).load("video_url")) .into("yourimageview");
источник
Это решение будет работать с любой версией Android. Доказано, что он работает в версиях 1.5 и 2.2. Это не еще одно решение «Это для Android 2.0+». Я нашел это на странице коллекции доски сообщений электронной почты и не могу найти исходную ссылку. Вся заслуга принадлежит оригинальному плакату.
В своем приложении вы можете использовать это, позвонив:
Bitmap bm = getVideoFrame(VideoStringUri);
Где-то в его собственной функции (вне 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; }
В папке 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... }
источник
MediaMetadataRetriever
поддерживается с уровня API 10Android 1.5 и 1.6 не предлагают эти эскизы, но 2.0, как видно из официальных примечаний к выпуску :
источник
Я отвечаю на этот вопрос поздно, но надеюсь, что это поможет другому кандидату, столкнувшемуся с той же проблемой.
Я использовал два метода для загрузки миниатюр для списка видео, первым из которых был
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"); }
он выглядит хорошо, но с этим решением возникла проблема, потому что, когда я прокручиваю список видео, он на некоторое время зависает из-за большой обработки.
поэтому после этого я нашел другое решение, которое отлично работает с использованием библиотеки Glide.
Glide .with( mContext ) .load( Uri.fromFile( new File( FILE_PATH+videoList.get(position) ) ) ) .into( holder.imgVideo );
Я рекомендовал более позднее решение для отображения эскизов со списком видео. Благодарность
источник
Это код для эскиза живого видео.
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"); } }
источник
Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(mMediaPath, MediaStore.Video.Thumbnails.MICRO_KIND);
Обратите внимание, что все параметры установлены