Variable frame rate: measure video time from timestamps
Counting frames gives you an order. It gives you elapsed time only if you also know how those frames are spaced. Before dividing a frame number by “25 fps” or “30 fps,” read the presentation timestamps for the two frames in the file you actually have.
For a file with variable frame timing, subtract the earlier frame’s timestamp from the later one. That measures the interval on this file’s presentation timeline. It does not establish when a camera recorded the scene, or how much real-world time passed across an edit.

A five-frame file that breaks the shortcut
For this article, we created a synthetic video containing five solid-blue frames and deliberately changed their timing. We inspected the FFV1 video in a Matroska file locally with ffprobe 9.0.2 on 2 November 2026. No incident footage or camera recording was used.
| Frame index, starting at zero | Presentation time, seconds | Gap from previous frame |
|---|---|---|
| 0 | 0.000 | — |
| 1 | 0.040 | 0.040 s |
| 2 | 0.080 | 0.040 s |
| 3 | 0.240 | 0.160 s |
| 4 | 0.280 | 0.040 s |
From the first frame’s presentation time to the last, the interval is 0.280 seconds. Assuming a constant 25 frames per second would give (4 − 0) / 25 = 0.160 seconds. The wider gap between indices 2 and 3 disappears in that calculation.
There are five frames but four gaps between them. Dividing five by 25 answers a different question and still assumes constant spacing. Nor is 0.280 seconds necessarily the full file duration: the final frame can remain on screen after its presentation timestamp.
Read the timing without creating another video
Keep the supplied file, record where it came from, and work on a copy. A SHA-256 file hash helps identify which exact file your calculation describes. Run this command with FFmpeg’s ffprobe installed, replacing COPY.mkv with the copy’s path:
ffprobe -v error -select_streams v:0 -show_frames -show_entries frame=pts_time,best_effort_timestamp_time -of json "COPY.mkv"
This reads the first video stream and prints frame information as JSON; it does not encode an output video. The ffprobe manual documents stream selection, frame output and the choice of fields. Long files can produce a large output.
pts_time expresses the presentation timestamp in seconds. Presentation time means when a frame is meant to be shown. Keep the second field separate: FFmpeg describes best_effort_timestamp as an estimate derived using heuristics in its frame definitions. In our fixture the two fields agreed for every frame. That agreement is a result for this fixture, not a promise about other files.
- Identify the two relevant frames in the same file and video stream. Record what visible event defines each selection.
- Match those frames to their presentation timestamps. Record whether your frame count starts at zero or one.
- Inspect the intervening timestamps and their differences. Unequal gaps show unequal presentation spacing in this file; a single average rate cannot describe all of them.
- Subtract the two timestamps, retaining the precision of the available data. Store the command and output alongside the result.
If a value is absent, do not replace it with zero. If only an estimated timestamp is available, label it as estimated. Repeated, decreasing or otherwise unexpected values need investigation before a precise interval is reported; sorting the numbers alone can sever their connection to the selected pictures. Small differences may also reflect timestamp precision. A timing anomaly does not, by itself, establish manipulation.
Why converting to a constant rate changes the question
An editing program may offer a constant-frame-rate export. FFmpeg’s frame-rate documentation explains that constant-rate processing can duplicate or drop frames. Measuring that new file describes the export. Preserve and inspect the supplied version before using a conversion for easier playback.
For two uploads of the same scene, first determine which pictures correspond using a keyframe comparison. Do not transfer frame numbers or timing directly between versions. A matching picture can occupy a different position on each file’s timeline.
Write a conclusion another reader can check
For the synthetic exercise, a defensible result is: “In this generated file, frame indices 0 and 4 have presentation timestamps 0.000 and 0.280 seconds. Their presentation-time difference is 0.280 seconds. This exercise makes no claim about camera capture time.”
For your own file, put its hash, stream, selected pictures, timestamp fields, subtraction and remaining uncertainty into the investigation record. The useful deliverable is a reproducible interval with a clear scope, not an unexplained frame count.
Published 2026-11-03 · OSINT Jet editorial team
