9

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

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() 中,我以毫秒为单位传递了不同的静态时间,如 10000、20000 等,但我仍然在不同的时间内从视频中获取相同的帧。我的目标是获得具有不同时间间隔的不同帧。

请给我你可能的帮助。

谢谢

4

6 回答 6

35

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

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

于 2013-04-24T21:42:35.413 回答
3

如果您的视频是 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;
        }

我已经测试过了。它正在运行。我已经制作了十个 ImageView 并读取了上面的框架

于 2014-06-19T11:59:17.147 回答
2

尝试微秒,它应该工作!

于 2012-10-07T00:23:00.117 回答
1

使用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]));
    }
}
于 2013-10-30T08:50:09.497 回答
0

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

于 2012-07-05T20:06:38.417 回答
0
public Bitmap getFrameAtTime (long timeUs, int option)

有人错过了timeUs预期为微秒的文档,而不是此方法的毫秒。您可以在其他方法文档中找到该提示:

timeUs long:以微秒为单位的时间位置

确保将您的毫秒乘以 1000

retriever.getFrameAtTime(1000000, Int) // returns the frame after one second
于 2021-01-04T15:02:50.517 回答