Repeat/loop Input Video with ffmpeg?

34

14

I just want to loop a mp4 video with ffmpeg and keep the current settings and codec.

For example if input.mp4 is 0:10 long, and I would want to loop it 4 times so output.mp4 is 0:40 long, how could I change the following command line to do that?

ffmpeg -i input.mp4 -c copy output.mp4

I tried...

ffmpeg -loop 4 -i input.mp4 -c copy output.mp4

...but I get the error "Option loop not found."

Thomas King

Posted 2014-10-27T18:22:50.133

Reputation: 173

Answers

38

Concat demuxer

This allows you to loop an input without needing to re-encode.

  1. Make a text file. Contents of an example text file to repeat 4 times.

    file 'input.mp4'
    file 'input.mp4'
    file 'input.mp4'
    file 'input.mp4'
    
  2. Then run ffmpeg:

    ffmpeg -f concat -i list.txt -c copy output.mp4
    

For Linux users

This example is the same as above but you don't have to manually make list.txt:

for i in {1..4}; do printf "file '%s'\n" input.mp4 >> list.txt; done
ffmpeg -f concat -i list.txt -c copy output.mp4

With most commonly-used modern shells, you can even avoid the creation of the list.txt file entirely. For example, with bash:

ffmpeg -f concat -i <(for i in {1..4}; do printf "file '%s'\n" input.mp4; done) -c copy output.mp4

Also see:


loop filter

Example using the loop filter to loop 4 times, each loop is 75 frames, each loop skips the first 25 frames of the input:

ffmpeg -i input -filter_complex loop=3:75:25 output
  • Filtering requires re-encoding.
  • This filter places all frames into memory.
  • Using loop=3 will loop 4 times.
  • To loop infinitely use -1.
  • You must list the number of frames to loop (shown as 75 in the example above). Max value is 32767.
  • Also see ffmpeg -h filter=loop.

movie filter

The movie filter has a loop option. See answer below by Monah Tuk. Filtering requires re-encoding. For audio use the amovie filter.


-stream_loop option

