Loop Specific Video Frames with FFmpeg Loop Filter

This guide explains how to use FFmpeg's native loop video filter to repeat a precise sequence of frames directly within an existing video stream. You will learn the exact syntax for the filter, what each parameter controls, how to calculate frame offsets, and how to handle common playback and audio considerations when extending video duration.

The loop Filter Syntax

The loop filter repeats a specified block of frames over a defined number of iterations. The basic syntax is:

-vf "loop=loop=<count>:size=<frames>:start=<frame_index>"

The filter accepts three primary parameters:

  • loop: The number of additional times to repeat the frame sequence. For example, 1 plays the sequence twice (original + 1 repeat). Set to -1 for an infinite loop.
  • size: The total number of consecutive frames in the sequence you want to loop.
  • start: The 0-based index of the first frame where the loop sequence begins.

Step-by-Step Command Example

Suppose you have a 30 fps video, and you want to loop a 2-second sequence (60 frames) starting at the 5-second mark (frame 150), repeating it 3 additional times.

Run the following command:

ffmpeg -i input.mp4 -vf "loop=loop=3:size=60:start=150" -c:v libx264 -c:a copy output.mp4

In this command:

  • start=150: The loop begins at frame 150.
  • size=60: It captures 60 consecutive frames (frames 150 through 209).
  • loop=3: It replays those 60 frames 3 extra times before the rest of the video continues.
  • -c:v libx264: The video stream is re-encoded to apply the filter.

Calculating Frame Numbers

Because the start parameter relies on frame indices rather than timestamps, determine the frame index using your video's frame rate (FPS):

\[\text{Frame Index} = \text{Timestamp (in seconds)} \times \text{Framerate}\]

For a 24 fps video starting at 3.5 seconds:

\[3.5 \times 24 = 84\]

The start value would be 84.

Audio Synchronization Considerations

The loop filter only affects video frames. If your source video contains audio, repeating video frames will cause the video stream to become longer than the audio stream, resulting in desynchronization after the looped section.

To apply a matching loop to the audio stream, use the aloop filter:

ffmpeg -i input.mp4 -filter_complex "[0:v]loop=loop=2:size=60:start=120[v];[0:a]aloop=loop=2:size=96000:start=192000[a]" -map "[v]" -map "[a]" -c:v libx264 -c:a aac output.mp4

Note that aloop calculates size and start in audio samples rather than frames. For a standard 48 kHz audio track:

  • Sample rate \(\times\) start time (seconds) = start sample (\(48000 \times 4 = 192000\)).
  • Sample rate \(\times\) duration (seconds) = size in samples (\(48000 \times 2 = 96000\)).