Fix FFmpeg Concat Filter Shortest Option Not Working
When concatenating multimedia streams using FFmpeg’s
concat filter, the -shortest command-line
option frequently fails to terminate the output at the end of the
shortest stream, resulting in frozen frames, bloated file sizes, or
indefinite encoding loops. This article explains the underlying causes
of this synchronization failure within FFmpeg's filtergraph architecture
and outlines reliable methods to properly terminate your encoded
media.
Why
-shortest Fails with the Concat Filter
The -shortest option tells the output muxer to stop
writing once the shortest input stream reaches its end-of-file (EOF).
When paired with the concat video/audio filter, several
issues prevent this mechanism from working as expected:
- Filtergraph Abstraction: The
concatfilter operates insidefilter_complex. The output muxer does not monitor the original source files directly; it monitors the synthetic stream generated by the filter. If the filter does not propagate EOF properly or keeps an internal buffer open, the muxer never receives the termination signal. - Muxer Interleaving Buffers: FFmpeg buffers packets to ensure audio and video remain interleaved. If an audio stream finishes but the video concat filter still holds unrendered or buffered frames, the muxer may wait indefinitely for stream closure or overshoot the actual duration.
- Timestamp Inconsistencies: Concatenating segments
with differing frame rates, missing timebases, or non-zero start
Presentation Timestamps (PTS) confuses the internal clock. If the audio
and video timestamps diverge,
-shortestfails to determine which stream actually reached the target end point.
How to Fix the Issue
1. Add
-fflags +shortest and Disable Interleave Delta
Modern versions of FFmpeg include an extended flag to enforce
stricter EOF checks on the shortest stream. Combining this with
-max_interleave_delta 0 forces the muxer to stop buffering
once any stream terminates.
ffmpeg -f concat -safe 0 -i list.txt -i background.mp3 \
-filter_complex "[0:v][0:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" \
-fflags +shortest -max_interleave_delta 0 -shortest output.mp42. Reset Presentation Timestamps (PTS) Before Concatenating
Mismatched timestamps across segments frequently cause the concat
filter to miscalculate the true duration. Reset timestamps on each
segment before passing them to concat:
ffmpeg -i input1.mp4 -i input2.mp4 -i audio.mp3 \
-filter_complex "\
[0:v]setpts=PTS-STARTPTS[v0]; \
[0:a]asetpts=PTS-STARTPTS[a0]; \
[1:v]setpts=PTS-STARTPTS[1]; \
[1:a]asetpts=PTS-STARTPTS[a1]; \
[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" -shortest output.mp43. Use
trim and atrim Filters Instead of
-shortest
If you know the expected duration of your segments, bypass
-shortest entirely. Enforce termination directly inside the
filtergraph using the trim and atrim
filters:
ffmpeg -i video1.mp4 -i video2.mp4 -i audio.mp3 \
-filter_complex "\
[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]; \
[2:a]atrim=0:60,asetpts=PTS-STARTPTS[music]" \
-map "[v]" -map "[music]" -t 60 output.mp44. Switch to the Concat Demuxer
If all input files share the identical codec, resolution, and audio
sample rate, bypass the concat filter entirely by using the
concat demuxer. The demuxer operates at the container level where
-shortest handles EOF signaling much more reliably:
ffmpeg -f concat -safe 0 -i filelist.txt -i audio.mp3 \
-c:v copy -c:a aac -shortest output.mp4