15

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
3
  • Essential info is missing: What does your script do, exactly? Can you post it here? Also, mind you that ffmpeg can only split at I-frames when doing a stream copy. If your script however re-encodes the file, it can virtually split anywhere.
    – slhck
    Oct 12, 2014 at 18:07
  • @slhck my original script splits the video into equivalent segments . For example -c 8 will split video into segments that are 8 seconds. It does not re-encode so which is why certain segments have a still image at the end. Here is a link to the script i am suing: SCRIPT . How can do this? Is it possible to do all this without the need of a script? Oct 12, 2014 at 18:13
  • @Code_Ed_Student They may be identical length but as you reported there is repeated information between segments. The segmenter handles all of this under the hood for you (the best it can). If you want to know more then it may be worthwhile to read on video encoding itself.
    – dstob
    Oct 12, 2014 at 19:03

2 Answers 2

19
+100

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.

8
  • This works! but it just takes a long time to re-encode video Oct 13, 2014 at 2:24
  • A GOP size of 9 is really low, not sure if that's recommendable here.
    – slhck
    Oct 13, 2014 at 6:03
  • 2
    @Code_Ed_Student It depends on your application. If you target playback from media where you don't expect packet loss or frame decoding issues, go with larger GOPs of up to 10 seconds (e.g. -g 250 at 25fps). For adaptive streaming media (e.g. DASH, HLS), segments might be just one second long, so the GOP size would be equal to the FPS. But certainly nothing less than the FPS, because it's inefficient.
    – slhck
    Oct 13, 2014 at 18:31
  • 1
    It's just the number of second times the frames per second your video has. If your video has 25 fps and you want a GOP of 10 seconds, you need a GOP size of 250. @Code_Ed_Student
    – slhck
    Oct 13, 2014 at 20:23
  • 1
    Please explain more about "expr:gte(t,n_forced*9)" ?
    – Dr.jacky
    Aug 23, 2015 at 11:50
15

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

1
  • How do I ensure accuracy using ffmpeg -segment_time instead of the slower script process? Oct 11, 2014 at 1:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .