【问题标题】:Get all frames from video using MediaMetadataRetriever使用 MediaMetadataRetriever 从视频中获取所有帧
【发布时间】:2022-11-27 00:26:45
【问题描述】:

我正在尝试使用 MediaMetadataRetrievergetFrameAt() 方法从视频中获取所有帧。 使用FFMPEG,我有以下信息:

  1. 视频帧数:234 帧

  2. 以毫秒为单位的视频持续时间: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() 方法一起使用

【问题讨论】:

    标签: java android mediametadataretriever


    【解决方案1】:

    要使用 getFrameeAtTime() 获取帧,您必须知道视频中每一帧的时间。您可以粗略地计算出,如果您已经通过获取帧时间(持续时间/帧)知道帧数,则可以对其使用 math.ceil() 方法并将其作为您的增量器。但是,您必须检查是否读取了最后一帧,因为您不能总是获得准确的帧时间,因为它们往往有很多小数位,这会导致错误表示为浮点数。 例如,60fps 视频的帧时间为 16+1/3 毫秒。其具有无限小数位。 此外,如果您的视频帧率过高,此方法甚至根本不起作用,因为在这种情况下,由 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

    给出。 而且我不能保证 declaframeTime 会产生正确的值,因为我不确切知道内部如何处理小数除法,并且完全有可能由于浮点溢出而导致问题

    【讨论】:

      【解决方案2】:

      您可以使用 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,MediaMetadataRetriever.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));
      

      【讨论】:

        猜你喜欢
        • 2013-11-09
        • 1970-01-01
        • 2013-11-14
        • 1970-01-01
        • 2020-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        相关资源
        最近更新 更多