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
).