简体   繁体   English

ffmpeg从修剪的视频中获取帧的时间

[英]ffmpeg Get time of frames from trimmed video

I am using FFmpeg in my application to extract frames from a video, the frames will be added to a trim video view where you get an illustration as to what is happening in the video at a specific time within the video. 我在应用程序中使用FFmpeg从视频中提取帧,这些帧将被添加到修剪视频视图中,在该视图中您可以了解视频在特定时间段内视频的情况。 So each frame needs to represent some time within the video. 因此,每个帧都需要代表视频中的某个时间。

I dont quite understand how FFmpeg is producing the frames. 我不太了解FFmpeg是如何产生帧的。 Here is my code: 这是我的代码:

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

My app allows you to record a video at a max length of 20s. 我的应用程序允许您录制视频的最大长度为20秒。 The number of frames extracted from the video depnds on how long the captured video is. 从视频中提取的帧数取决于所捕获视频的时长。 frameSeperation is calculated doing the below code. 通过以下代码计算frameSeperation。

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;

Maybe the above logic is very bad, if there is a better way please can somebody tell me. 上面的逻辑也许很不好,如果有更好的方法,请告诉我。

Anyway I run the code and below are a few test cases: 无论如何,我运行代码,下面是一些测试用例:

  • A video captured with a length of 6 seconds has 7 frames. 捕获的长度为6秒的视频有7帧。
  • A video captured with a length of 2 seconds has 3 frames. 长度为2秒的视频捕获了3帧。
  • A video captured with a length of 10 seconds has 12 frames. 捕获的长度为10秒的视频有12帧。
  • A video captured with a length of 15 seconds has 9 frames. 长度为15秒的视频捕获有9帧。
  • A video captured with a length of 20 seconds has 11 frames. 长度为20秒的视频捕获有11帧。

There is no consistency, and I find it hard to put timestamps against each frame because of this. 没有一致性,因此,我发现很难在每个帧上加上时间戳。 I feel like my logic is wrong or im not understanding. 我觉得我的逻辑是错误的或不理解。 Any help is much appreciated 任何帮助深表感谢

Update 1 更新1

So I did what you said in comments: 所以我做了你在评论中说的话:

 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"
    };

I also tried "-vframes=" + 8 at the same point where I put vFrames in cmd. 在将vFrame放入cmd的同一点,我也尝试了"-vframes=" + 8 It doesnt seem to work at all now no frames are being extracted from the video 现在似乎根本不起作用,没有从视频中提取帧

This is the effective flow for fps=x , with the default rounding method near , 这是fps=x的有效流,默认舍入方法near

Generate intervals of 1/x seconds, e,g. 产生1/x秒的间隔,例如 for x=1/3 , intervals are 0-3s, 3-6s, 6-9s... Within each interval, pick an earlier frame whose timestamp is nearest to the midpoint of that interval. 对于x=1/3 ,间隔为0-3s,3-6s,6-9s ...在每个间隔内,选择一个时间戳最近的那个帧,该时间戳最接近该间隔的中点。 This may lead to duplicate frames, when that nearest frame belongs to an earlier interval, and was already picked for that interval. 当最近的帧属于较早的间隔并且已经为该间隔选择时,这可能导致重复的帧。 Likely to happen if source is variable frame-rate. 如果源是可变帧率,则可能发生。

In your case, I would suggest to avoid rounding or stripping fractional values, if possible. 在您的情况下,如果可能的话,我建议避免舍入或去除小数值。 Or do it at the end. 或者在最后做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM