Search code examples
ffmpegvideo-streamingstreamingrtmpflv

FFMPEG: Loop multiple videos indefinitely


I've got an interesting setup. I have four videos which are all identical in duration, identical frame rate, and have identical PTS timestamps. I wish to stream these four videos to an RTMP server but keep them synchronized so that someone switching between the streams will not jump forward or back in time, but instead pick up right where they left off.

Here's the command I'm currently using:

ffmpeg \
    -re -stream_loop -1 -fflags +genpts -i 01.mp4 \
    -re -stream_loop -1 -fflags +genpts -i 02.mp4 \
    -re -stream_loop -1 -fflags +genpts -i 03.mp4 \
    -re -stream_loop -1 -fflags +genpts -i 04.mp4 \
    -map 0:v -map 0:a \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/01 \
    -map 1:v -map 1:a \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/02 \
    -map 2:v -map 2:a \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/03 \
    -map 3:v -map 3:a \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/04

This command properly synchronizes the streams and broadcasts all four, however the moment the video ends so does the stream. Due to the -stream_loop -1 I would expect the video to keep looping indefinitely. This is the output to stdout when the stream dies:

[flv @ 0x2392d40] Failed to update header with correct duration.
[flv @ 0x2392d40] Failed to update header with correct filesize.
[flv @ 0x229b980] Failed to update header with correct duration.
[flv @ 0x229b980] Failed to update header with correct filesize.
[flv @ 0x22f3bc0] Failed to update header with correct duration.
[flv @ 0x22f3bc0] Failed to update header with correct filesize.
[flv @ 0x23a4240] Failed to update header with correct duration.
[flv @ 0x23a4240] Failed to update header with correct filesize.
[libx264 @ 0x25ebd00] frame I:236   Avg QP:29.17  size: 20892
[libx264 @ 0x25ebd00] frame P:5412  Avg QP:32.33  size:  1892
[libx264 @ 0x25ebd00] mb I  I16..4: 100.0%  0.0%  0.0%
[libx264 @ 0x25ebd00] mb P  I16..4:  0.2%  0.0%  0.0%  P16..4: 18.5%  0.0%  0.0%  0.0%  0.0%    skip:81.3%
[libx264 @ 0x25ebd00] final ratefactor: 31.62
[libx264 @ 0x25ebd00] coded y,uvDC,uvAC intra: 68.8% 62.8% 34.6% inter: 8.8% 1.8% 0.0%
[libx264 @ 0x25ebd00] i16 v,h,dc,p: 38% 25% 19% 18%
[libx264 @ 0x25ebd00] i8c dc,h,v,p: 40% 22% 27% 11%
[libx264 @ 0x25ebd00] kb/s:515.11
[libspeex @ 0x2537580] 1 frames left in the queue on closing
[libx264 @ 0x2531d00] frame I:236   Avg QP:31.85  size: 15843
[libx264 @ 0x2531d00] frame P:5412  Avg QP:34.95  size:  2086
[libx264 @ 0x2531d00] mb I  I16..4: 100.0%  0.0%  0.0%
[libx264 @ 0x2531d00] mb P  I16..4:  2.8%  0.0%  0.0%  P16..4: 37.8%  0.0%  0.0%  0.0%  0.0%    skip:59.4%
[libx264 @ 0x2531d00] final ratefactor: 32.38
[libx264 @ 0x2531d00] coded y,uvDC,uvAC intra: 48.4% 40.8% 13.5% inter: 12.1% 4.0% 0.0%
[libx264 @ 0x2531d00] i16 v,h,dc,p: 41% 21% 26% 13%
[libx264 @ 0x2531d00] i8c dc,h,v,p: 48% 20% 24%  8%
[libx264 @ 0x2531d00] kb/s:510.33
[libspeex @ 0x2533080] 1 frames left in the queue on closing
[libx264 @ 0x22da600] frame I:236   Avg QP:26.11  size: 13705
[libx264 @ 0x22da600] frame P:5412  Avg QP:29.17  size:  2185
[libx264 @ 0x22da600] mb I  I16..4: 100.0%  0.0%  0.0%
[libx264 @ 0x22da600] mb P  I16..4:  4.5%  0.0%  0.0%  P16..4: 35.2%  0.0%  0.0%  0.0%  0.0%    skip:60.3%
[libx264 @ 0x22da600] final ratefactor: 28.44
[libx264 @ 0x22da600] coded y,uvDC,uvAC intra: 37.1% 40.1% 10.4% inter: 12.3% 6.2% 0.1%
[libx264 @ 0x22da600] i16 v,h,dc,p: 40% 21% 22% 17%
[libx264 @ 0x22da600] i8c dc,h,v,p: 43% 18% 28% 11%
[libx264 @ 0x22da600] kb/s:511.43
[libspeex @ 0x22db080] 1 frames left in the queue on closing
[libx264 @ 0x22d7a00] frame I:236   Avg QP:30.31  size: 13811
[libx264 @ 0x22d7a00] frame P:5412  Avg QP:33.28  size:  2209
[libx264 @ 0x22d7a00] mb I  I16..4: 100.0%  0.0%  0.0%
[libx264 @ 0x22d7a00] mb P  I16..4:  5.4%  0.0%  0.0%  P16..4: 37.4%  0.0%  0.0%  0.0%  0.0%    skip:57.2%
[libx264 @ 0x22d7a00] final ratefactor: 31.52
[libx264 @ 0x22d7a00] coded y,uvDC,uvAC intra: 37.9% 36.7% 9.5% inter: 11.4% 5.0% 0.1%
[libx264 @ 0x22d7a00] i16 v,h,dc,p: 41% 23% 21% 16%
[libx264 @ 0x22d7a00] i8c dc,h,v,p: 45% 19% 27%  9%
[libx264 @ 0x22d7a00] kb/s:516.78
[libspeex @ 0x22d8d80] 1 frames left in the queue on closing

