【问题标题】:android capture video frameandroid捕获视频帧
【发布时间】:2011-03-17 09:59:58
【问题描述】:

我需要获取视频文件的帧(它可能在 sdcard、缓存目录或应用程序目录上)。我在我的应用程序中有包 android.media,在里面我有类 MediaMetadataRetriever。要将第一帧放入位图中,我使用代码:

public static Bitmap getVideoFrame(Context context, Uri videoUri) {
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    try {
        retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
        retriever.setDataSource(context, videoUri);
        return retriever.captureFrame();
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException();
    } catch (RuntimeException ex) {
        throw new RuntimeException();
    } finally {
        retriever.release();
    }
}

但这不起作用。当我设置数据源时,它会引发异常(java.lang.RuntimeException: setDataSource failed: status = 0x80000000)。你知道如何让这段代码工作吗?或者您有没有使用 ffmpeg 或其他外部库的类似(简单)解决方案? videoUri 是一个有效的 uri(媒体播放器可以从该 URI 播放视频)

【问题讨论】:

  • 你的问题可以提供一个样本吗,我为这种样本尝试了很多,最后不得不问你。

标签: android video frame capture


【解决方案1】:

我使用了这段代码,这对我有用。你可以试试这个。

if (Build.VERSION.SDK_INT >= 14) {
                ffmpegMetaDataRetriever.setDataSource(
                        videoFile.getAbsolutePath(),
                        new HashMap<String, String>());
            } else {
                ffmpegMetaDataRetriever.setDataSource(videoFile
                        .getAbsolutePath());
            }

【讨论】:

    【解决方案2】:

    以下对我有用:

    public static Bitmap getVideoFrame(FileDescriptor FD) {
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            try {
                retriever.setDataSource(FD);
                return retriever.getFrameAtTime();
            } catch (IllegalArgumentException ex) {
                ex.printStackTrace();
            } catch (RuntimeException ex) {
                ex.printStackTrace();
            } finally {
                try {
                    retriever.release();
                } catch (RuntimeException ex) {
                }
            }
            return null;
        }
    

    如果您使用路径而不是文件描述符,也可以使用。

    【讨论】:

    • 什么值应该作为 FileDescripter 参数传递。 Real 认为,在我的应用程序中,只有视频 url,并且想要获取该视频文件的帧列表...
    • 要获取 FileDescriptor 对象,请执行 openFileInput(myVideoFileName).getFD()。为此,视频必须位于您的应用程序私有目录中。您还可以更改为 public static Bitmap getVideoFrame(String FD) 并传递您的视频路径。
    • 一秒钟内,视频有 25 到 30 帧。你能得到所有的帧。因为通过这种技术,我每次都会得到 3-4 个重复的帧。而且有些帧丢失了。
    • @Rab Ross 请提供详细代码。你是怎么做到的。我无法让它工作。扩展必须是什么,反之亦然
    • @Nepster 这是不久前的事,我无法再访问详细代码了。我很抱歉。
    【解决方案3】:

    试试这个,我已经用过了,它的工作原理

    public static Bitmap getVideoFrame(Context context, Uri uri) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setDataSource(uri.toString(),new HashMap<String, String>());
            return retriever.getFrameAtTime();
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        } catch (RuntimeException ex) {
            ex.printStackTrace();
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException ex) {
            }
        }
        return null;
    }
    

    你可以直接传递你的 url 来代替 uri。

    【讨论】:

    【解决方案4】:

    我的申请也有同样的错误。我在这个网站上看到了

    这是一种非官方的方式 它只适用于纸杯蛋糕(和 也许是以后的版本)。安卓团队 不保证 libmedia_jni.so,其中的java文件 用途,将被包括或拥有 未来版本中的相同界面。

    http://osdir.com/ml/AndroidDevelopers/2009-06/msg02442.html

    我已将手机更新为 GingerBread,但它不再工作了。

    【讨论】:

      【解决方案5】:

      Uri 不是很具体。有时它们指的是捆绑中的某些东西。它们通常需要转换为绝对路径形式。您使用 Uri 的另一个实例,它可能足够聪明,可以检查它是哪种 Uri。您展示的这个案例看起来并不难。

      【讨论】:

        【解决方案6】:

        我在使用 ThumbnailUtilshttp://developer.android.com/reference/android/media/ThumbnailUtils.html
        时遇到了同样的错误 它在后台使用 MediaMetadataRetriever,大​​多数情况下,您可以使用此方法毫无问题地向其发送文件路径:

        public static Bitmap createVideoThumbnail (String filePath, int kind)  
        

        但是,在 Android 4.0.4 上,我不断收到 @gabi 看到的相同错误。改用文件描述符解决了这个问题,并且仍然适用于非 4.0.4 设备。我实际上最终继承了 ThumbnailUtils。这是我的子类方法:

         public static Bitmap createVideoThumbnail(FileDescriptor fDescriptor, int kind) 
         {
            Bitmap bitmap = null;
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            try {
                retriever.setDataSource(fDescriptor);
                bitmap = retriever.getFrameAtTime(-1);
            } 
            catch (IllegalArgumentException ex) {
                // Assume this is a corrupt video file
                Log.e(LOG_TAG, "Failed to create video thumbnail for file description: " + fDescriptor.toString());
            }
            catch (RuntimeException ex) {
                // Assume this is a corrupt video file.
                Log.e(LOG_TAG, "Failed to create video thumbnail for file description: " + fDescriptor.toString());
            } finally {
                try {
                    retriever.release();
                } catch (RuntimeException ex) {
                    // Ignore failures while cleaning up.
                }
            }
        
            if (bitmap == null) return null;
        
            if (kind == Images.Thumbnails.MINI_KIND) {
                // Scale down the bitmap if it's too large.
                int width = bitmap.getWidth();
                int height = bitmap.getHeight();
                int max = Math.max(width, height);
                if (max > 512) {
                    float scale = 512f / max;
                    int w = Math.round(scale * width);
                    int h = Math.round(scale * height);
                    bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
                }
            } else if (kind == Images.Thumbnails.MICRO_KIND) {
                bitmap = extractThumbnail(bitmap,
                        TARGET_SIZE_MICRO_THUMBNAIL,
                        TARGET_SIZE_MICRO_THUMBNAIL,
                        OPTIONS_RECYCLE_INPUT);
            }
            return bitmap;
        }
        

        【讨论】:

          【解决方案7】:

          File 不存在时也会引发异常。所以在打电话给setDataSource()之前你最好检查一下new File(url).exists()

          【讨论】:

            【解决方案8】:

            那么有没有一种特定的方法可以从视频中获取帧

             File sdcard = Environment.getExternalStorageDirectory();
             File file = new File(sdcard, "myvideo.mp4");
            

            【讨论】:

            • 它给出了错误......现在它的工作......我想我的 Eclipse 编辑器有问题。还是谢谢
            • 我的评论是问你“这 2 行代码是你的答案还是你的问题的问题?”
            • 这是一个问题......上面的代码最初没有工作......但它现在可以正常工作了
            • @PareshMayani,如何获取视频文件的帧列表以显示在画廊视图中,请查看my question
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-30
            • 2012-01-24
            • 1970-01-01
            • 2011-12-29
            • 1970-01-01
            • 2011-04-13
            相关资源
            最近更新 更多