How to Use FFmpeg -shortest with Complex Filters

When combining multiple audio and video inputs of varying lengths using FFmpeg’s filter_complex, the output duration can sometimes exceed expectations. This guide explains how to properly apply the -shortest option alongside complex filtergraphs to ensure your output file terminates as soon as the shortest input stream ends, preventing frozen frames or trailing silence.

The Basic Syntax

By default, FFmpeg will continue rendering until all input streams are exhausted. To stop the output when the shortest input ends, place the -shortest flag at the end of your command, right before the output file name.

Here is a standard example of merging a video and an audio file where the audio is longer than the video:

ffmpeg -i video.mp4 -i long_audio.mp3 -filter_complex "[0:v]copy[v];[1:a]copy[a]" -map "[v]" -map "[a]" -shortest output.mp4

In this command, -shortest tells FFmpeg to stop encoding as soon as video.mp4 reaches its end, even if long_audio.mp3 has remaining playtime.

Using Filter-Specific Shortest Parameters

Sometimes, global flags like -shortest do not behave as expected when complex filters process the streams. Certain filters have their own internal parameter to handle stream termination.

The Overlay Filter

If you are overlaying a short video or image onto a longer background video, use the shortest=1 option directly inside the overlay filter:

ffmpeg -i background.mp4 -i logo.png -filter_complex "[0:v][1:v]overlay=10:10:shortest=1[outv]" -map "[outv]" output.mp4

The Amix Filter

If you are mixing multiple audio streams, the amix filter uses the duration parameter. Set this to shortest to stop mixing when the shortest audio input ends:

ffmpeg -i audio1.mp3 -i audio2.mp3 -filter_complex "amix=inputs=2:duration=shortest[outa]" -map "[outa]" output.mp3

Fixing Common Sync and Buffer Issues

A common issue when using -shortest with complex filtergraphs is that the output file still ends up too long, often with a frozen frame at the end. This happens because FFmpeg buffers frames to ensure sync.

To solve this, use the -shortest_buf_duration option. This tells FFmpeg how far ahead (in seconds) it is allowed to buffer before forcing the stream to end. Setting this to a low value like 1.0 or 0.5 usually resolves frozen frame issues:

ffmpeg -i video.mp4 -i audio.mp3 -filter_complex "[0:v]scale=1280:-1[v];[1:a]volume=0.8[a]" -map "[v]" -map "[a]" -shortest -shortest_buf_duration 1.0 output.mp4

By combining the global -shortest flag, filter-specific arguments like shortest=1, and adjusting the buffer duration, you can successfully control the output duration of any FFmpeg complex filtergraph.