Cut and Merge Video Segments with FFmpeg Select

This guide explains how to extract multiple disjoint segments from an input video and seamlessly combine them into a single output file using FFmpeg. By leveraging the select video filter and the aselect audio filter alongside timestamp recalculation, you can cut and concatenate various parts of your media in a single command without creating temporary files.

The Basic Syntax

To cut and join multiple segments, define time intervals using the between(t, start, end) function within both the video and audio filtergraphs, joined by the addition operator (+), which acts as a logical OR.

Here is the standard command structure:

ffmpeg -i input.mp4 -vf "select='between(t,10,20)+between(t,45,60)',setpts=N/FRAME_RATE/TB" -af "aselect='between(t,10,20)+between(t,45,60)',asetpts=N/SR/TB" output.mp4

In this example, FFmpeg extracts the segment between 10 and 20 seconds, and the segment between 45 and 60 seconds, merging them into output.mp4.


How the Filters Work

  1. select and aselect:
    • The between(t, start_seconds, end_seconds) expression returns 1 (true) if the current timestamp t falls within the range, and 0 (false) otherwise.
    • Adding multiple between() expressions with + allows the filter to retain frames from any specified range while dropping frames that fall outside them.
  2. setpts=N/FRAME_RATE/TB:
    • Dropping frames creates gaps in Presentation Time Stamps (PTS).
    • Recalculating the PTS using the frame count (N), input frame rate (FRAME_RATE), and time base (TB) generates continuous timestamps, preventing video freezing or playback stutter.
  3. asetpts=N/SR/TB:
    • Functions identically to the video timestamp filter, but for audio.
    • It reconstructs continuous audio timestamps based on the audio sample count (N), sample rate (SR), and time base (TB) to maintain audio-video synchronization.

Selecting More Than Two Segments

To add more segments, simply chain additional between() expressions within the single quotes:

ffmpeg -i input.mp4 -vf "select='between(t,5,15)+between(t,30,40)+between(t,75,90)',setpts=N/FRAME_RATE/TB" -af "aselect='between(t,5,15)+between(t,30,40)+between(t,75,90)',asetpts=N/SR/TB" output.mp4

Selecting Segments by Frame Numbers

If exact time offsets are difficult to calculate or frame accuracy is critical, you can replace the time parameter t with the frame index n (for video only):

ffmpeg -i input.mp4 -vf "select='between(n,100,250)+between(n,500,750)',setpts=N/FRAME_RATE/TB" -af "aselect='between(t,4.17,10.42)+between(t,20.85,31.28)',asetpts=N/SR/TB" output.mp4

Note: The audio filter aselect does not support video frame numbers (n), so audio ranges must still be specified in seconds or sample counts.