See answer below by Thingy and answer by Mulvya. Note that this option is buggy (see bug reports #6121 and #5719) and may not work for you. As mentioned by mulvya in ticket #6121 one workaround is to first re-mux to MKV or TS then use -stream_loop in the next command.


-loop option

The -loop option is specific to the image file demuxer and gif muxer, so it can't be used for typical video files, but it can be used to infinitely loop a series of input images. This example will loop over and over but the -t 30 will limit the output duration to 30 seconds:

ffmpeg -loop 1 -i %03d.png -t 30 output.mkv

Or to loop a GIF output:

ffmpeg -i input -loop 3 output.gif

LordNeckbeard

Posted 2014-10-27T18:22:50.133

Reputation: 4 801

Does this work fine with mp4 files?Thomas King 2014-10-28T19:08:12.627

2I get this error &gt; &lt;(for i in {1..4}; do printf "file '%s'\n" input.mp4; done) -bash: /dev/fd/63: Permission deniedJZ11 2015-11-09T18:46:50.250

@jamesfzhang - I think that's because you need an absolute path to the file (as explained here: https://trac.ffmpeg.org/wiki/Concatenate). To fulfill that, you could write: ffmpeg -safe 0 -f concat -i <(for i in {1..4}; do printf "file '$PWD'/'%s'\n" input.mp4; done) -c copy output.mp4

Plenus Franckly 2017-05-18T15:57:46.893

14

At least on FFmpeg 2.8.x (but oldie should works too) you can use lavfi as input format and complex filter graph using movie and setpts filters as a argument for -i option.

Next command doing this work for you:

ffmpeg -re -f lavfi -i "movie=filename=input.mp4:loop=0, setpts=N/(FRAME_RATE*TB)" output.mp4

Zero loop= arguments means infinity loop. Values greater zero sets repeat counts. setpts filters required for PTS adjusting for second and later repeats, otherwise most output muxers will fails with non-monotonic PTS increasing: loop does not recalc PTS.

Note, that using filters assuming that bypass frames without decoding/encoding is impossible: by design filters deals with decoded frames only.

At the FFmpeg 2.8.2 new input option -stream_loop inroduced. I first look it works more simple and allows copy content without transcoding:

ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -y output.mp4

But it does not recalculate PTS and output file is wrong. If you add filter to fix PTS (see setpts) you must remove -c copy too. Only bitstream filters can deals with encoded packets, but there is no any bitstream filters to fix PTS (see: https://ffmpeg.org/ffmpeg-bitstream-filters.html)

In any case ffmpeg on second pass fails with error:

input.mp4: Resource temporarily unavailable

Known work around for me: use container for input file without PTS limits (streaming container). One of them, known me, is MPEG-TS. So, you can simple convert your MP4 file to the MPEG-TS:

ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input.ts

And use next command to compose infinity file:

ffmpeg -re -stream_loop -1 -i input.ts -c copy -strict -2 -bsf:a aac_adtstoasc -y output.mp4

(bitstream filters should be used only if needed, on my samples it is required)

FFmpeg >= 2.8.2 is required in this case.

Monah Tuk

Posted 2014-10-27T18:22:50.133

Reputation: 241

1Running that command gives me error : "[mp4 @ 00000000053fa1a0] Could not find tag for codec rawvideo in stream #0, codec not currently supported in container". If I add -vcodec h264 before the input, that error disappears, but the encoder doesn't exit. Supplying a non-zero loop count produces a lot of errors but does exit. The file is not a valid output.Mulvya 2015-11-18T08:35:28.413

1The documentation for stream_loop says "Loop 0 means no loop, loop -1 means infinite loop."Mulvya 2015-11-18T08:36:47.677

Seems incorrect input files. Could you pleas share it? "Loop 0 means no loop, loop -1 means infinite loop." - seems I see old docs :-)Monah Tuk 2015-11-18T13:43:11.037

Mine were valid MP4s but can't share the ones I used .You can generate one using ffmpeg and then use that. Paste the console output if it works.Mulvya 2015-11-18T14:56:17.887

1I forgot: filters assuming transcoding (decode/encode). By design. So you must remove -c copy. Answer fixed.Monah Tuk 2015-11-18T16:48:45.340

1Nice to know, but that's a significant limitation if you have a large loop to generate.Mulvya 2015-11-18T17:02:13.640

Add info about stream_loop and WA to fix PTS issue without re-encode. FFmpeg >= 2.8.2 is required.Monah Tuk 2015-11-18T17:22:40.500

@MonahTuk I find the loop filter works much better than stream_loop (which causes a brief pause for any file I tried), with one exception: the moment I add the loop filter the audio disappears?Mike Versteeg 2017-06-22T12:56:13.747

@MikeVersteeg, you should check files. Time to time different tracks in file has a little bit different length or offset it can affect muxing. Issues in never versions of FFmpeg also can be occured. Also, most working case - use MPEG TS container as input and output.Monah Tuk 2017-06-23T00:05:28.147

10

With ffmpeg 2.8.4, the following command creates output.mp4 that is a repeating copy of input.mp4 until stopped:

ffmpeg -stream_loop -1 -i input.mp4 -c copy -fflags +genpts output.mp4

Thingy

Posted 2014-10-27T18:22:50.133

Reputation: 136

2Seems to be the fastest methodjosef 2017-01-23T17:43:24.717

Fastest method is an understatement, this method ramps up to multi-hour videos in a matter of seconds.SleighBoy 2018-02-13T23:28:34.613

0

Q: "... how could I change the following command line to do that? ffmpeg -i input.mp4 -c copy output.mp4" ?

A: The simple method that avoids problems of which Commands work with which version is the 'trivial solution':

ffmpeg -i input.mp4 -i input.mp4 -i input.mp4 -i input.mp4 -c copy output.mp4

See also: https://trac.ffmpeg.org/wiki/Concatenate for many examples.

Rob

Posted 2014-10-27T18:22:50.133

Reputation: 524

This does not do any concatenation. At least one of the concat methods has to be used: protocol, filter or demuxer. In this command, ffmpeg's auto mapping will select one video, one audio and one subtitle stream from among the inputs. Since they're identical, it's equivalent to the OP's first command.Mulvya 2017-03-11T06:36:50.477

Thanks for testing that Mulvya, as it differs from the behavior described in the Docs: https://ffmpeg.org/ffmpeg.html#Description - If there's similarity in the File names using "-i -i /tmp/test%d.mp4" (et. al) is also possible.

Rob 2017-03-11T17:28:19.393