9

我正在尝试从视频中提取所有帧。
通过以下代码,我想获取视频的前 30 帧,但我只得到了第一帧 30 次。

private ArrayList<Bitmap> getFrames(String path) {
    try {
        ArrayList<Bitmap> bArray = new ArrayList<Bitmap>();
        bArray.clear();
        MediaMetadataRetriever mRetriever = new MediaMetadataRetriever();
        mRetriever.setDataSource("/sdcard/myvideo.mp4");                    

        for (int i = 0; i < 30; i++) {
            bArray.add(mRetriever.getFrameAtTime(1000*i, 
                       MediaMetadataRetriever.OPTION_CLOSEST_SYNC));
        }
        return bArray;
    } catch (Exception e) { return null; }
}

现在,如何从视频中获取所有帧?

4

4 回答 4

3

Android SDK 中的视频支持有限,只能对关键帧进行 H264 编码视频的帧提取。为了提取任意帧,您需要使用像FFmpegMediaMetadataRetriever这样的库,它使用本机代码从视频中提取数据。它非常快,带有预编译的二进制文件(用于 ARM 和 x86),因此您无需深入研究 C++ 和 makefile,在 Apache 2.0 下获得许可,并带有一个演示 Android 应用程序。

还有一个纯 Java 库,JCodec ,但速度较慢,当我去年使用它时,提取帧的颜色会失真。

于 2015-02-07T10:27:20.773 回答
3

你必须将路径传递给这个方法......完美的工作代码!希望有帮助

gradle - 实现 'com.github.wseemann:FFmpegMediaMetadataRetriever-core:1.0.15'

public void VideoToGif(String uri) {
    Uri videoFileUri = Uri.parse(uri);

    FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
    retriever.setDataSource(uri);
    List<Bitmap> rev = new ArrayList<Bitmap>();
    MediaPlayer mp = MediaPlayer.create(GitToImage.this, videoFileUri);
    int millis = mp.getDuration();
    System.out.println("starting point");
    for (int i = 100000; i <=millis * 1000; i += 100000*2) {
        Bitmap bitmap = retriever.getFrameAtTime(i, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
        rev.add(bitmap);
    }

    GiftoImage((ArrayList) rev);
}
于 2021-03-19T07:47:38.693 回答
1

getFrameAt 以毫秒为单位获取数据,但您在 for 循环中增加了 0.001 毫秒。

    for(int i=1000000;i<millis*1000;i+=1000000) // for incrementing 1s use 1000
    {
       bArray.add(mRetriever.getFrameAtTime(i, 
                       MediaMetadataRetriever.OPTION_CLOSEST_SYNC));
    }

像上面一样改变它。以上是创建您想要的示例。我也在这里回答了

于 2015-02-07T12:38:57.783 回答
0

从 Android 9.0(API 级别 28)开始,MediaMetadataRetriever有一个getFrameAtIndex (int frameIndex)方法,它接受您想要的帧的从零开始的索引并返回一个位图。

https://developer.android.com/reference/android/media/MediaMetadataRetriever.html#getFrameAtIndex(int)

于 2019-03-20T08:41:16.363 回答