MediaMetadataRetriever.getFrameAtTime()只返回第一帧

我使用MetadataRetriever从video中提取了帧,并将所有图像存储在ArrayList<Bitmap> 。 我想将它们全部存储在SD卡上(仅用于testing目的)。

但是,当我从模拟器中拉出一个文件夹并查看保存的图像时,所有图像只是video的第一帧。

这是我如何从video中提取帧:

 File videoFile=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/videos","sample_mpeg4.mp4"); Uri videoFileUri=Uri.parse(videoFile.toString()); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setDataSource(videoFile.getAbsolutePath()); ArrayList<Bitmap> rev=new ArrayList<Bitmap>(); //Create a new Media Player MediaPlayer mp = MediaPlayer.create(getBaseContext(), videoFileUri); int millis = mp.getDuration(); for(int i=0;i<millis;i+=100){ Bitmap bitmap=retriever.getFrameAtTime(i,OPTION_CLOSEST_SYNC); rev.add(bitmap); } 

这就是我如何保存它们(我调用这个方法并传递位图ArrayList):

 public void saveFrames(ArrayList<Bitmap> saveBitmapList) throws IOException{ Random r = new Random(); int folder_id = r.nextInt(1000) + 1; String folder = Environment.getExternalStorageDirectory()+"/videos/frames/"+folder_id+"/"; File saveFolder=new File(folder); if(!saveFolder.exists()){ saveFolder.mkdirs(); } int i=1; for (Bitmap b : saveBitmapList){ ByteArrayOutputStream bytes = new ByteArrayOutputStream(); b.compress(Bitmap.CompressFormat.JPEG, 40, bytes); File f = new File(saveFolder,("frame"+i+".jpg")); f.createNewFile(); FileOutputStream fo = new FileOutputStream(f); fo.write(bytes.toByteArray()); fo.flush(); fo.close(); i++; } Toast.makeText(getApplicationContext(),"Folder id : "+folder_id, Toast.LENGTH_LONG).show(); } 

当我拉出一个文件夹来查看所有的帧,所有的图像是第一帧的video。 有人可以向我解释发生了什么?

更新:

我已经尝试了另一个video。 我发现我没有得到空白图像,但它总是只返回第一帧。

MediaMetadataRetriever.getFrameAtTime(long timeUS)只返回第一帧,但我想检索所有的帧。 我应该做什么改变?

我如何解决这个问题?

Solutions Collecting From Web of "MediaMetadataRetriever.getFrameAtTime()只返回第一帧"

MediaMetadataRetrievergetFrameAt方法需要几微秒(百万分之一秒)而不是毫秒,所以在你的情况下,它总是舍入到第一帧。

只需将毫秒转换为微秒,因为getFrameAt以毫秒为单位获取数据

 1 miliseconds have 1000 microseconds.. for(int i=1000000;i<millis*1000;i+=1000000){ Bitmap bitmap=retriever.getFrameAtTime(i,OPTION_CLOSEST_SYNC); rev.add(bitmap); } 

那么你的问题就解决了

我根据自己的需要创build了它。

 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); File videoFile=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/screenshots/","myvideo.mp4"); Uri videoFileUri=Uri.parse(videoFile.toString()); MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setDataSource(videoFile.getAbsolutePath()); ArrayList<Bitmap> rev=new ArrayList<Bitmap>(); //Create a new Media Player MediaPlayer mp = MediaPlayer.create(getBaseContext(), videoFileUri); int millis = mp.getDuration(); for(int i=1000000;i<millis*1000;i+=1000000) { Bitmap bitmap=retriever.getFrameAtTime(i,MediaMetadataRetriever.OPTION_CLOSEST_SYNC); rev.add(bitmap); } } } 
 long time; String formattedFileCount; FileOutputStream fos; BufferedOutputStream bos; NumberFormat fileCountFormatter = new DecimalFormat("00000"); int fileCount = 0; File jpegFile; ArrayList<Bitmap> bArray = null; Bitmap lastbitmap = null; bArray = new ArrayList<Bitmap>(); 

我以微秒为单位获取时间,并从Mediaplayer获得持续时间,例如:

 time = mp.getDuration()*1000; Log.e("Timeeeeeeee", time); bArray.clear(); MediaMetadataRetriever mRetriever = new MediaMetadataRetriever(); mRetriever.setDataSource(path); int j=0; 

我的帧频是12帧/秒,所以我划分1/12 = 0.083333,这是一个帧的第二部分,比我转换我的帧秒微秒,所以它变成83333

  for (int i = 833333; i <= time; i=i+83333) { bArray.add(mRetriever.getFrameAtTime(i, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)); formattedFileCount = fileCountFormatter.format(fileCount); lastbitmap = bArray.get(j); j++; // image is the bitmap jpegFile = new File(Environment.getExternalStorageDirectory().getPath() + "/frames/frame_" + formattedFileCount + ".jpg"); fileCount++; try { fos = new FileOutputStream(jpegFile); bos = new BufferedOutputStream(fos); lastbitmap.compress(Bitmap.CompressFormat.JPEG, 15, bos); bos.flush(); bos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } catch (Exception e) { } 

使用MetaMediaRetriever我能够得到video的screeshot

https://code.google.com/p/android/issues/detail?id=35794

在你的for / loop上试试这个:

 Bitmap bitmap = retriever.getFrameAtTime( TimeUnit.MICROSECONDS.convert(i, TimeUnit.MILLISECONDS), retriever.OPTION_CLOSEST_SYNC);