5

I want to ask this question again because old solutions no longer work with ffmpeg 6.0, owing to a change made in January 2023 that prevents the use of the -r and -vsync/-fps_mode parameters simultaneously.

The goal is to use filenames or superposed text with images of frames, to identify their exact (presentation) timestamps in the original video, without any kinds of offsets, sanitisations, and to a user-desired precision (by default, milliseconds). Additionally, it should be possible to tell that every frame has been dumped, and sorted in timestamp order, from a specified segment of the video. The motive is to use the video to time the durations of events recorded in it.

The command I had previously thought solved this problem was:

ffmpeg
-ss 1:23:45
-t 5
-i input.mkv
-copyts
-fps_mode passthrough
-r 1000
-frame_pts 1
%08d.jpg

But it's apparently no longer possible to use -fps_mode with -r 1000. It seems that the image2 muxer implicitly used here defaults to a timebase of 1, and -r 1000 was previously being used to scale the timebase to 0.001. I am unsure if -enc_time_base 0.001 will do the same thing, and if I may need to also use -video_track_timescale or similar. I want to ideally extract the timestamps verbatim from the source, optionally truncated (e.g. to milliseconds) and not have to make assumptions about CFR/VFR etc. So I'd like a pro to check I'm doing this correctly. I'd also like to know how to get these same timestamps superposed on the images themselves, but haven't researched it pending getting the filenames method to work. Thanks.

Here's an answer by Gyan suggesting the now-impossible mixture of -vsync and -r.

2 Answers 2

2

Yes, a change was subsequently made to enforce CFR when -r is set.
-enc_time_base 1/FPS should be used instead.

-video_track_timescale is specific to MP4/MOV output.

2
  • Here's the full command that worked for me to extract scene frames from a video and include the timestamp in the filename: ffmpeg -i "<videoPath>" -vf "select='gt(scene,0.4)'" -frame_pts true -enc_time_base 1 -vsync vfr scene-%2d.jpg
    – UnionP
    Commented Apr 25, 2023 at 22:50
  • The select video filter here is usually achieved by -ss -t before -i I think, and the vsync I've never seen the point of (I've never seen a timestamp clash so prefer the passthrough option). The timestamps here seem to have a precision of 1s, quite crude. Otherwise looks sound. Idk if -copyts is necessary.
    – Pyoro
    Commented Sep 5 at 3:12
1

Here's the full command I put together (in PowerShell notation); thanks for everyone's help!

$drawTextParams = "fontfile=<insertFontFileInCurrentDirectory>: fontcolor=yellow: fontsize=36: x=3: y=3: text='%{n} | %{pts}'"
ffmpeg  -ss 1:23  -t 4.5  -i video.mp4  -vf drawtext=$drawTextParams 
 -copyts  -fps_mode passthrough  -enc_time_base 0.001  -frame_pts 1  %08d.png
  • -ss before -i: seeks to timestamp of input file;
  • -t: duration of video to process;
  • -i: input file;
  • -vf drawtext: process video with text addition filter (parameters listed under $drawtextparams, but it basically imprints sequence numbers (%{n}) and timestamps (%{pts}));
  • -copyts: copies timestamps verbatim from original video;
  • -fps_mode passthrough: each frame is processed, along with its timestamp;
  • -enc_time_base 0.001: timestamps are rescaled by 1/0.001 = 1000 (i.e. to milliseconds);
  • -frame_pts 1: timestamps are printed in the filename;
  • %08d.png: selects image encoder and filename (8-digit integer including leading zeros).

BEWARE: it's usually not possible to encode full precision timestamps (microseconds) into the filename because the values are stored internally as signed int32 counts of the unit (here, microseconds) and will overflow if the timestamps are over 35:47 :(.

5
  • the values are stored internally as int32 counts --> no, they are stored at int64.
    – Gyan
    Commented Sep 5 at 4:46
  • @Gyan run the command in the answer on a 36+ min video with -ss 35:47 and -t 1 and it should overflow with accurate timestamps printed on the images and negative numbers in the filenames. 35:47 is max signed int in microseconds (which I think is the conventional default for full-precision timestamps, by analogy with the drawtext pts template). Tested with ffmpeg 6.0.
    – Pyoro
    Commented Sep 8 at 21:34
  • ^ and -enc_time_base 0.000001, sorry
    – Pyoro
    Commented Sep 8 at 21:41
  • for more information on this, one may consult this analysis wherein I stepped through the source code to figure out what was happening (ctrl+f "accuracy theory")
    – Pyoro
    Commented Sep 8 at 23:46
  • Ah, you're actually talking about img_number and not timestamps.
    – Gyan
    Commented Sep 9 at 4:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .