Skip to content

Instantly share code, notes, and snippets.

@CoffeeFlux
Last active September 21, 2017 09:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CoffeeFlux/d45453a3842ea14d3f0689af48a2be2d to your computer and use it in GitHub Desktop.
Save CoffeeFlux/d45453a3842ea14d3f0689af48a2be2d to your computer and use it in GitHub Desktop.

Breaking up video

Fundamentally there are two main kinds of operations people want to do with ffmpeg: short clips and chunking up video.

The former is easiest to do by just re-encoding the video, assuming the clips are short. This means you can select any arbitrary points to encode from/to, and while the operation will take a minute if you set the quality properly there should not be a significant loss.

The latter is more complicated. Trying to re-encoding hours of video at a high quality is time-consuming and a waste. In this case, you want to trim along keyframes so that you don't have to re-encode the video at all (assuming we're dealing with x264 here anyway). For the non-technical, keyframes are just locations where the video data is specified from scratch, as opposed to referencing frames elsewhere in the video.

Get ffmpeg

No, seriously. Windows builds are available here. You'll want the latest semantic numbered version (at the time of writing, 3.2.2) 64-bit statically linked builds.

Clips

The command you want is:

ffmpeg -i input_file.mp4 -c:a copy -c:v libx264 -preset slow -crf 18 -ss 00:00:00.000 -to 00:00:00.000 output_file.mp4

Obviously you'll want to change the names of the input and output files respectively.

If ffmpeg isn't on your path, change ffmpeg to the path to the ffmpeg binary.

The timestamp after -ss is the start time, and the one after -to is the end time. If you would prefer to specify a duration instead of an end time, change -to to -t.

The number after -crf- is a quality indicator, and lower is better but produces a larger output filesize. The value after -preset is the x264 encoding preset, same as in OBS, and slower presets produce smaller output filesizes but take longer to run.

Chunks

This gets more complicated. You want your start and end points to line up with the location of keyframes. Below is a simple process to help with this, though keep in mind that 00:00:00.000 is always a keyframe and thus you can ignore these steps for that particular timestamp.

  1. Find the time you roughly want for either the start or end.
  2. Locate the first keyframe after the desired end using the following command: ffmpeg -i input_file.mp4 -c copy -ss 00:00:00.000 -t 00:00:10.000 keyframe_check.mp4. Note that this uses -t, and so you'll just want to change the start time.
  3. Find out the location of keyframes in that clip. This can be done using ffprobe: ffprobe -show_frames -select_streams v -print_format json=c=1 keyframe_check.mp4. The first frame it outputs should be labeled "key_frame": 1. Take the "best_effort_timestamp_time" and add it to your start time; this is your keyframe.
  4. If you really care about having a duplicate frame between the videos you can subtract one frame's duration from this value when using it as an end time. For most people, this doesn't matter.

Now that you know the start and end times for a given clip, you can just use ffmpeg -i input_file.mp4 -c copy -ss 00:00:00.000 -to 00:00:00.000 keyframe_check.mp4, which should look familiar and be easy to deal with. Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment