Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-04-25T06:52:22.270Z
Answers.Text: Thanks for the suggestions, but when I use the gblur filter and looping, the speed is significantly reduced (3.3 seconds vs 2.3 seconds for a short example). The biggest contributor seems to be the gblur filter (3.2 seconds).
Answers.UserDisplayName: slhck
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-04-25T08:11:34.330Z
Answers.Text: Here, your script takes 41 seconds, and my script takes 7 seconds with gblur and 8 seconds with boxblur. fps for your script is 17 and its 89/86 for my script. So check your usage and logic of my script.
Answers.UserDisplayName: durandal
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-04-25T09:48:41.240Z
Answers.Text: Indeed it works quite well, thanks. I was only referring to the boxblur/gblur difference in my earlier comment. I was able to achieve a 3x speedup now (there are other effects which limit the benefits of your method). What are you implying with the feedback filter?
Answers.UserDisplayName: slhck
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-05-04T15:29:55.620Z
Answers.Text: Accepted for now, thanks for your pointers regarding processing of static images. I would still be curious how the feedback filter could help here?
Answers.UserDisplayName: slhck
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-04-22T16:29:23.450Z
Answers.LastActivityDate: 2022-04-22T16:29:23.450Z
Answers.UserDisplayName: durandal
Body: <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>
  
Tags: <ffmpeg>
Title: Complex filter performance deteriorates with effects on images and multiple overlays
UserDisplayName: slhck
ThreadText: # Complex filter performance deteriorates with effects on images and multiple overlays
  
  (Asked by: username_0 on 2022-04-21)
  
  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:
  
  ```bash
  #!/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](https://storage.googleapis.com/aveq-storage/examples/video.stackexchange.com-ffmpeg-slideshow-complex-filter/images.zip). The output video is [here](https://storage.googleapis.com/aveq-storage/examples/video.stackexchange.com-ffmpeg-slideshow-complex-filter/output.mp4).
  
  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?
  
  **Tags:** ffmpeg
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2022-04-22. Score: 1 | Accepted answer
  
  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
  
  ```
  
  > **Comments:**
  > **username_0**: Thanks for the suggestions, but when I use the gblur filter and looping, the speed is significantly reduced (3.3 seconds vs 2.3 seconds for a short example). The biggest contributor seems to be the gblur filter (3.2 seconds).  
  > **username_1**: Here, your script takes 41 seconds, and my script takes 7 seconds with gblur and 8 seconds with boxblur. fps for your script is 17 and its 89/86 for my script. So check your usage and logic of my script.  
  > **username_0**: Indeed it works quite well, thanks. I was only referring to the boxblur/gblur difference in my earlier comment. I was able to achieve a 3x speedup now (there are other effects which limit the benefits of your method). What are you implying with the feedback filter?  
  > **username_0**: Accepted for now, thanks for your pointers regarding processing of static images. I would still be curious how the feedback filter could help here?  
  
  ---
  
  