bytedeco/javacv

Invalid keyframe timestamps

Open

#875 opened on Jan 11, 2018

View on GitHub
 (4 comments) (0 reactions) (0 assignees)Java (1,583 forks)batch import
bughelp wanted

Repository metrics

Stars
 (6,985 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

Hi @saudet ,

I'm coming again with new issue. It looks like the timestamps of keyframes might be incorrect

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

public class VideoAnalyzer {

    public static final String PICTURE_FORMAT = "jpg";

    public static void main(String[] args) throws Exception {
        extractKeyFramePictures(true);
        extractKeyFramePictures(false);
    }

    public static void extractKeyFramePictures(boolean alternatives) throws Exception {
        try (FFmpegFrameGrabber video = new FFmpegFrameGrabber(
                "https://www.dropbox.com/s/ba3plzmv84y2qxd/keyframes_test.mp4?dl=1")) {
            video.start();
            long endTimeMicros = video.getLengthInTime();
            Frame frame;
            //an alternative way to grab keyframes based on Frame.keyFrame flag
            if (alternatives) {
                while (video.getTimestamp() <= endTimeMicros && (frame = video.grabImage()) != null) {
                    if (frame.keyFrame) {
                        savePicture(frame, video.getTimestamp(), "_alternative");
                    }
                }
            // default keyframes grabbing
            } else {
                while (video.getTimestamp() <= endTimeMicros && (frame = video.grabKeyFrame()) != null) {
                    savePicture(frame, video.getTimestamp(), "");
                }
            }
        }
    }
    
    private static void savePicture(Frame frame, long timestamp, String suffix) throws Exception {
        long timestampInMills = TimeUnit.MICROSECONDS.toMillis(timestamp);
        File frameFile = new File(timestampInMills + suffix + "." + PICTURE_FORMAT);
        BufferedImage image = new Java2DFrameConverter().convert(frame);
        ImageIO.write(image, PICTURE_FORMAT, frameFile);
    }
    
}

See two pictures 10677_alternative.jpg 10677_alternative

13580.jpg 13580

Correct keyframe appears at 10677 mills but FFmpegFrameGrabber.grabKeyFrame has the time 13580 mills with this keyframe.

It happens with some videos, not permanent.

Contributor guide