18

I have a long video with different scenes in it. I want to extract and concatenate 2 scenes from the video (that do not start on an I-frame) using ffmpeg 2.1.4.

For argument, say I want 5 seconds from 01:00 and 02:00.

I can do this:

ffmpeg -ss 01:00 -i in.mkv -ss 02:00 -i in.mkv -filter_complex "
  [0:v]select='lt(t,5)'[v0];
  [0:a]aselect='lt(t,5)'[a0];
  [v0][a0][1:v][1:a]concat=n=2:v=1:a=1
" -c:a libvorbis -t 10 out.mkv

That gives me the movie I want, but select actually forces ffmpeg to decode the entire rest of the movie. So, how do I tell it to truncate the first movie instead of decoding it?

I would prefer to do this with an ffmpeg complex filter, if possible. I know that I can just use -t to recode separate movies first, but the extra encoding step is very slow in my case and also loses a fair amount of quality for this video.

I can't seem to find a filter that truncates the length of a steam. Are there filter nodes that correspond to the -t or -ss parameters?

2 Answers 2

25

concat filter

This method is best if you need to perform additional filtering:

Use the trim, atrim, setpts, asetpts, and concat filters:

ffmpeg -i input -filter_complex \
"[0:v]trim=60:65,setpts=PTS-STARTPTS[v0]; \
 [0:a]atrim=60:65,asetpts=PTS-STARTPTS[a0]; \
 [0:v]trim=120:125,setpts=PTS-STARTPTS[v1];
 [0:a]atrim=120:125,asetpts=PTS-STARTPTS[a1]; \
 [v0][a0][v1][a1]concat=n=2:v=1:a=1[out]" \
-map "[out]" output.mkv
  • setpts and asetpts will prevent a jerky output due to presentation timestamp issues.

  • Make sure to use a recent version. See the FFmpeg Download page for links to builds for Windows, OS X, and Linux.


concat demuxer

Another method is to to create the segments individually and stream copy them instead of re-encoding (to save time and quality), and join them with the concat demuxer.

$ ffmpeg -ss 60 -i input -t 5 -codec copy clip1.mkv
$ ffmpeg -ss 120 -i input -t 5 -codec copy clip2.mkv
$ echo "file 'clip1.mkv'" > concat.txt
$ echo "file 'clip2.mkv'" >> concat.txt
$ ffmpeg -f concat -i concat.txt -codec copy output.mkv
10
  • 2
    Ah, thanks. trim is what I was missing. However, it takes a very long time to get to the time offset I specify, as if decoding everything up to it. Also, part of the output was missing audio. To fix, I specified the same input multiple times with -ss, then use trim to truncate the video. You don't need setpts in that case, since ss sets pts to 0. That seemed to work and didn't have weird random pauses during encoding. As for copying streams, I tried that before. It starts at the previous I-frame, so you get a different part of the movie than the one you wanted.
    – scubed
    Commented Mar 18, 2014 at 4:05
  • Would you please answer my question it is similar to this one. video.stackexchange.com/questions/18247/…
    – Eftekhari
    Commented Apr 26, 2016 at 15:43
  • Interestingly the -filter_complex works but the concat files doesn't - i.e. the 1st video looks fine but the quality of the 2nd is horrible. Note, I copied these commands exactly for both (except for the input file).
    – bobmarksie
    Commented Aug 13, 2017 at 20:24
  • How can I trim clip by frames and concatenate?
    – puneet18
    Commented Aug 29, 2020 at 21:18
  • @puneet18 Are you using concat filter or concat demuxer?
    – llogan
    Commented Aug 29, 2020 at 22:41
8

This should work faster...

ffmpeg -ss 1:00 -t 5 -i in.mkv -ss 2:00 -t 5 -i in.mkv \
  -filter_complex "[0][1]concat=n=2:v=1:a=1" \ 
  out.mkv

There's no need to specify -t on the output. There's no need to split the audio and video before the concat.

1
  • 2
    This uses the concat filter which will require re-encoding. This may or may not be desired by the user.
    – llogan
    Commented Jun 5, 2015 at 0:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.