Insert background image using FFmpeg

5

3

I've just started using FFMpeg and I'm trying to create a video slideshow from images with a background image. The background would not change only the image.

Similar to this:

enter image description here

I have the following

"ffmpeg -framerate 1/5 \
-start_number 1 \
-i "C:/test/%03d.jpg" \
-c:v libx264 \
-r 30 "C:/test/video.mp4"

And that works perfectly to create slideshow with the pictures but when I try to add a background image for each picture using the following command (overlay).

"ffmpeg -framerate 1/5 \
-start_number 1 \
-i "C:/test/%03d.jpg" \
-vf 'movie=C:/test/bg.jpg [over], [in][over] overlay'
-c:v libx264 \
-r 30 "C:/test/video.mp4"

This is my error log:

    ffmpeg version N-69587-g15a8846 Copyright (c) 2000-2015 the FFmpeg developers
  built with gcc 4.9.2 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-

    bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-lzma --enable-decklink --enable-zlib
      libavutil      54. 18.100 / 54. 18.100
      libavcodec     56. 21.102 / 56. 21.102
      libavformat    56. 19.100 / 56. 19.100
      libavdevice    56.  4.100 / 56.  4.100
      libavfilter     5.  9.103 /  5.  9.103
      libswscale      3.  1.101 /  3.  1.101
      libswresample   1.  1.100 /  1.  1.100
      libpostproc    53.  3.100 / 53.  3.100
    Trailing options were found on the commandline.
    Input #0, image2, from 'C:/test/%03d.jpg':
      Duration: 00:00:15.00, start: 0.000000, bitrate: N/A
        Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown), 768x1024 [SAR 1:1 DAR 3:4], 0.20 fps, 0.20 tbr, 0.20 tbn, 0.20 tbc
    At least one output file must be specified

Update from answer:

