Answers.Body: <p>For MP4/MOV files, you could do this as follows:</p>
  <p>Say you wanted the frame number for frame at 1:05.00 (65.00s)</p>
  <p>Run</p>
  <p><code>ffmpeg -ss 1:05 -copyts -noaccurate_seek -i input.mp4 -vf &quot;select=gte(t\,64.8)*lt(t\,65.20) &quot; -f null -  -v 56 2&gt;&amp;1 | grep -e &quot;timestamp&quot; -e &quot;select_out:0&quot;</code></p>
  <p>For Rotem's test file, this produces</p>
  <pre><code>[mov,mp4,m4a,3gp,3g2,mj2 @ ...] stream 0, timestamp 663552, sample 500
  [Parsed_select_0 @ ...] n:148.000000 pts:663552.000000 t:64.800000 key:0 interlace_type:P pict_type:P scene:nan -&gt; select:1.000000 select_out:0
  [Parsed_select_0 @ ...] n:149.000000 pts:664576.000000 t:64.900000 key:0 interlace_type:P pict_type:B scene:nan -&gt; select:1.000000 select_out:0
  [Parsed_select_0 @ ...] n:150.000000 pts:665600.000000 t:65.000000 key:0 interlace_type:P pict_type:P scene:nan -&gt; select:1.000000 select_out:0
  [Parsed_select_0 @ ...] n:151.000000 pts:666624.000000 t:65.100000 key:0 interlace_type:P pict_type:B scene:nan -&gt; select:1.000000 select_out:0
  </code></pre>
  <p>So the nearest prior keyframe is #500, and the desired frame is #150 starting from the keyframe, hence an absolute index of 650, starting from 0, thus the 651st frame.</p>
  <p>This process keeps the decoding to a minimum. You can alter the radius in the select expression based on the framerate.</p>
  <hr />
  <p>Edit: the original method will be restored in ffmpeg 7.1<br />
  Edit2: My earlier answer didn't account for frame reordering. Modified process.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-13T19:07:03.067Z
Answers.LastActivityDate: 2024-09-14T11:00:21.843Z
Answers.LastEditDate: 2024-09-14T11:00:21.843Z
Answers.UserDisplayName: Gyan
Answers.Body: <p>We may use FFprobe <a href="https://stackoverflow.com/a/28376817/4926757">frames counting</a>:</p>
  <p><code>ffprobe -read_intervals &quot;%+01:05.01&quot; -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 input.mp4</code></p>
  <hr />
  <p><code>-read_intervals &quot;%+01:05.01 ...&quot;</code> - stops counting when timestamp reaches 01:05 (add 0.01 for including timestamp 01:05).</p>
  <hr />
  <p>Example:</p>
  <p>Build input video file <code>input.mp4</code> for testing (1000 frames at 10fps):<br />
  <code>ffmpeg -y -f lavfi -r 10 -i testsrc=size=384x216:rate=1:duration=1000 -vf setpts=N/TB/10 -c:v libx264 input.mp4</code></p>
  <p>Executing:</p>
  <p><code>ffprobe -read_intervals &quot;%+01:05.01&quot; -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 input.mp4</code></p>
  <p>Output:<br />
  <code>651</code></p>
  <p>Note: The result starts counting from 1.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-14T04:29:26.410Z