My FFMPEG version:

$ ffmpeg -version
ffmpeg version N-90065-g8a8d0b3 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.5) 20160609
configuration: --prefix=/home/sbarnett/ffmpeg_build --pkg-config-flags=--static --extra-cflags=-I/home/sbarnett/ffmpeg_build/include --extra-ldflags=-L/home/sbarnett/ffmpeg_build/lib --extra-libs='-lpthread -lm' --bindir=/home/sbarnett/bin --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libspeex --enable-nonfree
libavutil      56.  7.101 / 56.  7.101
libavcodec     58. 11.101 / 58. 11.101
libavformat    58.  9.100 / 58.  9.100
libavdevice    58.  1.100 / 58.  1.100
libavfilter     7. 12.100 /  7. 12.100
libswscale      5.  0.101 /  5.  0.101
libswresample   3.  0.101 /  3.  0.101
libpostproc    55.  0.100 / 55.  0.100

How do I get the video to loop indefinitely? Why is -stream_loop -1 not working?

Update (Edited with new error)

Following @Gyan's advice, I attempted to use filter_complex with the movie filter, however I may be doing it incorrectly:

ffmpeg \
    -stream_loop -1 \
    -re -i 01.mp4 \
    -re -i 02.mp4 \
    -re -i 03.mp4 \
    -re -i 04.mp4 \
    -filter_complex \
        "movie=01.mp4:loop=0[v1];[v1]setpts=N/FRAME_RATE/TB[v1];
         amovie=01.mp4:loop=0[a1];[a1]asetpts=N/SR/TB[a1];
         movie=02.mp4:loop=0[v2];[v2]setpts=N/FRAME_RATE/TB[v2];
         amovie=02.mp4:loop=0[a2];[a2]asetpts=N/SR/TB[a2];
         movie=03.mp4:loop=0[v3];[v3]setpts=N/FRAME_RATE/TB[v3];
         amovie=03.mp4:loop=0[a3];[a3]asetpts=N/SR/TB[a3];
         movie=04.mp4:loop=0[v4];[v4]setpts=N/FRAME_RATE/TB[v4];
         amovie=04.mp4:loop=0[a4];[a4]asetpts=N/SR/TB[a4]" \
    -map "[v1]" -map "[a1]" \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/01 \
    -map "[v2]" -map "[a2]" \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/02 \
    -map "[v3]" -map "[a3]" \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/03 \
    -map "[v4]" -map "[a4]" \
        -c:a speex -ar 16000 -ac 1 \
        -c:v libx264 -preset ultrafast \
        -b:v 500k -b:a 32k \
        -f flv rtmp://output/04

This threw the following error:

[libspeex @ 0x23f4d80] nb_samples (325) != frame_size (320) (avcodec_encode_audio2)

Solution

  • stream_loop isn't yet implemented for multiple inputs; you'll have to use the movie filter.

    ffmpeg \
        -filter_complex \
            "movie=01.mp4:loop=0,setpts=N/FRAME_RATE/TB,realtime[v1];
             amovie=01.mp4:loop=0,asetpts=N/SR/TB,arealtime[a1];
             movie=02.mp4:loop=0,setpts=N/FRAME_RATE/TB,realtime[v2];
             amovie=02.mp4:loop=0,asetpts=N/SR/TB,arealtime[a2];
             movie=03.mp4:loop=0,setpts=N/FRAME_RATE/TB,realtime[v3];
             amovie=03.mp4:loop=0,asetpts=N/SR/TB,arealtime[a3];
             movie=04.mp4:loop=0,setpts=N/FRAME_RATE/TB,realtime[v4];
             amovie=04.mp4:loop=0,asetpts=N/SR/TB,arealtime[a4]" \
        -map "[v1]" -map "[a1]" \
            -c:a speex -ar 16000 -ac 1 \
            -c:v libx264 -preset ultrafast \
            -b:v 500k -b:a 32k \
            -f flv rtmp://output/01 \
        -map "[v2]" -map "[a2]" \
            -c:a speex -ar 16000 -ac 1 \
            -c:v libx264 -preset ultrafast \
            -b:v 500k -b:a 32k \
            -f flv rtmp://output/02 \
        -map "[v3]" -map "[a3]" \
            -c:a speex -ar 16000 -ac 1 \
            -c:v libx264 -preset ultrafast \
            -b:v 500k -b:a 32k \
            -f flv rtmp://output/03 \
        -map "[v4]" -map "[a4]" \
            -c:a speex -ar 16000 -ac 1 \
            -c:v libx264 -preset ultrafast \
            -b:v 500k -b:a 32k \
            -f flv rtmp://output/04