Trimming Video with FFmpeg

If you're a developer and work with video, there's a chance that you may need to trim or cut parts of the video for your users. In this post, I'll be going through the commands needed to do this in FFmpeg along with some details to consider when trimming video. Let's dive in!

Aaron Bos | Tuesday, April 30, 2024

Seeking with FFmpeg

The functionality for "trimming" or "cutting" video is included in a command flag -ss and it's referred to as "seeking". The seek option is a time duration value that tells FFmpeg where to seek directly in the input or output.

Here is an example of a command using the -ss option where FFmpeg will seek five seconds at the beginning of the input video before decoding it for the output. The output from this command will be missing the first five seconds of the original input.

ffmpeg -ss 5 -i input.mp4 out.mp4

It's important to note that the placement of -ss in the command will play a role in how FFmpeg seeks the video as well as how fast the command runs. When specified before the input file(s) or -i flag, FFmpeg will seek directly to the specified duration on the input before decoding.

The other alternative is to include the -ss flag after the input file(s), which results in FFmpeg decoding and discarding each frame of the video until it reaches the seek time duration.

ffmpeg -i input.mp4 -ss 5 out.mp4

This can be useful or required if filters need to be applied to generate the desired output, but it's key to know this can be much slower than seeking the input file. For that reason, I'd default to seeking the command input unless seeking the output is required.

Time Duration Syntax

When it comes to values that we can use for the -ss flag, FFmpeg expects a "time duration" value. Time duration values can come in two forms and both forms can specify negative values.

  1. [-][HH:]MM:SS[.m...]
  2. [-]S+[.m...][s|ms|us]

In the first syntax HH: represents the number of hours and is optional. MM and SS are required representing minutes and seconds respectively. Finally, .m represents an optional decimal value for seconds. Our previous command using this syntax would look like the command below.

ffmpeg -ss 00:05 -i input.mp4 out.mp4

We used the second syntax listed in our previous examples, but I do think it's worth noting that seconds are assumed unless specified with one of the valid suffixes.

  • s seconds
  • ms milliseconds
  • us microseconds

All of the commands below are equivalent in the amount of video to seek in comparison to previous commands.

ffmpeg -ss 5000ms -i input.mp4 out.mp4
ffmpeg -ss 5000000us -i input.mp4 out.mp4
ffmpeg -ss 5s -i input.mp4 out.mp4

So far the commands we've listed will seek or trim video starting at the beginning of an input file. Next, we'll look at the command flags we can use to also trim video from the end of a file.

Cutting Parts of Video

There may be situations when you want to remove video from the end of a file and to do that we'll want to look at the -t and -to command flags. While these two flags serve similar purposes, they are mutually exclusive and can't be used together in the same command. If both are included, -t will take priority. So what do these flags do exactly?

Both -t and -to accept time duration values, but how FFmpeg uses the time durations is the key differentiator between the two flags.

  • -t expects its value to be a duration of the input or output
  • -to expects its value to be a position in the input or output

Similarly to -ss these commands can be used to operate on the input or output (before or after the -i input.file). When -t and -to are used in a command without -ss their behavior is pretty straightforward. For example, this command will result in the output containing the first eight seconds of video.

ffmpeg -t 8 -i input.mp4 out.mp4

Things get a little more interesting when -t and -to are used in conjunction with the -ss flag. Using them together allows us to cut parts in the middle of an input file, but it's important to keep in mind where in the command we place certain flags. For example, if -ss is specified before the input then we need to place -t or -to in the right place, before or after the input, to achieve the desired results. Let's go through the following scenario.

  • Original video is ten seconds
  • Desired output is five seconds
    • Trim two seconds from the beginning
    • Trim three seconds from the end
********** # Original
  *****   # Trimmed

We could structure this command several ways varying the positions of the -ss, -t, and -to flags while achieving the same end result.

ffmpeg -ss 2 -i input.mp4 -t 5 out.mp4
ffmpeg -ss 2 -i input.mp4 -to 5 out.mp4
ffmpeg -ss 2 -t 5 -i input.mp4 out.mp4
ffmpeg -ss 2 -to 7 -i input.mp4 out.mp4
ffmpeg -i input.mp4 -ss 2 -t 5 out.mp4
ffmpeg -i input.mp4 -ss 2 -to 7 out.mp4

All of these commands are similar and result in the same output, but the ordering of the command flags is important. You'll notice that when -ss is specified before the input and -t or -to are specified on the output the value provided is the same. This is because the duration and position are applied to the input that has already been adjusted by seeking to the specified time duration. When both flags are applied to the same side of the command i.e. both on input or output, then the -to position is relative to the original input duration.

I think this post goes to show that while trimming video may be simple on the surface, can find ways to be complicated even for the simplest of problems. There are a lot of other considerations to take into account when trimming video like codec copying and timestamps. I hope this is a good introduction to the problem space and provides a solid platform for you to learn more!

As always thank you for taking the time to read this blog post!