从Android视频中获取帧

从Android视频中获取帧,android,video,Android,Video,我想从视频中获取帧数。。我正在使用以下代码: 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

我想从视频中获取帧数。。我正在使用以下代码:

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) {
        }
    }


}
}

在getFrameAtTime()中,我以毫秒为单位传递不同的静态时间,如1000020000等,但我仍然在不同的时间内从视频中获得相同的帧。我的目标是以不同的时间间隔获得不同的帧

请给我你可能的帮助


谢谢

我认为getFrameAt()返回最接近您指定的时间间隔的帧。因此,如果最接近这两个时间间隔的帧是相同的,那么指定1000或1500作为时间(以毫秒为单位)可能会返回相同的帧。要获得帧数,您可能需要获得重复的帧,然后通过只检查几个像素来检查它们是否不同。但您必须确保不会错过任何帧。

试试微秒,它应该可以工作

时间偏移参数的单位是微秒,而不是毫秒。因此,将时间偏移量乘以1000,它应该可以正常工作

感谢Google没有在文档中指定这一点。

使用,我能够高效地获取所有帧,使用此代码可以获取所有视频帧:

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]));
    }
}
私有类解码器扩展异步任务{
私有静态最终字符串标记=“解码器”;
受保护的整数doInBackground(文件…参数){
FileChannelWrapper ch=null;
试一试{
ch=NIOUtils.readableFileChannel(参数[0]);
FrameGrab FrameGrab=新的FrameGrab(ch);
MediaInfo mi=frameGrab.getMediaInfo();
位图帧=Bitmap.createBitmap(mi.getDim().getWidth(),mi.getDim().getHeight(),Bitmap.Config.ARGB_8888);
对于(int i=0;!flag;i++){
frameGrab.getFrame(frame);
if(frame==null)
打破
OutputStream os=null;
试一试{
os=new BufferedOutputStream(新文件(参数[0].getParentFile(),String.format(“img%08d.jpg”,i)));
frame.compress(CompressFormat.JPEG,90,os);
}最后{
如果(os!=null)
os.close();
}
出版进度(一);
}
}捕获(IOE异常){
Log.e(标签“IO”,e);
}捕获(JCodeceException e){
Log.e(标签“JCodec”,e);
}最后{
NIOUtils.closes(ch);
}
返回0;
}
@凌驾
受保护的void onProgressUpdate(整型…值){
progress.setText(String.valueOf(值[0]);
}
}

如果您的视频为10秒。如果你想在1秒后拍摄一帧,你可以增加1000000,也就是说在1秒后

我已将图像视图的id存储在数组中

int[] ids_of_images = new int[]{R.id.img,R.id.img2,R.id.img3,R.id.img4,R.id.img5};
looper =1000000;
然后

 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;
        }
for(int i=0;i
有人没有记录到该方法的
timeUs
预期为微秒,而不是毫秒。您可以在以下内容中找到该提示:

timeUslong:以微秒为单位的时间位置

确保你的毫秒乘以1000

retriever.getFrameAtTime(1000000, Int) // returns the frame after one second

你的代码太慢了,一帧1秒。你找到更好的解决方案了吗?还没有,伙计!事实上我也在寻找优化的解决方案。看看我下面的解决方案吧!@Rahulupadhaya你解决了你的问题吗?很好的逻辑。我会试试。投反对票的原因是什么。请解释一下
retriever.getFrameAtTime(1000000, Int) // returns the frame after one second