Slicing video file into several segments

I am currently using ffmpeg to slice video files. I automated the process through a script called ffmpeg_split.sh. Although this very slow it is efficient in splitting videos into equivalent settings. The only issue is that it has frame rate issues. Below evil soup recommended a way to do all this using segment in ffmpeg. I tried this but it does not give me equivalent duration segments.

UPDATE

Per evilsoup using this command to segment videos:

ffmpeg -i input.mp4 -c copy -map 0 -segment_time 8 -f segment output%03d.mp4

OLD:

Here is the syntax to slice a video with script: ffmpeg_split.sh -s test_vid.mp4 -o video-part%03d.mp4 -c 00:00:08

Results

my_split_script.sh

input.mp4 – Duration 00:01:20
#EXTINF:10,
Output01.mp4
#EXTINF:10,
Output02.mp4
#EXTINF:10,
Output03.mp4
#EXTINF:9,
Output04.mp4
#EXTINF:10,
Output05.mp4
#EXTINF:10,
Output06.mp4
#EXTINF:11,
Output07.mp4
#EXTINF:10,
Output08.mp4
real    0m30.517s #execution time

ffmpeg

input.mp4 – Duration 00:01:20
#EXTINF:10,
Output01.mp4
#EXTINF:10,
Output02.mp4
#EXTINF:6,
Output03.mp4
#EXTINF:10,
Output04.mp4
#EXTINF:10,
Output05.mp4
#EXTINF:7,
Output06.mp4
#EXTINF:10,
Output07.mp4
#EXTINF:9,
Output08.mp4
real    0m7.493s #executition time

You can do this directly from ffmpeg without the use of a script. Essentially whenever you use ffmpeg segment, it will go ahead and do its best to split close to the time you specified for each segment. This is based in key_frames it will find the closest key frame and cut there. In order to cut exact segments you will need to re encode the whole video.

ffmpeg -i input.mp4 -c:v libx264 -crf 22 -map 0 -segment_time 9 -g 9 -sc_threshold 0 -force_key_frames "expr:gte(t,n_forced*9)" -f segment output%03d.mp4

You will need to read into -crf, -sc_threshold and -force_key_frames. In the wiki for ffmpeg.


ffmpeg can actually do this itself, using the segment muxer

ffmpeg -i input.mp4 -c copy -map 0 -segment_time 8 -f segment output%03d.mp4

You should definitely read the documentation and play around a bit to get the best results (the default will be good enough for most purposes, but won't get you 100% accurate splitting).


In general, if you need to get information such as duration out of a file, it's better to use ffprobe, which comes bundled with ffmpeg -- it prints the information as a bunch of key=value pairs, making it much easier to deal with.

ffprobe -show_format file.mp4 | grep -F duration | cut -d= -f2
## or, if you want hh:mm:ss format:
ffprobe -show_format -sexagesimal file.mp4 | grep -F duration | cut -d= -f2

...but, I think it's probably better to rely on ffmpeg's own options, rather than a shell script (which will be much less efficient, since it needs to call many instances of ffmpeg).