【问题标题】:how can I show a video thumbnail from a video path?如何显示视频路径中的视频缩略图?
【发布时间】:2021-07-14 14:13:34
【问题描述】:

我想在 ImageView 中显示来自存储上的视频路径的视频缩略图。是否有一个函数可以获取视频路径并返回缩略图的位图?我通过此代码获取视频路径:

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;
}

【问题讨论】:

标签: android file imageview android-bitmap video-thumbnails


【解决方案1】:

这是创建缩略图的默认方式。

迷你型

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 以及 Device 的 Video path。

Glide.with(context).with(this)
                    .asBitmap()
                    .load(videoFilePath) // or URI/path
                    .into(imgView); //imageview to set thumbnail to

另外,您可以使用.override(50,50)Glide 来调整缩略图的大小。

【讨论】:

  • 我测试了你的代码但没有用。当我尝试使用 glide 加载图片时,android studio 出现错误:错误:任务':app:transformDexArchiveWithExternalLibsDexMergerForDebug'的执行失败。 > java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: 无法合并 dex
  • enable multidexing ,这是不同的问题,显示什么错误?
  • 这是错误:错误:任务':app:transformDexArchiveWithExternalLibsDexMergerForDebug'的执行失败。 > java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: 无法合并 dex –
  • 你是否在 Gradle 中启用了multidexing,如果没有,则在 app/build.gradle 中使用android { defaultConfig { multiDexEnabled true } }
【解决方案2】:

使用Glide lib

显示本地存储的缩略图

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

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

【讨论】:

  • 我测试了你的代码但没有用。当我尝试使用 glide 加载图片时,android studio 出现错误:错误:任务':app:transformDexArchiveWithExternalLibsDexMergerForDebug'的执行失败。 > java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: 无法合并 dex
  • 这个错误与multidex有关。为您的项目启用 multidex 并尝试
【解决方案3】:

您可以使用ThumbnailUtils 加载3 种格式的视频缩略图:

  • MINI_KIND:适合媒体详细信息查看
  • FULL_SCREEN_KIND:适合标题
  • 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)

【讨论】:

    【解决方案4】:

    我有第三种方法来设置图像/视频的缩略图。 希望对你有帮助。

    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);
    

    【讨论】:

      【解决方案5】:

      如果有人正在寻找 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)
          }
      }
      

      【讨论】:

        【解决方案6】:

        如果没有 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);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-03-25
          • 1970-01-01
          • 1970-01-01
          • 2012-06-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-24
          • 2011-07-14
          相关资源
          最近更新 更多