Answers.Body: <p>setpts filter only retimes frames; it cannot add or drop frames.</p>
  <p>The MP4 format is configured to require constant frame rate, and so ffmpeg's frame management (vsync) logic gets to work. This looks at the output frame rate, and the timestamps of the supplied frames to carry out frame duplication or drop decisions. But it first rebases the timestamps in terms of the output frame rate, and in this case, there seems to be some quirk in the output of that logic.</p>
  <p>Instead of debugging it, I suggest you manually drop half the frames before retiming.</p>
  <pre><code>-vf &quot;select=mod(n+1\,2),setpts=0.5*PTS&quot;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-09-07T10:44:05.347Z
Answers.Text: Yes, sorry for the confusion, I expressed the concept a bit roughly, thank you for the clarification.
Answers.UserDisplayName: IvanProsperi94
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-09-07T10:27:37.630Z
Answers.LastActivityDate: 2023-09-07T10:27:37.630Z
Answers.UserDisplayName: Gyan
Body: <h1>Description</h1>
  <p>I found a strange behavior in <code>setpts</code> filter: sometimes when I use it to speed up a video it inserts more frames than expected.</p>
  <p>My ffmpeg version is the following:</p>
  <pre><code>ffmpeg version 6.0-static https://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 8 (Debian 8.3.0-6)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100
  </code></pre>
  <h1>Preparation</h1>
  <p>Use this video as input, taken from <a href="https://trac.ffmpeg.org/wiki/ChangingFrameRate#Verifyingframeratechanges" rel="nofollow noreferrer">FFmpeg Wiki page about changing frame rate</a>:</p>
  <pre><code>ffmpeg -f lavfi -i testsrc=duration=10:size=854x480:rate=60 -vf &quot;drawtext=text=%{n}:fontsize=72:r=60:x=(w-tw)/2: y=h-(2*lh):fontcolor=white:box=1:boxcolor=0x00000099&quot; test.mp4
  </code></pre>
  <p>The <code>test.mp4</code> video has 60 fps, 600 total frames and a duration of 10 s.</p>
  <p>Use this command to create a 2x version of the input.</p>
  <pre><code>ffmpeg -i test.mp4 -vf &quot;setpts=0.5*PTS&quot; test_2x.mp4
  </code></pre>
  <p>The output should be twice as fast as the input, dropping half the frames to maintain the same framerate in half the duration: it should be still at 60 fps, but have a duration of 5 s and 300 total frames.</p>
  <h1>Problem</h1>
  <p>The issue is that the output video has 302 frames, not the exact 300, and consequently it has a duration of 05.033333 s. As the input video has the frame number printed on it, I can see that the first frames are not correctly dropped.</p>
  <p>This is what I get:</p>
  <pre><code> input frame:  | 0 | 1 | 2 | 3 | 4 | 5 | 6 |  7 |  8 |  9 | ... |
  output frame:  | 0 | 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12 | 14 | ... |
  </code></pre>
  <p>Notice that the first 5 frames are replicated without any drop, while 2 of them (1 and 3) should have been dropped.</p>
  <p>This is what I expected:</p>
  <pre><code> input frame:  | 0 | 1 | 2 | 3 | 4 |  5 |  6 |  7 |  8 |  9 | ... |
  output frame:  | 0 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | ... |
  </code></pre>
  <p>The issue is present also if I use other encoders or containers to create my output file: I tried ffvhuff in an mkv file and raw video in an y4m file, with the same results.</p>
  <p>The problem desappears if I add a <code>fps=60</code> filter after the <code>setps</code> one.</p>
  
Tags: <ffmpeg><video>
Title: FFmpeg setpts filter produces wrong frame number
UserDisplayName: IvanProsperi94
ThreadText: # FFmpeg setpts filter produces wrong frame number
  
  (Asked by: username_0 on 2023-09-07)
  
  # Description
  
  I found a strange behavior in `setpts` filter: sometimes when I use it to speed up a video it inserts more frames than expected.
  
  My ffmpeg version is the following:
  
  ```
  ffmpeg version 6.0-static https://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2023 the FFmpeg developers
  built with gcc 8 (Debian 8.3.0-6)
  configuration: --enable-gpl --enable-version3 --enable-static --disable-debug --disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig --enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom --enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
  libavutil      58.  2.100 / 58.  2.100
  libavcodec     60.  3.100 / 60.  3.100
  libavformat    60.  3.100 / 60.  3.100
  libavdevice    60.  1.100 / 60.  1.100
  libavfilter     9.  3.100 /  9.  3.100
  libswscale      7.  1.100 /  7.  1.100
  libswresample   4. 10.100 /  4. 10.100
  libpostproc    57.  1.100 / 57.  1.100
  
  ```
  
  # Preparation
  
  Use this video as input, taken from [FFmpeg Wiki page about changing frame rate](https://trac.ffmpeg.org/wiki/ChangingFrameRate#Verifyingframeratechanges):
  
  ```
  ffmpeg -f lavfi -i testsrc=duration=10:size=854x480:rate=60 -vf "drawtext=text=%{n}:fontsize=72:r=60:x=(w-tw)/2: y=h-(2*lh):fontcolor=white:box=1:boxcolor=0x00000099" test.mp4
  
  ```
  
  The `test.mp4` video has 60 fps, 600 total frames and a duration of 10 s.
  
  Use this command to create a 2x version of the input.
  
  ```
  ffmpeg -i test.mp4 -vf "setpts=0.5*PTS" test_2x.mp4
  
  ```
  
  The output should be twice as fast as the input, dropping half the frames to maintain the same framerate in half the duration: it should be still at 60 fps, but have a duration of 5 s and 300 total frames.
  
  # Problem
  
  The issue is that the output video has 302 frames, not the exact 300, and consequently it has a duration of 05.033333 s. As the input video has the frame number printed on it, I can see that the first frames are not correctly dropped.
  
  This is what I get:
  
  ```
   input frame:  | 0 | 1 | 2 | 3 | 4 | 5 | 6 |  7 |  8 |  9 | ... |
  output frame:  | 0 | 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12 | 14 | ... |
  
  ```
  
  Notice that the first 5 frames are replicated without any drop, while 2 of them (1 and 3) should have been dropped.
  
  This is what I expected:
  
  ```
   input frame:  | 0 | 1 | 2 | 3 | 4 |  5 |  6 |  7 |  8 |  9 | ... |
  output frame:  | 0 | 2 | 4 | 6 | 8 | 10 | 12 | 14 | 16 | 18 | ... |
  
  ```
  
  The issue is present also if I use other encoders or containers to create my output file: I tried ffvhuff in an mkv file and raw video in an y4m file, with the same results.
  
  The problem desappears if I add a `fps=60` filter after the `setps` one.
  
  **Tags:** ffmpeg, video
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2023-09-07. Score: 1 | Accepted answer
  
  setpts filter only retimes frames; it cannot add or drop frames.
  
  The MP4 format is configured to require constant frame rate, and so ffmpeg's frame management (vsync) logic gets to work. This looks at the output frame rate, and the timestamps of the supplied frames to carry out frame duplication or drop decisions. But it first rebases the timestamps in terms of the output frame rate, and in this case, there seems to be some quirk in the output of that logic.
  
  Instead of debugging it, I suggest you manually drop half the frames before retiming.
  
  ```
  -vf "select=mod(n+1\,2),setpts=0.5*PTS"
  
  ```
  
  > **Comments:**
  > **username_0**: Yes, sorry for the confusion, I expressed the concept a bit roughly, thank you for the clarification.  
  
  ---
  
  