是否有任何API可以为我提供Android中给定视频文件关键帧的时间戳列表?
答案 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 ;