Wednesday 21 February 2018

How to get time stamp of closest keyframe before a given timestamp with FFmpeg?


I want a FFmpeg seeking command that fast and accurate. I found this.


The solution is that we apply -ss for both input (fast seeking) and output (accurate seeking). But: If the input seeking is not accurate, how can we be sure that the seeking position is accurate?




For example: If we wanted to seek to 00:03:00, the command is something like:


ffmpeg -ss 00:02:30 -i  ... -ss 00:00:30 

The first -ss will seek to somewhere else, not 00:02:30, say 00:02:31. And after applying the second seek, the final result would be 00:03:01- not what we want. Is that correct?


Where does the first -ss seek to? Does it seek to the keyframe that is closest to 00:02:30?


If so, here is my thought—correct me if I'm wrong: after first seeking, we get the timestamp of the result (in this example: 00:02:31), then we apply second seeking with appropriate time, in this case 00:00:29.


Question is: How do we get time stamp of the first seek result?



Answer



To literally answer your title's question: You can get a list of I-frames with


ffprobe -select_streams v -show_frames  

You can further limit this to the necessary output by adding -show_entries frame=pkt_pts_time,pict_type.


To see which frame is closest (comes after) a certain timestamp, you'd first need to find out all timestamps of the keyframes, for example with awk.


First, define the time you want to look for, e.g., 2:30m which equals to 150s.


ffprobe -select_streams v -show_frames -show_entries frame=pkt_pts_time,pict_type -v quiet in.mp4 | 
awk -F= '
/pict_type=/ { if (index($2, "I")) { i=1; } else { i=0; } }
/pkt_pts_time/ { if (i && ($2 >= 150)) print $2; }
' | head -n 1

For example, this would return 150.400000.




Note that when using -ss before -i, FFmpeg will locate the keyframe previous to the seek point, then assign negative PTS values to all following frames up until it reaches the seek point. A player should decode but not display frames with negative PTS, and the video should start accurately.


Some players do not properly respect this and will display black video or garbage. In this case, the above script can be used to find the PTS of the keyframe after your seek point, and use that to start seeking from the keyframe. This, however, will not be accurate.


Note that if you want to be super accurate while seeking—and retain compatibility with many players—you should probably convert the video to any lossless, intra-only format, where you could cut at any point, and then re-encode it. But this will not be fast.


No comments:

Post a Comment

Where does Skype save my contact's avatars in Linux?

I'm using Skype on Linux. Where can I find images cached by skype of my contact's avatars? Answer I wanted to get those Skype avat...