如何获取Android中视频文件的关键帧(同步帧)时间戳列表?

时间:2012-08-03 15:11:01

标签: android video

是否有任何API可以为我提供Android中给定视频文件关键帧的时间戳列表?

4 个答案:

答案 0 :(得分:9)

对于一个优雅的解决方案,似乎你需要使用ffmpeg for android来实现这一目标。有人试过这样的方式:How to get the frame from video file in android;并建议使用ffmpeg。

我检查了参考手册,但是只能找到一种方法来使用MediaMetadataRetriever()获取相对于给定位置的关键帧本身(没有时间戳),如下所述:http://developer.android.com/reference/android/media/MediaMetadataRetriever.html#extractMetadata%28int%29

如果您不想使用ffmpeg,可以尝试以下方法:

private ArrayList<int> getKeyFrameTimestamps(String filename) {
  ArrayList<int> timeStamps = new ArrayList<int>();

  try {
    MediaMetadataRetriever mRetriever = new MediaMetadataRetriever();
    mRetriever.setDataSource(getDataSource(filename));
    mRetriever.getFrameAtTime(i, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);

    Bitmap lastFame = mRetriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_NEXT_SYNC);
    result.add(0);

    for(int time=1; frame ; ++time) {
      Bitmap frame = mRetriever.getFrameAtTime(time, MediaMetadataRetriever.OPTION_PREVIOUS_SYNC);
      if (frame && !frame.sameAs(lastFrame)) {
        result.add(time);
        lastFrame = frame;
      }
    }
  } catch (Exception e) {  /* TODO: HANDLE THIS */ }

  return timeStamps;
}

这当然不是很优雅,但可能没有麻烦安装ffmpeg ...它可能也很慢(我不知道)。但也许这正是你所需要的。

PS:可以在此找到适合您问题的ffmpeg教程:http://dranger.com/ffmpeg/tutorial07.html

答案 1 :(得分:5)

我相信正确的答案是http://code.google.com/p/mp4parser/

  

isoparser API可以读写MP4文件结构。它是一个处理所谓的盒子的低级工具,但它与处理轨道和电影等结构一样。

漂亮的API和比ffmpeg庞然大物快得多的方法

答案 2 :(得分:1)

4.1+ - 比mp4parser更快,因为在本机底层完成并且代码更清晰

mp4parser你必须从getsyncsamples + getsampledurations计算时间戳,这也是烦人的,他们不会与ffprobe匹配。这可以得到准确的结果

MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(getVideoPath());

int trackindex = MediaExtractorUtil.selectVideoTrack(extractor);
extractor.selectTrack(trackindex);

while (extractor.getSampleTime() != -1) {
    long sampleTime = extractor.getSampleTime();

    // check not really necessary but JIC
    if ((extractor.getSampleFlags() & MediaExtractor.SAMPLE_FLAG_SYNC) > 0) {
        mKeyframeTimestampsMS.add(sampleTime / 1000);
    }

    extractor.seekTo(sampleTime + 1, MediaExtractor.SEEK_TO_NEXT_SYNC);
}

答案 3 :(得分:0)

使用MediaExtractor,您可以在任何所需时间拥有所有关键(同步)帧时间和/或任何特定关键帧。 +一些更有用的数据。

然后通过MediaMetadataRetriever - &gt; getFrameAtTime你可以获得帧位图。

这是使用MediaExtractor的示例代码:

    mediaExtractor = new MediaExtractor() ;
    mediaExtractor.setDataSource(mediaPath);
    int numTracks = mediaExtractor.getTrackCount();
    for (int i = 0; i < numTracks; ++i) {
        MediaFormat format = mediaExtractor.getTrackFormat(i);
        String mime = format.getString(MediaFormat.KEY_MIME);
        if ( mime.startsWith("video") ) {
            mediaExtractor.selectTrack(i);
        }
        Log.i( "LOG_Extractor" , "track "+i+" "+mime );
    }

    currentTime = mediaPlayer.getCurrentPosition();
    mediaExtractor.seekTo( (long)currentTime*1000 , MediaExtractor.SEEK_TO_PREVIOUS_SYNC );
    previousKeyFrameTimeMilis = mediaExtractor.getSampleTime() /1000 ;