如何显示视频路径中的视频缩略图?
how can I show a video thumbnail from a video path?
我想在存储中的视频路径中的 ImageView 中显示视频缩略图。是否有采用视频路径和 returns 缩略图位图的函数?我通过此代码获取视频路径:
public ArrayList<String> getAllMedia() {
HashSet<String> videoItemHashSet = new HashSet<>();
String[] projection = {MediaStore.Video.VideoColumns.DATA, MediaStore.Video.Media.DISPLAY_NAME};
Cursor cursor = getContext().getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
try {
cursor.moveToFirst();
do {
videoItemHashSet.add((cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))));
} while(cursor.moveToNext());
cursor.close();
} catch(Exception e) {
e.printStackTrace();
}
ArrayList<String> downloadedList = new ArrayList<>(videoItemHashSet);
return downloadedList;
}
显示本地存储的缩略图
String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
GlideApp
.with(context)
.asBitmap()
.load(Uri.fromFile(new File(filePath)))
.into(imageViewGifAsBitmap);
这是创建缩略图的默认方式。
迷你款
Bitmap thumb;
//MINI_KIND, size: 512 x 384 thumbnail
thumb = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
img_tumbnail.setImageBitmap(thumb);
微型类
Bitmap thumb;
//MICRO_KIND, size: 96 x 96 thumbnail
thumb= ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MICRO_KIND);
img_tumbnail.setImageBitmap(thumb);
此外,您可以将 Glide 用于 Url 以及设备的视频路径。
Glide.with(context).with(this)
.asBitmap()
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
此外,您可以使用 .override(50,50)
和 Glide 来调整缩略图的大小。
我有第三种方法来设置 image/video 的缩略图。
希望对你有帮助。
1) ThumbnailUtils --> 有效但缓慢
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(thumbPath, MediaStore.Video.Thumbnails.MINI_KIND);
holder.ivThumb.setImageBitmap(thumb);
2) FFmpegMediaMetadataRetriever --> 非常有效但很慢
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
try {
retriever.setDataSource(thumbPath);
thumb.setImageBitmap(retriever.getFrameAtTime(0));
} catch (Exception ex) {
// Assume this is a corrupt file
}
3) Glide --> 有效且快速
RequestOptions options = new RequestOptions()
.centerCrop()
.placeholder(android.R.drawable.stat_notify_error)
.error(android.R.drawable.stat_notify_error);
Glide.with(context)
.load(thumPath)
.apply(options)
.into(thumb);
您可以使用 ThumbnailUtils
加载 3 种格式的视频缩略图:
- MINI_KIND :适合媒体详细信息查看
- FULL_SCREEN_KIND :适合 header
- MICRO_KIND : 适合 recycleView
例如:
holder.videoThumb.setImageBitmap(ThumbnailUtils.createVideoThumbnail(getItem(position).videoURL, MediaStore.Images.Thumbnails.MICRO_KIND))
最大的缺点是 ThumbnailUtils 在 UI 线程 上运行,因此如果您尝试在 recycleView 中使用此方法,那么它会让您的应用跳帧。您的 RecycleView 将出现滞后滚动,如果您的项目超过 7 个,那么您的应用将开始抛出 ANR.
这意味着您需要创建 AsyncTask 或线程,这可能会再次导致内存泄漏。
结论; Glide 在加载视频缩略图方面表现更好。
这里 DiskCacheStrategy.RESULT
是对我有用的重要参数,可以在回收视图中提供平滑快速的滚动。
Glide.with(context).load(getItem(position).videoURL)
.asBitmap()
.placeholder(R.drawable.app_icon)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.into(holder.videoThumb)
如果没有 FileDescriptorBitmapDecoder
,某些设备无法正常工作
所以我在 FileDescriptorBitmapDecoder 中使用了以下代码
public static void loadLocalVideoThumbanail(Context context, String path, final ImageView imageView) {
try {
if (path == null || path.isEmpty())
return;
BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
int microSecond = 1000000;// 1st second as an example
VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
Glide.with(context).load(path).asBitmap().thumbnail(0.6f)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.dontAnimate()
.videoDecoder(fileDescriptorBitmapDecoder)
.override(200,200)
.into(imageView);
} catch (Exception e) {
MyLog.e(TAG, "LoadImage: ", e);
}
}
如果有人正在寻找 Kotlin 版本。你可以试试这个扩展功能。
它正在使用 coil.
/**
* https://github.com/coil-kt/coil/issues/413
*/
fun ImageView.setThumbnail(uri: Uri, frameMillis: Long = 2000) {
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(VideoFrameFileFetcher(context))
add(VideoFrameUriFetcher(context))
}.build()
val request = ImageRequest.Builder(context)
.data(uri)
.videoFrameMillis(frameMillis)
.target(this)
.fetcher(VideoFrameUriFetcher(context))
.build()
findViewTreeLifecycleOwner()?.lifecycleScope?.launch(Dispatchers.Main) {
imageLoader.execute(request)
}
}
我想在存储中的视频路径中的 ImageView 中显示视频缩略图。是否有采用视频路径和 returns 缩略图位图的函数?我通过此代码获取视频路径:
public ArrayList<String> getAllMedia() {
HashSet<String> videoItemHashSet = new HashSet<>();
String[] projection = {MediaStore.Video.VideoColumns.DATA, MediaStore.Video.Media.DISPLAY_NAME};
Cursor cursor = getContext().getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
try {
cursor.moveToFirst();
do {
videoItemHashSet.add((cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))));
} while(cursor.moveToNext());
cursor.close();
} catch(Exception e) {
e.printStackTrace();
}
ArrayList<String> downloadedList = new ArrayList<>(videoItemHashSet);
return downloadedList;
}
显示本地存储的缩略图
String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
GlideApp
.with(context)
.asBitmap()
.load(Uri.fromFile(new File(filePath)))
.into(imageViewGifAsBitmap);
这是创建缩略图的默认方式。
迷你款
Bitmap thumb;
//MINI_KIND, size: 512 x 384 thumbnail
thumb = ThumbnailUtils.createVideoThumbnail(filePath, MediaStore.Video.Thumbnails.MINI_KIND);
img_tumbnail.setImageBitmap(thumb);
微型类
Bitmap thumb;
//MICRO_KIND, size: 96 x 96 thumbnail
thumb= ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MICRO_KIND);
img_tumbnail.setImageBitmap(thumb);
此外,您可以将 Glide 用于 Url 以及设备的视频路径。
Glide.with(context).with(this)
.asBitmap()
.load(videoFilePath) // or URI/path
.into(imgView); //imageview to set thumbnail to
此外,您可以使用 .override(50,50)
和 Glide 来调整缩略图的大小。
我有第三种方法来设置 image/video 的缩略图。 希望对你有帮助。
1) ThumbnailUtils --> 有效但缓慢
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(thumbPath, MediaStore.Video.Thumbnails.MINI_KIND);
holder.ivThumb.setImageBitmap(thumb);
2) FFmpegMediaMetadataRetriever --> 非常有效但很慢
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
try {
retriever.setDataSource(thumbPath);
thumb.setImageBitmap(retriever.getFrameAtTime(0));
} catch (Exception ex) {
// Assume this is a corrupt file
}
3) Glide --> 有效且快速
RequestOptions options = new RequestOptions()
.centerCrop()
.placeholder(android.R.drawable.stat_notify_error)
.error(android.R.drawable.stat_notify_error);
Glide.with(context)
.load(thumPath)
.apply(options)
.into(thumb);
您可以使用 ThumbnailUtils
加载 3 种格式的视频缩略图:
- MINI_KIND :适合媒体详细信息查看
- FULL_SCREEN_KIND :适合 header
- MICRO_KIND : 适合 recycleView
例如:
holder.videoThumb.setImageBitmap(ThumbnailUtils.createVideoThumbnail(getItem(position).videoURL, MediaStore.Images.Thumbnails.MICRO_KIND))
最大的缺点是 ThumbnailUtils 在 UI 线程 上运行,因此如果您尝试在 recycleView 中使用此方法,那么它会让您的应用跳帧。您的 RecycleView 将出现滞后滚动,如果您的项目超过 7 个,那么您的应用将开始抛出 ANR.
这意味着您需要创建 AsyncTask 或线程,这可能会再次导致内存泄漏。
结论; Glide 在加载视频缩略图方面表现更好。
这里 DiskCacheStrategy.RESULT
是对我有用的重要参数,可以在回收视图中提供平滑快速的滚动。
Glide.with(context).load(getItem(position).videoURL)
.asBitmap()
.placeholder(R.drawable.app_icon)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.into(holder.videoThumb)
如果没有 FileDescriptorBitmapDecoder
,某些设备无法正常工作所以我在 FileDescriptorBitmapDecoder 中使用了以下代码
public static void loadLocalVideoThumbanail(Context context, String path, final ImageView imageView) {
try {
if (path == null || path.isEmpty())
return;
BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
int microSecond = 1000000;// 1st second as an example
VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
Glide.with(context).load(path).asBitmap().thumbnail(0.6f)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.dontAnimate()
.videoDecoder(fileDescriptorBitmapDecoder)
.override(200,200)
.into(imageView);
} catch (Exception e) {
MyLog.e(TAG, "LoadImage: ", e);
}
}
如果有人正在寻找 Kotlin 版本。你可以试试这个扩展功能。 它正在使用 coil.
/**
* https://github.com/coil-kt/coil/issues/413
*/
fun ImageView.setThumbnail(uri: Uri, frameMillis: Long = 2000) {
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(VideoFrameFileFetcher(context))
add(VideoFrameUriFetcher(context))
}.build()
val request = ImageRequest.Builder(context)
.data(uri)
.videoFrameMillis(frameMillis)
.target(this)
.fetcher(VideoFrameUriFetcher(context))
.build()
findViewTreeLifecycleOwner()?.lifecycleScope?.launch(Dispatchers.Main) {
imageLoader.execute(request)
}
}