Answers.Text: With a read interval starting at the beginning and the printing of frame properties, this will decode all frames. If the timestamp is, say, 1h30m in a 30 fps stream, that's 162000 frames!
Answers.UserDisplayName: Gyan
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-14T08:12:25.620Z
Answers.Text: I know, but the [original method](https://stackoverflow.com/a/69693602/4926757) also traverses all the frames. I assume FFprobe doesn't decode all the frames, just parse all the frames. Your solution is much more efficient, but the output is 647. It is also not going to work when there is no PTS=65.0000 (say it is 65.01) . Please note that I am not trying to compete with your answer. I  had my answer ready after the OP posted the question in Super User, but moved it to Video Production site.
Answers.UserDisplayName: Rotem
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-14T10:28:22.697Z
Answers.Text: The original method uses `-vcodec copy` and fffprobe needs to decode frames if `show_frames` or `show_entries frame=` is specified.
Answers.UserDisplayName: Gyan
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-14T11:01:02.707Z
Answers.Text: I forgot about frame reordering. Modified answer.
Answers.UserDisplayName: Gyan
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-14T12:33:35.627Z
Answers.Text: I updated my answer with `-count_packets`. It's simpler than my previous solution, and probably faster than my previous solution.
Answers.UserDisplayName: Rotem
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-09-13T20:29:34.920Z
Answers.LastActivityDate: 2024-09-14T12:31:33.840Z
Answers.LastEditDate: 2024-09-14T12:31:33.840Z
Answers.UserDisplayName: Rotem
Body: <p>My question is based on the answer given here <a href="https://stackoverflow.com/a/69693602">https://stackoverflow.com/a/69693602</a>.</p>
  <p>The question asked was</p>
  <blockquote>
  <p>How can I get the frame number closest to a given time (relative to the start of the video) using ffmpeg?</p>
  </blockquote>
  <p>The proposed answer is to use following command and parse the output for <code>frame=</code> value:</p>
  <pre><code>ffmpeg -t 01:05 -i input.mp4 -nostats -vcodec copy -y -f rawvideo /dev/null
  </code></pre>
  <p>Using that command with ffmpeg 6.1.1 or higher omits the output of <code>frame=</code> value:</p>
  <pre><code>[out#0/rawvideo @ 0x603658390f80] video:10789kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
  size=   10789kB time=00:00:07.46 bitrate=11837.3kbits/s speed=2.01e+03x
  </code></pre>
  <p>Does anyone know a solution for that problem with ffmpeg &gt;= 6.1.1?</p>
  
Tags: <ffmpeg><video>
Title: How to get frame number given a timestamp using ffmpeg
UserDisplayName: Max Chr.
ThreadText: # How to get frame number given a timestamp using ffmpeg
  
  (Asked by: username_0 on 2024-09-13)
  
  My question is based on the answer given here <https://stackoverflow.com/a/69693602>.
  
  The question asked was
  
  > How can I get the frame number closest to a given time (relative to the start of the video) using ffmpeg?
  
  The proposed answer is to use following command and parse the output for `frame=` value:
  
  ```
  ffmpeg -t 01:05 -i input.mp4 -nostats -vcodec copy -y -f rawvideo /dev/null
  
  ```
  
  Using that command with ffmpeg 6.1.1 or higher omits the output of `frame=` value:
  
  ```
  [out#0/rawvideo @ 0x603658390f80] video:10789kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
  size=   10789kB time=00:00:07.46 bitrate=11837.3kbits/s speed=2.01e+03x
  
  ```
  
  Does anyone know a solution for that problem with ffmpeg >= 6.1.1?
  
  **Tags:** ffmpeg, video
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_2 on 2024-09-13. Score: 3 | Accepted answer
  
  We may use FFprobe [frames counting](https://stackoverflow.com/a/28376817/4926757):
  
  `ffprobe -read_intervals "%+01:05.01" -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 input.mp4`
  
  ---
  
  `-read_intervals "%+01:05.01 ..."` - stops counting when timestamp reaches 01:05 (add 0.01 for including timestamp 01:05).
  
  ---
  
  Example:
  
  Build input video file `input.mp4` for testing (1000 frames at 10fps):  
  `ffmpeg -y -f lavfi -r 10 -i testsrc=size=384x216:rate=1:duration=1000 -vf setpts=N/TB/10 -c:v libx264 input.mp4`
  
  Executing:
  
  `ffprobe -read_intervals "%+01:05.01" -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 input.mp4`
  
  Output:  
  `651`
  
  Note: The result starts counting from 1.
  
  > **Comments:**
  > **username_1**: With a read interval starting at the beginning and the printing of frame properties, this will decode all frames. If the timestamp is, say, 1h30m in a 30 fps stream, that's 162000 frames!  
  > **username_2**: I know, but the [original method](https://stackoverflow.com/a/69693602/4926757) also traverses all the frames. I assume FFprobe doesn't decode all the frames, just parse all the frames. Your solution is much more efficient, but the output is 647. It is also not going to work when there is no PTS=65.0000 (say it is 65.01) . Please note that I am not trying to compete with your answer. I  had my answer ready after the OP posted the question in Super User, but moved it to Video Production site.  
  > **username_1**: The original method uses `-vcodec copy` and fffprobe needs to decode frames if `show_frames` or `show_entries frame=` is specified.  
  > **username_1**: I forgot about frame reordering. Modified answer.  
  > **username_2**: I updated my answer with `-count_packets`. It's simpler than my previous solution, and probably faster than my previous solution.  
  
  ---
  
  ### Answer by username_1 on 2024-09-13. Score: 2
  
  For MP4/MOV files, you could do this as follows:
  
  Say you wanted the frame number for frame at 1:05.00 (65.00s)
  
  Run
  
  `ffmpeg -ss 1:05 -copyts -noaccurate_seek -i input.mp4 -vf "select=gte(t\,64.8)*lt(t\,65.20) " -f null - -v 56 2>&1 | grep -e "timestamp" -e "select_out:0"`
  
  For username_2's test file, this produces
  
  ```
  [mov,mp4,m4a,3gp,3g2,mj2 @ ...] stream 0, timestamp 663552, sample 500
  [Parsed_select_0 @ ...] n:148.000000 pts:663552.000000 t:64.800000 key:0 interlace_type:P pict_type:P scene:nan -> select:1.000000 select_out:0
  [Parsed_select_0 @ ...] n:149.000000 pts:664576.000000 t:64.900000 key:0 interlace_type:P pict_type:B scene:nan -> select:1.000000 select_out:0
  [Parsed_select_0 @ ...] n:150.000000 pts:665600.000000 t:65.000000 key:0 interlace_type:P pict_type:P scene:nan -> select:1.000000 select_out:0
  [Parsed_select_0 @ ...] n:151.000000 pts:666624.000000 t:65.100000 key:0 interlace_type:P pict_type:B scene:nan -> select:1.000000 select_out:0
  
  ```
  
  So the nearest prior keyframe is #500, and the desired frame is #150 starting from the keyframe, hence an absolute index of 650, starting from 0, thus the 651st frame.
  
  This process keeps the decoding to a minimum. You can alter the radius in the select expression based on the framerate.
  
  ---
  
  Edit: the original method will be restored in ffmpeg 7.1  
  Edit2: My earlier answer didn't account for frame reordering. Modified process.
  
  
  ---
  
  