【问题标题】:ffmpeg Get time of frames from trimmed videoffmpeg 从修剪的视频中获取帧的时间
【发布时间】:2018-04-29 10:25:25
【问题描述】:

我在我的应用程序中使用 FFmpeg 从视频中提取帧,这些帧将被添加到修剪视频视图中,您可以在其中了解视频中特定时间视频中发生的情况。所以每一帧都需要代表视频中的一些时间。

我不太明白 FFmpeg 是如何生成帧的。这是我的代码:

"-i",
videoCroppedFile.getAbsolutePath(),
"-vf",
"fps=1/" + frameSeperation,
mediaStorageDir.getAbsolutePath() +
"/%d.jpg"

我的应用允许您录制最长 20 秒的视频。从视频中提取的帧数取决于捕获的视频的长度。 frameSeparation 是通过以下代码计算得出的。

String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
    long videoLength = Long.parseLong(time) / 1000;
    double frameSeperationDouble = (double) videoLength;
    // Divide by 11 because there is a maximum of 11 frames on trim video view
    frameSeperationDouble /= 11;
    frameSeperationDouble = Math.ceil(frameSeperationDouble);
    int frameSeperation = (int) frameSeperationDouble;

也许上面的逻辑很糟糕,如果有更好的方法请有人告诉我。

无论如何我运行代码,下面是一些测试用例:

  • 拍摄的时长为 6 秒的视频有 7 帧。
  • 以 2 秒的长度拍摄的视频有 3 帧。
  • 一个长度为 10 秒的视频有 12 帧。
  • 拍摄的时长为 15 秒的视频有 9 帧。
  • 一个长度为 20 秒的视频有 11 帧。

没有一致性,因此我发现很难为每一帧设置时间戳。我觉得我的逻辑是错误的或者我不理解。非常感谢任何帮助

更新 1

所以我按照你在cmets中说的做了:

 final FFmpeg ffmpeg = FFmpeg.getInstance(mContext);
        final File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
                + "/Android/data/"
                + mContext.getPackageName()
                + "/vFrames");

    if (!mediaStorageDir.exists()){
        mediaStorageDir.mkdirs();
    }

    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    retriever.setDataSource(mContext, Uri.fromFile(videoCroppedFile));
    String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
    long videoLength = Long.parseLong(time) / 1000;
    double frameSeperationDouble = (double) videoLength / 8;

    retriever.release();

    final String cmd[] = {

            "-i",
            videoCroppedFile.getAbsolutePath(),
            "-vf",
            "fps=1/" + frameSeperationDouble,
            "-vframes," + 8,
            mediaStorageDir.getAbsolutePath() +
            "/%d.jpg"
    };

我还在将 vFrames 放入 cmd 的同一点上尝试了 "-vframes=" + 8。它似乎根本不起作用,现在没有从视频中提取帧

【问题讨论】:

  • 如果你想获取视频的每一帧,只需去掉-vf fps=1/[frameseparation]。如果您想每 x 秒捕获一次图像,您可能应该改用 -r fps

标签: java android ffmpeg android-ffmpeg


【解决方案1】:

这是fps=x的有效流程,默认取整方法near

生成1/x 秒的间隔,例如对于x=1/3,间隔为 0-3s、3-6s、6-9s... 在每个间隔内,选择一个较早的帧,其时间戳最接近该间隔的中点。当最近的帧属于较早的间隔并且已经为该间隔挑选时,这可能会导致重复的帧。如果源是可变帧速率,则可能发生。

在您的情况下,我建议尽可能避免舍入或去除小数值。或者在最后做。

【讨论】:

  • 我隐约理解您的建议,但并不完全理解。如果可能的话,你能给我一些示例代码吗?因为视频长度是可变的,所以我不完全理解你的场景是如何工作的。谢谢
  • 您的目标是从每个视频中获取 11 帧,无论时长如何?
  • 老实说 8 帧是我想要的数量,与持续时间无关
  • 将视频时长除以 8,不要转换为整数。保留(至少 2 个)十进制值并将其传递给 ffmpeg。在过滤器后添加"-vframes", "8"
  • 请检查更新的答案。非常感谢您的帮助,因为我已经坚持了一段时间。现在
猜你喜欢
  • 2010-11-07
  • 2017-08-10
  • 2014-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-13
  • 1970-01-01
相关资源
最近更新 更多