Search code examples
androidffmpegmediavideo-processing

FFMpeg: Add background image during the process of video creation


In reference to my previous question FFMpeg: merge images with audio for specific duration I have successfully merged few images with audio for specific duration by using following command.

ffmpeg \
-y \
-f concat \
-safe 0 \
-r 1/5 \
-i concat.txt \
-i audio.ogg \
-c:v libx264 \
-profile:v high \
-crf 17 \
-preset ultrafast \
-strict experimental \
-t 15 \
output.mp4

In order to add a background image, I tried to use https://superuser.com/a/876275/299733 and other solutions that exist on the web. But the given solution doesn't overlay my images properly and I was getting black video throughout the duration. Therefore, I encode the resultant video from earlier command once again via :

ffmpeg \
-y \
-loop 1 \
-i bg.jpg \
-i output.mp4 \
-filter_complex "overlay=(W-w)/2:(H-h)/2:shortest=1,format=yuv420p" \
-c:v libx264 \
-profile:v high \
-crf 17 \
-preset ultrafast \
-strict experimental \
-t 15 \
output2.mp4

Now, I am able to get the desired result. Is there any way to merge both requests into a single pass? Or a better way without loss of any performance?

Additional details:

concat.txt

file '/home/shubham/Desktop/FFMpeg/image_1.jpg'
file '/home/shubham/Desktop/FFMpeg/image_2.jpg'
file '/home/shubham/Desktop/FFMpeg/image_3.jpg'

Based on @gyan response

Updated concat.xml:

file '/home/shubham/Desktop/FFMpeg/image_4.jpg'
duration 5
file '/home/shubham/Desktop/FFMpeg/image_5.jpg'
duration 5
file '/home/shubham/Desktop/FFMpeg/image_6.jpg'
duration 5
file '/home/shubham/Desktop/FFMpeg/image_6.jpg'

Updated Command:

ffmpeg \
-y \
-loop 1 \
-i bg.jpg \
-f concat \
-safe 0 \
-i concat.txt \
-i audio.ogg \
-filter_complex "[1]fps=25[v];[0][v]overlay=(W-w)/2:(H-h)/2:shortest=1,format=yuv420p" \
-c:v libx264 \
-profile:v high \
-crf 17 \
-preset ultrafast \
-strict experimental \
-t 15 \
output.mp4

The problem is that when images are of different resolution or even for the same resolution the images are skipped. And most of the times last image is shown. However, there are no criteria of which image is selected and which one is skipped. SAMPLE: https://drive.google.com/file/d/1JxCsV2eudKzdgWWuefXqdaWPaBf9Dzzd/view?usp=sharing

However, if I repeatedly used the same image or copy the image and rename it. In both the cases, I get proper images on the background without any skipping.

EDIT: 09 JULY 2018

As @gyan stated in comments: Convert each image to same resolution and type. I check the info of images. via

 ffmpeg -i image_X.jpg

And found out two images have different encoding:

Image 1: Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown), 640x480 [SAR 72:72 DAR 4:3], 25 tbr, 25 tbn, 25 tbc

Image 2: Stream #0:0: Video: mjpeg, yuvj444p(pc, bt470bg/unknown/unknown), 640x480 [SAR 72:72 DAR 4:3], 25 tbr, 25 tbn, 25 tbc

Which is the possible cause of the failure in merging.


Solution

  • Use

    ffmpeg \
    -y \
    -loop 1 \
    -i bg.jpg \
    -f concat \
    -safe 0 \
    -r 1/5 \
    -i concat.txt \
    -i audio.ogg \
    -filter_complex "[1]fps=25[v];[0][v]overlay=(W-w)/2:(H-h)/2:shortest=1,format=yuv420p" \
    -c:v libx264 \
    -profile:v high \
    -crf 17 \
    -preset ultrafast \
    -strict experimental \
    -t 15 \
    output.mp4
    

    The concat demuxer registers the properties of its first input, like codec, resolution, timebase..etc as its demuxed stream property. So, for reliable results, all inputs should have the same properties.