ffmpeg: extremely precise extraction of video segments
I want to extract segments of video with extremely precise start and end points. Unfortunately I'm only seeing accuracy to a hundredth of a second.
ffmpeg -i kayak.mp4 -ss 00:00:00 -t 2.86953 kayak_segment.mp4
Though I expect this segment to have a duration of 2.86953
, analysis on the outputted segment shows 2.891
.
ffprobe -i kayak_segment.mp4 -show_format -v quiet | sed -n 's/duration=//p'
(returns 2.891000
)
How do I best ensure that the durations of extracted video segments are as close to what is specified as possible? I'm not concerned about audio.
Thanks!
Video and audio streams are not continuous but quantized, so for a constant 25 fps video stream, the duration can take on values of 0.04 s x N
where N is the number of frames. If the audio codec is AAC @ 48000 sampling rate then with 1024 samples per frame, audio duration will be multiples of 1024/48000 = 0.021333 s
*.
Due to how AAC encoding occurs, there is a silent/padding audio frame at the beginning of the audio stream whose duration is 0.021333 s
but whose presentation time is -0.21333
. In format
, that packet is accounted for (but not in stream
duration).
When t
is used to trim a clip, all frames whose presentation timestamps are less than t
are pulled through. The duration of the last video frame isn't trimmed, but the duration of the last audio frame may be trimmed, but this too is quantized. SO, the final format
duration will be, AFAIK, Sum of all durations of packets of the stream featuring the greatest PTS
.
If you are not concerned with audio, you can strip it out (use -an
), and see that your t
value is similarly quantized as the video stream.