Slicing video file into several segments

30,851

Solution 1

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.

Solution 2

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

Share:
30,851

Related videos on Youtube

Code_Ed_Student
Author by

Code_Ed_Student

Updated on September 18, 2022

Comments

  • Code_Ed_Student
    Code_Ed_Student almost 2 years

    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
    
    • slhck
      slhck over 9 years
      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.
    • Code_Ed_Student
      Code_Ed_Student over 9 years
      @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?
    • dstob
      dstob over 9 years
      @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.
  • Code_Ed_Student
    Code_Ed_Student over 9 years
    This works! but it just takes a long time to re-encode video
  • slhck
    slhck over 9 years
    A GOP size of 9 is really low, not sure if that's recommendable here.
  • Code_Ed_Student
    Code_Ed_Student over 9 years
    @slhck what would you recommend for the GOP size?
  • slhck
    slhck over 9 years
    @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.
  • Code_Ed_Student
    Code_Ed_Student over 9 years
    @slhck Ok great, explanation. How do I calculate to determine? Lets say instead of 10 i want up to 9 secs or x secs.
  • slhck
    slhck over 9 years
    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
  • Code_Ed_Student
    Code_Ed_Student over 9 years
    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?
  • Dr.jacky
    Dr.jacky almost 9 years
    Please explain more about "expr:gte(t,n_forced*9)" ?