【问题标题】:Android - Display a video thumbnail from a URLAndroid - 显示来自 URL 的视频缩略图
【发布时间】:2014-06-24 16:27:20
【问题描述】:

我需要将基于 URL 的视频缩略图显示到我的 ListView 项目的 ImageView 视图子项中,我找到了这个 post 但没有工作。

结果

代码

        thumb_image.setImageBitmap(new LoadVideoThumbnail().execute(URLs.videos +"/"+videos.get(position).getId()+".mp4").get());

异步任务

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

        @Override
        protected Bitmap doInBackground(String... objectURL) {
            //return ThumbnailUtils.createVideoThumbnail(objectURL[0], Thumbnails.MINI_KIND);
            return ThumbnailUtils.extractThumbnail(ThumbnailUtils.createVideoThumbnail(objectURL[0], Thumbnails.MINI_KIND), 100, 100);
        }

        @Override
        protected void onPostExecute(Bitmap result){
             //img.setImageBitmap(result);
        }

    }

【问题讨论】:

  • 从提供视频的服务器获取缩略图。否则,我怀疑您需要下载整个视频才能获得缩略图。
  • 我只是在评论,因为这并不是真正的答案,但我们在工作中使用毕加索。 square.github.io/picasso 开源,易于使用,在 android 上运行良好。
  • 然后使用 Picasso 或 Ion 或其他任何东西从服务器下载缩略图。
  • Glide 加载本地视频缩略图@hasnain

标签: android url


【解决方案1】:

无需下载视频,您可以使用以下方法生成视频缩略图:

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(1, MediaMetadataRetriever.OPTION_CLOSEST);
    }
    catch (Exception e)
    {
        e.printStackTrace();
        throw new Throwable("Exception in retriveVideoFrameFromVideo(String videoPath)"+ e.getMessage());
    }
    finally
    {
        if (mediaMetadataRetriever != null)
        {
            mediaMetadataRetriever.release();
        }
    }
    return bitmap;
}

【讨论】:

  • 我也用同样的方法创建缩略图,在eclipse上运行正常,但是在android studio上运行时没有发现class def错误
  • @KishuDroid,我如何在 ImageView 上附加该代码以加载缩略图,我对该代码感到困惑,请帮助我
  • 我在某些设备上出现系统错误
  • @franklinexpress 请提供有关您的错误的更多信息。
  • 这在使用内部回收站视图时不实用,需要延迟
【解决方案2】:

使用 glide,我使用的是 Glide 4.8.0

  long thumb = getLayoutPosition()*1000;
  RequestOptions options = new RequestOptions().frame(thumb);
  Glide.with(getBaseContext()).load(url).apply(options).into(mThumb);

【讨论】:

  • 比 MediaMetadataRetriever 解决方案好得多。
  • 在哪里声明 getLayoutPosition() 方法? @WallaceRoberto
  • 比 MediaMetadataRetriever 解决方案好得多。
【解决方案3】:

@CommonsWare,

并非每个视频都在服务器中存储单独的缩略图。但我们有一些图书馆

使用 jniLibs 的 fmmr.jar

直接在 10 秒内提供来自服务器 url 的缩略图。

缩略图的sample code

FFmpegMediaMetadataRetriever fmmr = new FFmpegMediaMetadataRetriever();
        try {
            fmmr.setDataSource(videoPath);

            Bitmap b = fmmr.getFrameAtTime();

            if (b != null) {
                Bitmap b2 = fmmr.getFrameAtTime(4000000, FFmpegMediaMetadataRetriever.OPTION_CLOSEST_SYNC);
                if (b2 != null) {
                    b = b2;
                }
            }

            if (b != null) {
                Log.i("Thumbnail", "Extracted frame");
                return b;
            } else {
                Log.e("Thumbnail", "Failed to extract frame");
            }
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        } finally {
            fmmr.release();
        }

【讨论】:

  • 这个库太大了,因为是原生写的,大约25MB!
【解决方案4】:

你好试试这个 sn-p 在我的情况下工作

        Uri videoUri = data.getData();
        String selectedPathVideo="";
        selectedPathVideo = ImageFilePath.getPath(getApplicationContext(), videoUri);
        Log.i("Image File Path", ""+selectedPathVideo);

        try {
            Bitmap thumb = ThumbnailUtils.createVideoThumbnail(selectedPathVideo, MediaStore.Video.Thumbnails.MICRO_KIND);


            imgFarmerVideo.setImageBitmap(thumb);

        } catch (Exception e) {
            e.printStackTrace();
        }

支持类

public class ImageFilePath {
    /**
     * Method for return file path of Gallery image
     *
     * @param context
     * @param uri
     * @return path of the selected image file from gallery
     */
    public static String getPath(final Context context, final Uri uri)
    {

        //check here to KITKAT or new version
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {

            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] {
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}

【讨论】:

    【解决方案5】:

    使用android ThumbnailUtils 类

      public static Bitmap getThumblineImage(String videoPath) {
        return ThumbnailUtils.createVideoThumbnail(videoPath, MINI_KIND);
      }
    

    【讨论】:

    • 导入静态android.provider.MediaStore.Video.Thumbnails.MINI_KIND;
    【解决方案6】:

    以下是从视频路径获取缩略图的 Kotlin 代码。

    fun retrieveVideoFrameFromVideo(videoPath: String?): Bitmap? {
        var bitmap: Bitmap? = null
        var mediaMetadataRetriever: MediaMetadataRetriever? = null
        try {
            mediaMetadataRetriever = MediaMetadataRetriever()
            mediaMetadataRetriever.setDataSource(videoPath, HashMap<String, String>())
            bitmap = mediaMetadataRetriever.frameAtTime
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            mediaMetadataRetriever?.release()
        }
        return bitmap
    }
    

    调用方法如下。

    val bm = retrieveVideoFrameFromVideo(model.FilePath)
    imgPreview.setImageBitmap(bm)
    

    【讨论】:

    • 我收到一个错误:getFrameAtTime: videoFrame is a NULL pointer
    【解决方案7】:

    您可以使用 Glide 加载视频网址的缩略图。

      Glide.with(binding.getRoot().getContext())
                            .load("https://www.example.sample-mp4-file.mp4")
                            .diskCacheStrategy(DiskCacheStrategy.ALL)
                            .into(binding.ivThumbnail);
    

    【讨论】:

      【解决方案8】:

      要显示视频的位图预览,只需设置 VideoView 的视频路径,让流缓冲即可。

      例如:

      videoView.setVideoPath("/sdcard/myawesomevideo.mp4");
      

      几秒钟后,您将看到视频的第一帧。

      【讨论】:

      • setVideoPath 也接受 HTTP URL!只需将我的答案中的路径替换为真实的 HTTP URL。
      • 对不起..但我也希望将其显示到 ImageView 中
      • 当 VideoView 本身为您提供预览时,为什么您需要在 ImageView 中显示预览?
      • 所以你建议我将 videoview 与 listview 一起使用?
      • 对不起,我不明白。我从没谈过 WebView:WebViews 用于 HTML 内容,而不是视频内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      • 2015-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-20
      • 1970-01-01
      相关资源
      最近更新 更多