我正在尝试从视频中提取所有帧 通过以下代码我想获取视频的前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; }
}
现在,我如何从视频中获取所有帧?
答案 0 :(得分:2)
Android SDK中的视频支持受到限制,H264编码视频的帧提取仅适用于关键帧。为了提取任意帧,您需要使用像FFmpegMediaMetadataRetriever这样的库,它使用本机代码从视频中提取数据。它非常快,带有预编译的二进制文件(适用于ARM和x86),因此您不需要深入研究C ++和makefile,它是在Apache 2.0下获得许可的,并附带一个演示Android应用程序。
还有一个纯Java库,JCodec但速度较慢,去年我使用它时,提取帧的颜色会失真。
答案 1 :(得分:2)
您必须将路径传递给此方法...完美运行的代码!希望有帮助
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);
}
答案 2 :(得分:0)
getFrameAt以毫秒为单位获取数据但是你在for循环中增加了.001毫秒。
for(int i=1000000;i<millis*1000;i+=1000000) // for incrementing 1s use 1000
{
bArray.add(mRetriever.getFrameAtTime(i,
MediaMetadataRetriever.OPTION_CLOSEST_SYNC));
}
像上面一样改变它。以上是创建所需内容的示例。我也回答了它here
答案 3 :(得分:0)
从Android 9.0(API级别28)开始,MediaMetadataRetriever
具有getFrameAtIndex (int frameIndex)
方法,该方法接受所需帧的从零开始的索引并返回位图。