繁体   English   中英

android捕获视频帧

[英]android capture video frame

我需要获取一个视频文件的框架(它可能在sdcard,cache dir或app dir上)。 我在我的应用程序中有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的视频)

以下适用于我:

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

如果您使用路径而不是filedescriptor也可以。

试试这个,我已经习惯了它的工作

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

代替uri,您可以直接传递您的网址。

我使用ThumbnailUtils类得到了同样的错误http://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;
}

File不存在时也会抛出异常。 所以在调用setDataSource()之前,最好检查一下是否有new File(url).exists()

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

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

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

这是一种非官方的做法,它只适用于蛋糕(也许是后来的版本)。 Android团队不保证java文件使用的libmedia_jni.so将在未来版本中包含或具有相同的界面。

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

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

Uri不是很具体。 有时它们会引用捆绑中的某些东西。 它们通常需要转换为绝对路径形式。 在你使用Uri的另一个例子中,它可能非常聪明,可以检查它是什么类型的Uri。 您显示的这种情况似乎看起来不是很难。

那么是否有一种特定的方法来从视频中获取帧

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM