Slicing video file into several segments

6

2

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

Code_Ed_Student

Posted 2014-10-04T14:10:02.883

Reputation: 139

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 – 2014-10-12T18:07:23.723

@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?

– Code_Ed_Student – 2014-10-12T18:13:49.910

@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 – 2014-10-12T19:03:23.847

Answers

10

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.

techAddict82

Posted 2014-10-04T14:10:02.883

Reputation: 316

This works! but it just takes a long time to re-encode video – Code_Ed_Student – 2014-10-13T02:24:17.503

A GOP size of 9 is really low, not sure if that's recommendable here. – slhck – 2014-10-13T06:03:24.013

@slhck what would you recommend for the GOP size? – Code_Ed_Student – 2014-10-13T17:14:30.250

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 – 2014-10-13T18:31:32.483

@slhck Ok great, explanation. How do I calculate to determine? Lets say instead of 10 i want up to 9 secs or x secs. – Code_Ed_Student – 2014-10-13T18:48:07.673

1It'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 – 2014-10-13T20:23:54.230

Great, I will try that. The only downside to this whole answer is that the re-encode process takes a longer time. Is there a quicker way to reencode video and then segment? – Code_Ed_Student – 2014-10-13T20:33:20.277

1Please explain more about "expr:gte(t,n_forced*9)" ? – Dr.jacky – 2015-08-23T11:50:48.837

8

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

evilsoup

Posted 2014-10-04T14:10:02.883

Reputation: 10 085

How do I ensure accuracy using ffmpeg -segment_time instead of the slower script process? – Code_Ed_Student – 2014-10-11T01:26:09.843