How do I extract the timestamps associated with frames ffmpeg extracts from a video with the -r option?

12

5

ffmpeg -i myvid.mp4  -r  25  -t  100  image-%d.jpeg 

Is the command I'm using to extract frames and it's working just like I expected. However I'd also like to look at the timestamps of the frames. At whatever precision. 100 miliseconds is good enough for me. Can ffmpeg do this?

Providing additional details,

When I run the above command i get around 100 JPEGs, I guess there is a 1 to 1 (or many to 1) correspondence between these JPEGS and frames of the video. I would like to know the timestamp of the frame that was output as a JPEG image 'i'.

Additionally I tried ffprobe but I find it reports even the video duration inaccurately :(

Srini

Posted 2014-11-18T18:57:31.440

Reputation: 225

As what? AFAIK jpeg has no such metadata. The EXIF timestamp is for capture time. – Rajib – 2014-11-18T19:04:35.527

Sure the JPEG doesn't have the metadata, but the mp4 might. Can I direct ffmpeg to pull it along with the frames which it later encodes as JPEGS and dump the time stamps in a file? – Srini – 2014-11-18T19:06:30.390

Please include the complete ffmpeg console output from your command. – llogan – 2014-11-18T20:19:10.103

ffprobe can give you the timestamp information from the mp4 video stream. Are you asking as if frames may be duplicated or dropped then what is the correspondence to the original mp4 timestamps? In that case I would explore increasing the verbosity settings to see if you can get the frame by frame during execution. Could you expand on what you mean by "timestamps associated with frames". – dstob – 2014-11-18T21:41:22.340

@dstob The timestamps associated with frames are the presentation timestamps of the input video, i.e. when each frame should be shown, relative to the start of the video. – slhck – 2014-11-19T20:19:57.547

@Srinivas Suresh Quite often stream information is incorrect. You can use -show_frames and do a little parsing yourself or use -count_frames and the native framerate to calculate the duration. Since the correspondence seems so flexible then you'll have to do any final extraction yourself. Fun question btw, you might look at increasing verbosity during the ffmpeg run to get timestamp values as ffmpeg is choosing to duplicate/drop frames. Maybe combine this with ffrobe -show_frames to make your desired correspondence? – dstob – 2014-11-21T04:18:22.940

Answers

13

What you can do is "simulate" the image writing process by filtering with the fps filter, then using ffprobe to show the timestamps of the generated frames. This means that at 25 fps, the 50th frame (like your 50th image) will have a PTS of 2.00 seconds.

You do it like this:

ffprobe -f lavfi -i "movie=input.mp4,fps=fps=25[out0]" -show_frames -show_entries frame=pkt_pts_time -of csv=p=0

Will output:

0
0.04
0.08
0.12
0.16
...

These are the timestamps for each output image. You can actually combine the list of frames and the timestamps:

ls -1 image-*.jpeg > images.txt
ffprobe -f lavfi -i "movie=input.mp4,fps=fps=25[out0]" -show_frames -show_entries frame=pkt_pts_time -of csv=p=0 > frames.txt
paste images.txt frames.txt > combined.txt

Will create a file with:

image-0001.jpeg 0
image-0002.jpeg 0.04
image-0003.jpeg 0.08
image-0004.jpeg 0.12

Note that this may result in extraneous lines if there are too many frames or too many lines of info output. It seems a little inaccurate there.

slhck

Posted 2014-11-18T18:57:31.440

Reputation: 182 472

Is this the timestamp in relation to a constant framerate placed on the output or the correspondence of the outputted jpegs to the original mp4 timestamps that could be any framerate and have any timestamp values? – dstob – 2014-11-21T04:13:52.723

This timestamp is based on the requested output framerate. It relates to both the output pictures as well as the original input video frames those pictures came from—there is only one time base. This works because when changing the framerate, ffmpeg will (of course) not play the video faster, but "stretch" the presentation time of each frame, and drop unneeded frames. – slhck – 2014-11-21T07:25:10.803

Why does there have to be only one time base when you are manually creating the output time base? This won't always be the case of course but on the first 60 fps video I threw at it, ffmpeg just created its own time base ignoring the time stamps of the input. – dstob – 2014-11-21T19:01:28.653

Not sure I understand what exactly you're getting at. ffmpeg selects as input timebase whatever it parses as the first input file's timebase. You can of course also tell ffmpeg to throw away the input timestamps with -vsync drop, but that happens after filtering, IIRC.

– slhck – 2014-11-21T19:57:17.773