<cfscript>
    try {
        runtime = createObject("java", "java.lang.Runtime").getRuntime();
        command = '#ffmpegPath#' &
        ' -loop 1' &
        ' -framerate 1' &
        ' -i "C:/test/bg.jpg"' & 
        ' -framerate 1/5 -start_number 1' &
        ' -i "C:/test/%03d.jpg"' & 
        ' -filter_complex "overlay=(W-w)/2:(H-h)/2,format=yuv420p"' &
        ' -c:v libx264' &
        ' -r 30' &
        ' -movflags +faststart' &
        ' -shortest' &
        ' "C:/test/out.mp4"'; 
        process = runtime.exec(#command#);
        results.errorLogSuccess = processStream(process.getErrorStream(), errorLog);
        results.resultLogSuccess = processStream(process.getInputStream(), resultLog);
        results.exitCode = process.waitFor();
    }
    catch(exception e) {
        results.status = e;    
    }
</cfscript>

Yannick

Posted 2015-02-10T19:58:34.833

Reputation: 127

You're missing one backslash after the -vf line. That's why ffmpeg tells you that there are trailing options (-vf) and no output file. But even then it wouldn't work, as you need a complex filtergraph, and you need to position the overlay correctly. – slhck – 2015-02-10T20:11:00.927

Answers

6

Slideshow with static image background

pug life

You don't need to use the movie source filter, and use -filter_complex instead of -vf.

ffmpeg \
-loop 1 \
-framerate 1 \
-i bg.jpg \
-framerate 1/5 \
-i "C:/test/%03d.jpg" \
-filter_complex "overlay=(W-w)/2:(H-h)/2:shortest=1,format=yuv420p" \
-c:v libx264 \
-r 30 \
-movflags +faststart \
output.mp4
  • format=yuv420p will ensure a widely compatible "pixel format" or chroma subsampling scheme which is useful to add when using libx264.

  • -movflags +faststart will relocate some data after encoding is finished which will allow viewers to begin playback before the file is completely downloaded. Useful for example if you're hosting it yourself and putting it on a web site.

With audio

ffmpeg \
-loop 1 \
-framerate 1 \
-i bg.jpg \
-framerate 1/5 \
-i "C:/test/%03d.jpg" \
-i audio.mp3 \
-filter_complex "overlay=(W-w)/2:(H-h)/2:shortest=1,format=yuv420p" \
-c:v libx264 \
-r 30 \
-c:a aac -strict experimental \
-b:a 192k \
-movflags +faststart \
-shortest
output.mp4

With text

Text can be added with the drawtext filter.

ffmpeg \
-loop 1 \
-framerate 1 \
-i bg.jpg \
-framerate 1/5 \
-i "C:/test/%03d.jpg" \
-i audio.mp3 \
-filter_complex "overlay=(W-w)/2:(H-h)/2:shortest=1,drawtext=fontsize=30:fontfile=FreeSerif.ttf:text='hello world':x=(w-text_w)/2:y=10,format=yuv420p" \
-c:v libx264 \
-r 30 \
-c:a aac -strict experimental \
-b:a 192k \
-movflags +faststart \
-shortest \
output.mp4

See the drawtext filter documentation for many more options.

With a border

The drawbox filter can be used to draw a white border around the overlaid image. Notice that I started naming the inputs and outputs from each filter, then I referenced the final filter results with -map.

ffmpeg \
-loop 1 \
-framerate 1 \
-i bg.jpg \
-framerate 1/5 \
-i "C:/test/%03d.jpg" \
-i audio.mp3 \
-filter_complex "[1:v]drawbox=t=5:c=white[fg];[0:v][fg]overlay=(W-w)/2:(H-h)/2:shortest=1,drawtext=fontsize=30:fontfile=FreeSerif.ttf:text='hello world':x=(w-text_w)/2:y=10,format=yuv420p[v]" \
-map "[v]"
-map 0:a
-c:v libx264 \
-r 30 \
-c:a aac -strict experimental \
-b:a 192k \
-movflags +faststart \
-shortest \
output.mp4

Also see

llogan

Posted 2015-02-10T19:58:34.833

Reputation: 31 929

Thanks so much for the great answer. I've updated my question with the answer you gave me but when I run the command it never ends and the size of the file just gets bigger. I have to kill the process. Can you check if I made a mistake (see Update from answer). – Yannick – 2015-02-10T21:44:58.340

@Yannick Does it work as expected if you run ffmpeg manually via command line? – llogan – 2015-02-10T21:55:05.183

Yes @LordNeckbeard as you can see http://screencast.com/t/LYqd0KNoMjX

– Yannick – 2015-02-10T22:10:47.467

1@Yannick. I forgot to use the shortest=1 option in overlay. This is needed because I made you loop your background image, and by default overlay will not end when the shortest input ends. Answer has been updated. – llogan – 2015-02-11T00:32:35.160

got this error: [Parsed_drawtext_1 @ 0x26b4000] Could not load font "FreeSerif.ttf": cannot open resource [AVFilterGraph @ 0x263fa00] Error initializing filter 'drawtext' with args 'fontsize=30:fontfile=FreeSerif.ttf:text=hello world:x=(w-text_w)/2:y=10' Error initializing complex filters. Invalid argument – NineCattoRules – 2017-03-03T18:04:52.187

1@NineCattoRules You need to point fontfile option to a font file available on your computer. You may need to use the full path, such as /usr/share/fonts/TTF/DejaVuSans.ttf. – llogan – 2017-03-03T18:10:40.973

@LordNeckbeard thanks for helping out with ffmpeg media queries. Can you have a look at https://stackoverflow.com/questions/51192759/ffmpeg-add-background-image-during-the-process-of-video-creation

– Killer – 2018-07-05T13:37:40.160

@Killer I was away for several weeks. Looks like you got an answer. – llogan – 2018-07-17T19:33:36.887

@LordNeckbeard i have almost done like you however there are some image drop. Please have a look https://stackoverflow.com/questions/51520915/ffmpeg-frame-drop-when-merging-a-image-sequence-and-overlaying-during-video-crea

– Killer – 2018-07-27T09:33:15.023