I want to be able to trim a little bit off the beginning and end of a long video with FFmpeg. I can do this with a command like:
ffmpeg -i input.mp4 -ss 13 -to 59 output.mp4
FFmpeg will seek accurately to the requested times and do a full re-encode to the output file. This will take a relatively long time, but produce great results.
A faster way of trimming is to copy the video and audio data using -c copy
, e.g:
ffmpeg -i input.mp4 -ss 13 -to 59 -c copy output.mp4
However, because the trims are not at I-Frames, the output video is often choppy: frozen until the first I-Frames. Or doesn't quite have the length requested.
I wondered if it was possible to combine these methods:
- Measure where the I-Frames are, e.g:
ffprobe -select_streams v -skip_frame nokey -show_frames -show_entries frame=pts_time input.mp4
- Do a re-encode trim from the requested start up to the nearest I-Frame, e.g:
ffmpeg -i input.mp4 -ss 13 -to 13.12345 output1.mp4
- Do a copy trim from I-Frame to I-Frame, e.g:
ffmpeg -i input.mp4 -ss 13.12345 -to 58.12345 -c copy output2.mp4
- Do a re-encode trim from the last requested I-Frame up to the end, e.g:
ffmpeg -i input.mp4 -ss 58.12345 -to 59 output3.mp4
- Concatenating the three files together, e.g:
echo "file 'output1.mp4'" > mylist.txt
echo "file 'output2.mp4'" >> mylist.txt
echo "file 'output3.mp4'" >> mylist.txt
ffmpeg -y -f concat -safe 0 -i mylist.txt -c copy output4.mp4
In my testing this produces video that doesn't play well. Frames that freeze, audio out of sync, etc. I imagine because the three files I am concatenating aren't exactly the same format (frame rate, position of key frames, something along those lines). However, it certainly is faster for trimming little bits off of long files, if I could get it to work.
Is this method likely to work? If so, how could I get FFmpeg to produce three intermediate files that will concatenate nicely?