【问题标题】:Getting Frames From Videos Android从 Android 视频中获取帧
【发布时间】:2012-04-11 08:13:40
【问题描述】:

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

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 等,但我仍然在不同时间内从视频中获取相同的帧。我的目标是获得具有不同时间间隔的不同帧。

请给我你可能的帮助。

谢谢

【问题讨论】:

  • 您的代码运行速度太慢,一帧需要 1 秒。您找到更好的解决方案了吗?
  • 还没有哥们!其实我也在寻找优化的解决方案。
  • 那么看看下面我的解决方案吧!
  • @RahulUpadhyay 你的问题解决了吗?

标签: android video


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    如果您的视频是 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 并读取了上面的框架

    【讨论】:

    • 逻辑好。我试试看。
    • 投反对票的原因是什么。请解释
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      使用jCodec library,我可以使用此代码有效地获取所有帧以获取所有视频的帧:

      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]));
          }
      }
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:
          public Bitmap getFrameAtTime (long timeUs, int option)
          

          有人错过了记录 timeUs 预计为微秒,而不是此方法的毫秒。您可以在other methods doc 中找到该提示:

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

          确保将毫秒乘以 1000

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

          【讨论】:

            猜你喜欢
            • 2013-07-20
            • 1970-01-01
            • 1970-01-01
            • 2023-03-21
            • 1970-01-01
            • 2020-06-07
            • 1970-01-01
            • 2019-05-14
            • 1970-01-01
            相关资源
            最近更新 更多