从 Android 视频中获取帧
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10102242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting Frames From Videos Android
提问by Rahul Upadhyay
I wanna get number of frames from video.. I m using following code:
我想从视频中获取帧数..我使用以下代码:
package com.vidualtest;
import java.io.File;
import java.io.FileDescriptor;
import android.app.Activity;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.os.Bundle;
import android.os.Environment;
import android.widget.ImageView;
public class VidualTestActivity extends Activity {
/** Called when the activity is first created. */
File file;
ImageView img;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
img = (ImageView) findViewById(R.id.img);
File sdcard = Environment.getExternalStorageDirectory();
file = new File(sdcard, "myvid.mp4");
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(file.getAbsolutePath());
img.setImageBitmap(retriever.getFrameAtTime(10000,MediaMetadataRetriever.OPTION_CLOSEST));
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (RuntimeException ex) {
ex.printStackTrace();
} finally {
try {
retriever.release();
} catch (RuntimeException ex) {
}
}
}
}
}
here in getFrameAtTime() i m passing different static time like 10000,20000, etc. in milliseconds , but still i'm getting same frame from video within different time. My aim is to get different frames with different time interval.
在 getFrameAtTime() 中,我以毫秒为单位传递了不同的静态时间,如 10000、20000 等,但我仍然在不同的时间内从视频中获取相同的帧。我的目标是获得具有不同时间间隔的不同帧。
Please get me your possible help.
请给我你可能的帮助。
Thanks
谢谢
回答by Rickster
The time offset parameter is in microseconds, not milliseconds. So multiply your time offset by 1000, and it should work correctly.
时间偏移参数以微秒为单位,而不是毫秒。因此,将您的时间偏移量乘以 1000,它应该可以正常工作。
Thank you Google for NOT specifying this in the documentation.
感谢谷歌没有在文档中指定这一点。
回答by Jawad Zeb
if Your video is of 10s . if you want to take a frame after 1 second you increment it 1000000 which means after 1sec.
如果您的视频是 10 秒。如果您想在 1 秒后拍摄一帧,请将其增加 1000000,这意味着在 1 秒后。
I have stored id of image view in an array..
我已经将图像视图的 id 存储在一个数组中..
int[] ids_of_images = new int[]{R.id.img,R.id.img2,R.id.img3,R.id.img4,R.id.img5};
looper =1000000;
and then
进而
for(int i=0 ;i <10; i++)
{
ImageView imageView = (ImageView)findViewById(ids_of_images[i]);
imageView.setImageBitmap(retriever.getFrameAtTime(looper,MediaMetadataRetriever.OPTION_CLOSEST));
looper +=1000000;
}
I have tested it .. It is running . I have make ten ImageView and read frame like above
我已经测试过了。它正在运行。我已经制作了十个 ImageView 并像上面一样阅读框架
回答by Nati
Try Microseconds, it should work !
尝试微秒,它应该可以工作!
回答by Nativ
With the jCodec library, I'm able to get all frames efficiently with this code to get all the video's frames:
使用jCodec 库,我可以使用此代码有效地获取所有帧以获取所有视频的帧:
private class Decoder extends AsyncTask<File, Integer, Integer> {
private static final String TAG = "DECODER";
protected Integer doInBackground(File... params) {
FileChannelWrapper ch = null;
try {
ch = NIOUtils.readableFileChannel(params[0]);
FrameGrab frameGrab = new FrameGrab(ch);
MediaInfo mi = frameGrab.getMediaInfo();
Bitmap frame = Bitmap.createBitmap(mi.getDim().getWidth(), mi.getDim().getHeight(), Bitmap.Config.ARGB_8888);
for (int i = 0; !flag; i++) {
frameGrab.getFrame(frame);
if (frame == null)
break;
OutputStream os = null;
try {
os = new BufferedOutputStream(new FileOutputStream(new File(params[0].getParentFile(), String.format("img%08d.jpg", i))));
frame.compress(CompressFormat.JPEG, 90, os);
} finally {
if (os != null)
os.close();
}
publishProgress(i);
}
} catch (IOException e) {
Log.e(TAG, "IO", e);
} catch (JCodecException e) {
Log.e(TAG, "JCodec", e);
} finally {
NIOUtils.closeQuietly(ch);
}
return 0;
}
@Override
protected void onProgressUpdate(Integer... values) {
progress.setText(String.valueOf(values[0]));
}
}
回答by user1210233
I think getFrameAt() returns the frame thats closest to the time interval you specify. So specifying 1000 or 1500 as the time (in milliseconds) might return the same frame if the frame that's closest to both those time intervals is the same. To get the number of frames, you might want to get repetitive frames and then check whether they are distinct by just checking a few pixels. But you'll have to make sure that you don't miss any frames.
我认为 getFrameAt() 返回最接近您指定的时间间隔的帧。因此,如果最接近这两个时间间隔的帧相同,则指定 1000 或 1500 作为时间(以毫秒为单位)可能会返回相同的帧。要获得帧数,您可能希望获得重复的帧,然后仅通过检查几个像素来检查它们是否不同。但是您必须确保不会错过任何帧。