我正在尝试使用MediaMetadataRetriever
和getFrameAt()
方法从视频中获取所有帧。使用FFMPEG,我得到了以下信息:
-
视频帧数:234帧
-
视频持续时间(毫秒(:90000
int counter = 0; long mVideoDuration = 9000; for (long i = 0; i < mVideoDuration * 1000; i += 1000) { Bitmap thumbnail = mMediaMetadataRetriever.getFrameAtTime(i); }
上面的代码不起作用,它几乎循环了8944次,这太多了,我不想得到所有这些帧,我只想得到234帧。
getFrameAtIndex()
工作非常好,但由于API级别的兼容性,我希望使其与getFrameAt()
方法一起工作
要使用getFrameeAtTime((获取帧,您必须知道视频中每一帧的时间。如果你已经知道帧计数,你可以通过获取帧时间(持续时间/帧(,采用math.ceil((方法,并将其作为增量,粗略地计算出。然而,你必须检查最后一帧是否被读取,因为你不能总是得到确切的帧时间,bc它们往往有很多小数位,这可能会导致错误的浮点表示。例如,60fps的视频将具有16+1/3毫秒的帧时间。Wich具有无限的小数位数。此外,如果你有一个帧速率太高的视频,这种方法甚至根本不起作用,因为在这种情况下,通过math.ceil((进行的四舍五入可能会导致足够大的裕度来跳过帧。准确地说,这种方法只在以下情况下有效:
(math.ceil(frameTime(-frameTime(‧frameCount<frameTime
我希望,到现在为止,你已经知道这是一个非常糟糕的主意,你可能应该用另一种方法来获得单个帧。但是,这里仍然有一个实现:
int lastTime;
long mVideoDuration = 9000;
mVideoDuration*=1000;
int frameTime=math.ceil(mVideoDuration/frameCount)
for(int i =0, i<=mVideoDuration, i+=frameTime){
Bitmap thumbnail = mMediaMetadataRetriever.getFrameAtTime(i);
lastTime=i;
}
if (lastTime<mVideoDuration){
mMediaMetadataRetriever.getFrameAtTime(mVideoDuration);
}
这已经是假设了,
(math.ceil(frameTime(-frameTime(‧frameCount<frameTime
给出。我不能保证declarframeTime会得到正确的值,因为我不知道小数除法是如何在内部处理的,这完全可能会导致浮点溢出的问题
您可以使用getFramesAtIndex(int frameIndex, int numFrames)
而不是getFrameAt()
,它将返回包含请求的视频帧的位图列表。
此方法类似于getFramesAtIndex(int,int,MediaMetadataRetriever.BitmapParams(,不同之处在于将使用MediaMetadataRetriever.BitmapParams的默认值。参数:frameIndex–要检索的第一个视频帧的基于0的索引。帧索引必须是有效帧的索引。可通过METADATA_KEY_VIDEO_FRAME_COUNT键查询可用于检索的帧总数。numFrames–要检索的连续视频帧数。必须是正值。流必须至少包含从frameIndex开始的numFrames帧。退货:包含请求的视频帧的位图列表。如果检索失败,返回的数组包含的帧可能少于请求的帧。投掷:IllegalStateException–如果容器不包含视频或图像序列。IllegalArgumentException–如果frameIndex或numFrames无效,或者流不包含至少从frameIndex开始的numFrames。另请参阅:getFrameAtIndex(int,MediaMetadataRetriever.BitmapParams(,getFrameAtIndex(int(,getFramesAtIndex(int,int,Media元数据检索器.BitmapParams(
关于numFrames
,您可以通过以下方式获得帧数:
m_mediaMetadataRetriever = new MediaMetadataRetriever();
m_mediaMetadataRetriever.setDataSource(getApplicationContext(), your_video_path);
int numFrames = Integer.parseInt(m_mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT));