To loop a video with FFmpeg, put -stream_loop N before the -i it applies to. N is the number of extra plays, so -stream_loop 3 gives you four plays, -stream_loop -1 loops forever, and you stop the infinite version with -t . That is the whole trick; the rest of this post is about the three ways it quietly goes wrong and a small pytest suite that catches them.
Everything below was run on November 12, 2026 with Homebrew FFmpeg 9.0.1 on macOS against a real 10.04-second clip (720x1280, 24 fps, AAC audio): the public cat example from Voor's Bad Times AI page . Any short MP4 works the same way.
The three commands
Loop a fixed number of times, no re-encode:
# 3 plays in total = 2 extra plays ffmpeg -stream_loop 2 -i clip.mp4 -c copy -movflags +faststart clip_x3.mp4
Enter fullscreen mode
Exit fullscreen mode
Loop to an exact length (re-encode so the cut lands on a frame, not on a packet):
ffmpeg -stream_loop -1 -i clip.mp4 -t 30 \ -c:v libx264 -pix_fmt yuv420p -crf 20 -preset veryfast \ -c:a aac -b:a 160k…