user525: I want to generate a slideshow video that is composed of 1–n input images. Each input image is rendered in the foreground and simultaneously as a blurred background, for a few seconds. The next image will be placed on top of the previous image, and the background changes. Each image should fade in. The background should crossfade.
I've got this working, and the script looks like this:
#!/usr/bin/env bash

ffmpeg \
  -y \
  -hide_banner \
  -f lavfi -i color=black:r=10:s=894x494:d=24 \
  -loop 1 -framerate 10 -i images/trees.jpg \
  -loop 1 -framerate 10 -i images/bridge.jpg \
  -loop 1 -framerate 10 -i images/river.jpg \
  -loop 1 -framerate 10 -i images/woman.jpg \
  -filter_complex "
    [1:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg1];
    [2:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg2];
    [3:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg3];
    [4:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg4];

    [imageBg1][imageBg2]xfade=transition=fade:duration=1:offset=6[imageBgFade1];
    [imageBgFade1][imageBg3]xfade=transition=fade:duration=1:offset=12[imageBgFade2];
    [imageBgFade2][imageBg4]xfade=transition=fade:duration=1:offset=18[imageBgFade3];

    [1:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=0:d=1:alpha=1,rotate=0.03490658503988659:c=none[image1];
    [2:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=6:d=1:alpha=1,rotate=-0.017453292519943295:c=none[image2];
    [3:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=12:d=1:alpha=1,rotate=0.017453292519943295:c=none[image3];
    [4:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=18:d=1:alpha=1,rotate=0:c=none[image4];

    [imageBgFade3][image1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,0,24)'[imageFg1];
    [imageFg1][image2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,6,24)'[imageFg2];
    [imageFg2][image3]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,12,24)'[imageFg3];
    [imageFg3][image4]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,18,24)'[imageFg4];
    [imageFg4]fps=fps=30,format=yuv420p[finalVideo]" \
  -map "[finalVideo]" \
  -t 24 \
  -c:v libx264 \
  -preset ultrafast \
  -crf 28 \
  output.mp4

I am setting up a canvas of a predetermined size, and a rendering framerate of 10 FPS. Here I can achieve a speed of ~2.7⨉. With 30 FPS, the speed drops to 0.9⨉ (which is, understandably, 3⨉ less).
For testing, the images are here. The output video is here.
The problem is that the complexity of the script (i.e., the encoding speed) increases with the number of inputs. The background is not the problem; using xfade means only one image is shown at a particular time. However, the foreground has to perform the overlay calculations for every image, with up to n overlays. Also, the blurring is done for each frame of the image.
I am aware of the fact that even the ffmpeg manual says:

You can chain together more overlays but you should test the efficiency of such approach.

I cannot think of any other way to improve the performance here. Reducing the FPS could work, since everything is static, except that the fades — they will not look smooth anymore.
Any ideas?

user38203: The main cause of slowdown is using boxblur filter on static images that are animated.
Use gblur filter instead, it is generally faster. Also use loop filter to animate static images after heavy processing. About chaining bunch of overlays at end, that can become quite problematic for more images, perhaps using feedback filter from latest ffmpeg version could help, that is still open question.
    ffmpeg -f lavfi -i color=black:r=10:s=894x494:d=24 -framerate 30 -i images/trees.jpg -framerate 30 -i images/bridge.jpg  -framerate 30 -i images/river.jpg   -framerate 30 -i images/woman.jpg   -filter_complex "
    [1:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg1];
    [2:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg2];
    [3:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg3];
    [4:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg4];
    
    [imageBg1][imageBg2]xfade=transition=fade:duration=1:offset=6[imageBgFade1];
    [imageBgFade1][imageBg3]xfade=transition=fade:duration=1:offset=12[imageBgFade2];
    [imageBgFade2][imageBg4]xfade=transition=fade:duration=1:offset=18[imageBgFade3];
    
    [1:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=0.03490658503988659:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=0:d=1:alpha=1[image1];
    [2:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=-0.017453292519943295:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=6:d=1:alpha=1[image2];
    [3:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=0.017453292519943295:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=12:d=1:alpha=1[image3];
    [4:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=0:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=18:d=1:alpha=1[image4];
    
    [imageBgFade3][image1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,0,24)'[imageFg1];
    [imageFg1][image2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,6,24)'[imageFg2];
    [imageFg2][image3]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,12,24)'[imageFg3];
    [imageFg3][image4]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,18,24)'[finalVideo]"   -map "[finalVideo]" -c:v rawvideo x.nut


525: <p>I want to generate a slideshow video that is composed of 1–<em>n</em> input images. Each input image is rendered in the foreground and simultaneously as a blurred background, for a few seconds. The next image will be placed on top of the previous image, and the background changes. Each image should fade in. The background should crossfade.</p>
<p>I've got this working, and the script looks like this:</p>
<pre class="lang-bash prettyprint-override"><code>#!/usr/bin/env bash

ffmpeg \
  -y \
  -hide_banner \
  -f lavfi -i color=black:r=10:s=894x494:d=24 \
  -loop 1 -framerate 10 -i images/trees.jpg \
  -loop 1 -framerate 10 -i images/bridge.jpg \
  -loop 1 -framerate 10 -i images/river.jpg \
  -loop 1 -framerate 10 -i images/woman.jpg \
  -filter_complex &quot;
    [1:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg1];
    [2:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg2];
    [3:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg3];
    [4:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,boxblur=luma_radius=25:chroma_radius=25:luma_power=1[imageBg4];

    [imageBg1][imageBg2]xfade=transition=fade:duration=1:offset=6[imageBgFade1];
    [imageBgFade1][imageBg3]xfade=transition=fade:duration=1:offset=12[imageBgFade2];
    [imageBgFade2][imageBg4]xfade=transition=fade:duration=1:offset=18[imageBgFade3];

    [1:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=0:d=1:alpha=1,rotate=0.03490658503988659:c=none[image1];
    [2:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=6:d=1:alpha=1,rotate=-0.017453292519943295:c=none[image2];
    [3:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=12:d=1:alpha=1,rotate=0.017453292519943295:c=none[image3];
    [4:v]setpts=PTS-STARTPTS,trim=duration=24,settb=AVTB,format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,fade=in:st=18:d=1:alpha=1,rotate=0:c=none[image4];

    [imageBgFade3][image1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,0,24)'[imageFg1];
    [imageFg1][image2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,6,24)'[imageFg2];
    [imageFg2][image3]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,12,24)'[imageFg3];
    [imageFg3][image4]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,18,24)'[imageFg4];
    [imageFg4]fps=fps=30,format=yuv420p[finalVideo]&quot; \
  -map &quot;[finalVideo]&quot; \
  -t 24 \
  -c:v libx264 \
  -preset ultrafast \
  -crf 28 \
  output.mp4
</code></pre>
<p>I am setting up a canvas of a predetermined size, and a rendering framerate of 10 FPS. Here I can achieve a speed of ~2.7⨉. With 30 FPS, the speed drops to 0.9⨉ (which is, understandably, 3⨉ less).</p>
<p>For testing, the images are <a href="https://storage.googleapis.com/aveq-storage/examples/video.stackexchange.com-ffmpeg-slideshow-complex-filter/images.zip" rel="nofollow noreferrer">here</a>. The output video is <a href="https://storage.googleapis.com/aveq-storage/examples/video.stackexchange.com-ffmpeg-slideshow-complex-filter/output.mp4" rel="nofollow noreferrer">here</a>.</p>
<p>The problem is that the complexity of the script (i.e., the encoding speed) increases with the number of inputs. The background is not the problem; using <code>xfade</code> means only one image is shown at a particular time. However, the foreground has to perform the overlay calculations for every image, with up to <em>n</em> overlays. Also, the blurring is done for each frame of the image.</p>
<p>I am aware of the fact that even the ffmpeg manual says:</p>
<blockquote>
<p>You can chain together more overlays but you should test the efficiency of such approach.</p>
</blockquote>
<p>I cannot think of any other way to improve the performance here. Reducing the FPS could work, since everything is static, except that the fades — they will not look smooth anymore.</p>
<p>Any ideas?</p>
 38203: <p>The main cause of slowdown is using boxblur filter on static images that are animated.</p>
<p>Use gblur filter instead, it is generally faster. Also use loop filter to animate static images after heavy processing. About chaining bunch of overlays at end, that can become quite problematic for more images, perhaps using feedback filter from latest ffmpeg version could help, that is still open question.</p>
<pre><code>    ffmpeg -f lavfi -i color=black:r=10:s=894x494:d=24 -framerate 30 -i images/trees.jpg -framerate 30 -i images/bridge.jpg  -framerate 30 -i images/river.jpg   -framerate 30 -i images/woman.jpg   -filter_complex &quot;
    [1:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg1];
    [2:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg2];
    [3:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg3];
    [4:v]format=yuva444p,scale=894:494:force_original_aspect_ratio=increase,crop=894:494,gblur=7,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB[imageBg4];
    
    [imageBg1][imageBg2]xfade=transition=fade:duration=1:offset=6[imageBgFade1];
    [imageBgFade1][imageBg3]xfade=transition=fade:duration=1:offset=12[imageBgFade2];
    [imageBgFade2][imageBg4]xfade=transition=fade:duration=1:offset=18[imageBgFade3];
    
    [1:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=0.03490658503988659:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=0:d=1:alpha=1[image1];
    [2:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=-0.017453292519943295:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=6:d=1:alpha=1[image2];
    [3:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=0.017453292519943295:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=12:d=1:alpha=1[image3];
    [4:v]format=yuva444p,scale=670.5:370.5:force_original_aspect_ratio=decrease,pad=width=894:height=494:x=(ow-iw)/2:y=(oh-ih)/2:color=#00000000,rotate=0:c=none,loop=800:1:0,trim=duration=24,setpts=PTS-STARTPTS,settb=AVTB,fade=in:st=18:d=1:alpha=1[image4];
    
    [imageBgFade3][image1]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,0,24)'[imageFg1];
    [imageFg1][image2]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,6,24)'[imageFg2];
    [imageFg2][image3]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,12,24)'[imageFg3];
    [imageFg3][image4]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2:shortest=1:enable='between(t,18,24)'[finalVideo]&quot;   -map &quot;[finalVideo]&quot; -c:v rawvideo x.nut
</code></pre>
