FFmpeg PNG overlayed on background image to video - ffmpeg

I'm trying to overlay an image on a background image and make a video from it with a certain duration.
I found something on some old 2011 thread but FFmpeg doesn't seem to find '-loop_input' so I guess it's an outdated command.
ffmpeg -loop_input -f image2 -i background.png -r 25 -vframes 250 -an -vcodec png test.mov
How do I make this work in the current ffmpeg version?

Use the -loop option for the image demuxer:
ffmpeg -loop 1 -i background.png -frames:v 250 -c:v png test.mov
But because you are going from PNG to PNG you can stream copy it:
ffmpeg -loop 1 -i background.png -frames:v 250 -c:v copy test2.mov
Default frame rate is 25, so I removed the -r 25. If you want to set frame rate with image inputs then use the image demuxer -framerate input option, such as ffmpeg -loop 1 -framerate 24 -i background.png ...
Your input has no audio, so I removed -an.
-f image2 is not needed: it will automatically determine the proper demuxer.

Related

How to convert video to gif and mp3 that sync using ffmpeg?

I want to convert video to gif with audio. The two should match when played at the same time.
The command I use somehow generates results that's a bit off.
To create gif:
ffmpeg -ss 00:00:10 -i input.mp4 -t 4 -pix_fmt rgb24 -r 10 -filter:v "scale=-1:300" out.gif
To create mp3:
ffmpeg -ss 00:00:10 -i input.mp4 -t 4 out.mp3
I'm guessing this has something to do with the slicing.
Untested: You could try one of these two options below. If still not working then please provide a short clip (MP4 link) that can be tested to give you required solution...
Option 1) Try using -itsoffset instead of -t...
ffmpeg -ss 00:00:10 -itsoffset 4 -i input.mp4 -pix_fmt rgb24 -r 10 -filter:v "scale=-1:300" out.gif
ffmpeg -ss 00:00:10 -itsoffset 4 -i input.mp4 out.mp3
Option 2) Avoid issue of non-matching times for keyframes (of video track vs audio track)...
First trim the video (get's whatever audio is available at nearest video keyframe to your time):
ffmpeg -ss 00:00:10 -i input.mp4 -t 4 trimmed.mp4
Then use trimmed MP4 (will have synced audio) as source for your output GIF and MP3.
ffmpeg -i trimmed.mp4 -pix_fmt rgb24 -r 10 -filter:v "scale=-1:300" out.mp4
ffmpeg -i trimmed.mp4 out.mp3

FFmpeg | Option loop not found

The loop option is not working with gif image.
When I'm working with png image the code good.
But when I'm working with animated gif image the error is thrown Option loop not found.
In my example I'm trying to create the video from input image with specific duration.
ffmpeg -loop 1 -t 5 -i 15324210315b56e3a78abe5.png -i watermark.png -filter_complex "[0]scale=trunc(iw/2)*2:trunc(ih/2)*2[v];[v][1]overlay=x=(W-w-10):y=(H-h-10)" output.mp4
Below command is not working
ffmpeg -loop 1 -t 5 -i 15323488345b55c9a2b2908.gif -i watermark.png -filter_complex "[0]scale=trunc(iw/2)*2:trunc(ih/2)*2[v];[v][1]overlay=x=(W-w-10):y=(H-h-10)" output.mp4
GIFs are handled by a seperate demuxer module, not the generic image sequence demuxer. The gif demuxer has a separate option. See command below.
ffmpeg -ignore_loop 0 -t 5 -i 15323488345b55c9a2b2908.gif ...
The python script for gif to video conversion using ffmpeg library
f"/opt/ffmpeglib/ffmpeg -ignore_loop 0 -i {lambda_file_path} -c:v libx264 -t 10 -pix_fmt yuv420p {lambda_output_file_path}

How to create a video from images with FFmpeg?

ffmpeg -r 1/5 -start_number 2 -i img%03d.png -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
This line worked fine but I want to create a video file from images in another folder.
Image names in my folder are:
img001.jpg
img002.jpg
img003.jpg
...
How could I input images files from a different folder? Example: C:\mypics
I tried this command but ffmpeg generated a video with the first image (img001.jpg) only.
ffmpeg -r 1/5 -start_number 0 -i C:\myimages\img%03d.png -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
-pattern_type glob
This great option makes it easier to select the images in many cases.
Normal speed video with one image per frame at 30 FPS
ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
-c:v libx264 -pix_fmt yuv420p out.mp4
Here's what it looks like:
GIF generated with: https://askubuntu.com/questions/648603/how-to-create-an-animated-gif-from-mp4-video-via-command-line/837574#837574
Add some audio to it:
ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
-i audio.ogg -c:a copy -shortest -c:v libx264 -pix_fmt yuv420p out.mp4
Result: https://www.youtube.com/watch?v=HG7c7lldhM4
These are the test media I've used:
wget -O opengl-rotating-triangle.zip https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.zip?raw=true
unzip opengl-rotating-triangle.zip
cd opengl-rotating-triangle
wget -O audio.ogg https://upload.wikimedia.org/wikipedia/commons/7/74/Alnitaque_%26_Moon_Shot_-_EURO_%28Extended_Mix%29.ogg
Images generated with: How to use GLUT/OpenGL to render to a file?
It is cool to observe how much the video compresses the image sequence way better than ZIP as it is able to compress across frames with specialized algorithms:
opengl-rotating-triangle.mp4: 340K
opengl-rotating-triangle.zip: 7.3M
Convert one music file to a video with a fixed image for YouTube upload
Answered at: https://superuser.com/questions/700419/how-to-convert-mp3-to-youtube-allowed-video-format/1472572#1472572
Slideshow video with one image per second
ffmpeg -framerate 1 -pattern_type glob -i '*.png' \
-c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
Add some music to it, cutoff when the presumably longer audio when the images end:
ffmpeg -framerate 1 -pattern_type glob -i '*.png' -i audio.ogg \
-c:a copy -shortest -c:v libx264 -r 30 -pix_fmt yuv420p out.mp4
Here are two demos on YouTube:
https://www.youtube.com/watch?v=grV64VE1U6c
https://www.youtube.com/watch?v=_6D05gCWh_I
Be a hippie and use the Theora patent-unencumbered video format in an OGG container:
ffmpeg -framerate 1 -pattern_type glob -i '*.png' -i audio.ogg \
-c:a copy -shortest -c:v libtheora -r 30 -pix_fmt yuv420p out.ogv
Your images should of course be sorted alphabetically, typically as:
0001-first-thing.jpg
0002-second-thing.jpg
0003-and-third.jpg
and so on.
I would also first ensure that all images to be used have the same aspect ratio, possibly by cropping them with imagemagick or nomacs beforehand, so that ffmpeg will not have to make hard decisions. In particular, the width has to be divisible by 2, otherwise conversion fails with: "width not divisible by 2".
Full realistic slideshow case study setup step by step
There's a bit more to creating slideshows than running a single ffmpeg command, so here goes a more interesting detailed example inspired by this timeline.
Get the input media:
mkdir -p orig
cd orig
wget -O 1.png https://upload.wikimedia.org/wikipedia/commons/2/22/Australopithecus_afarensis.png
wget -O 2.jpg https://upload.wikimedia.org/wikipedia/commons/6/61/Homo_habilis-2.JPG
wget -O 3.jpg https://upload.wikimedia.org/wikipedia/commons/c/cb/Homo_erectus_new.JPG
wget -O 4.png https://upload.wikimedia.org/wikipedia/commons/1/1f/Homo_heidelbergensis_-_forensic_facial_reconstruction-crop.png
wget -O 5.jpg https://upload.wikimedia.org/wikipedia/commons/thumb/5/5a/Sabaa_Nissan_Militiaman.jpg/450px-Sabaa_Nissan_Militiaman.jpg
wget -O audio.ogg https://upload.wikimedia.org/wikipedia/commons/7/74/Alnitaque_%26_Moon_Shot_-_EURO_%28Extended_Mix%29.ogg
cd ..
# Convert all to PNG for consistency.
# https://unix.stackexchange.com/questions/29869/converting-multiple-image-files-from-jpeg-to-pdf-format
# Hardlink the ones that are already PNG.
mkdir -p png
mogrify -format png -path png orig/*.jpg
ln -P orig/*.png png
Now we have a quick look at all image sizes to decide on the final aspect ratio:
identify png/*
which outputs:
png/1.png PNG 557x495 557x495+0+0 8-bit sRGB 653KB 0.000u 0:00.000
png/2.png PNG 664x800 664x800+0+0 8-bit sRGB 853KB 0.000u 0:00.000
png/3.png PNG 544x680 544x680+0+0 8-bit sRGB 442KB 0.000u 0:00.000
png/4.png PNG 207x238 207x238+0+0 8-bit sRGB 76.8KB 0.000u 0:00.000
png/5.png PNG 450x600 450x600+0+0 8-bit sRGB 627KB 0.000u 0:00.000
so the classic 480p (640x480 == 4/3) aspect ratio seems appropriate.
Do one conversion with minimal resizing to make widths even (TODO
automate for any width, here I just manually looked at identify output and reduced width and height by one):
mkdir -p raw
convert png/1.png -resize 556x494 raw/1.png
ln -P png/2.png png/3.png png/4.png png/5.png raw
ffmpeg -framerate 1 -pattern_type glob -i 'raw/*.png' -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p raw.mp4
This produces terrible output, because as seen from:
ffprobe raw.mp4
ffmpeg just takes the size of the first image, 556x494, and then converts all others to that exact size, breaking their aspect ratio.
Now let's convert the images to the target 480p aspect ratio automatically by cropping as per ImageMagick: how to minimally crop an image to a certain aspect ratio?
mkdir -p auto
mogrify -path auto -geometry 640x480^ -gravity center -crop 640x480+0+0 png/*.png
ffmpeg -framerate 1 -pattern_type glob -i 'auto/*.png' -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p auto.mp4
So now, the aspect ratio is good, but inevitably some cropping had to be done, which kind of cut up interesting parts of the images.
The other option is to pad with black background to have the same aspect ratio as shown at: Resize to fit in a box and set background to black on "empty" part
mkdir -p black
mogrify -path black -thumbnail 640x480 -background black -gravity center -extent 640x480 png/*.png
ffmpeg -framerate 1 -pattern_type glob -i 'black/*.png' -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p black.mp4
Generally speaking though, you will ideally be able to select images with the same or similar aspect ratios to avoid those problems in the first place.
About the CLI options
Note however that despite the name, -glob this is not as general as shell Glob patters, e.g.: -i '*' fails: https://trac.ffmpeg.org/ticket/3620 (apparently because filetype is deduced from extension).
-r 30 makes the -framerate 1 video 30 FPS to overcome bugs in players like VLC for low framerates: VLC freezes for low 1 FPS video created from images with ffmpeg Therefore it repeats each frame 30 times to keep the desired 1 image per second effect.
Next steps
You will also want to:
cut up the part of the audio that you want before joining it: Cutting the videos based on start and end time using ffmpeg
ffmpeg -i in.mp3 -ss 03:10 -to 03:30 -c copy out.mp3
Alternatively, you can also cut it directly in the conversion command by adding the -ss just before the audio -i:
ffmpeg -framerate 1 -pattern_type glob -i 'raw/*.png' -ss 0:36 -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p raw.mp4
TODO: learn to cut and concatenate multiple audio files into the video without intermediate files, I'm pretty sure it's possible:
ffmpeg cut and concat single command line
https://video.stackexchange.com/questions/21315/concatenating-split-media-files-using-concat-protocol
https://superuser.com/questions/587511/concatenate-multiple-wav-files-using-single-command-without-extra-file
Different duration for each image
https://video.stackexchange.com/questions/23530/use-ffmpeg-to-create-a-video-from-a-few-images gives a solution.
You create a file in.txt like:
file png/1.png
outpoint 5
file png/2.png
outpoint 2
file png/3.png
outpoint 7
and outpoint sets the duration of the previous image in seconds.
Then we just remove -framerate from the previous conversion commands:
ffmpeg -f concat -i in.txt -framerate 1 -i orig/audio.ogg -c:v libx264 -c:a copy -shortest -r 30 -pix_fmt yuv420p black.mp4
I also like that that approach with file names in a file is nicer than having to rename the input files to have the correct order, which makes it easier to quickly reorder images on a text editor (multiple -i did not work). Having two lines per input file makes that a bit more annoying, I didn't manage to combine the file and outpoint into a single line, but still, good to know.
This approach is also convenient if you are just going to convert a subset of your images. Then, to save time on the ImageMagick, you can reuse that in.txt file to loop over only the images you care about:
grep -E '^file ' in.txt | sed -E 's/^file //; s/\..*//' | while read f; do
echo $f
convert -thumbnail 1280x720 -background black -gravity center -extent 1280x720 "$(command ls -1 ../$f.* | grep -v .xcf | head -n1)" "out/$f.jpg"
done
Tested on
ffmpeg 3.4.4, vlc 3.0.3, Ubuntu 18.04.
Bibliography
http://trac.ffmpeg.org/wiki/Slideshow official wiki
See the Create a video slideshow from images – FFmpeg
If your video does not show the frames correctly If you encounter problems, such as the first image is skipped or only shows for one frame, then use the fps video filter instead of -r for the output framerate
ffmpeg -r 1/5 -i img%03d.png -c:v libx264 -vf fps=25 -pix_fmt yuv420p out.mp4
Alternatively the format video filter can be added to the filter chain to replace -pix_fmt yuv420p like "fps=25,format=yuv420p". The advantage of this method is that you can control which filter goes first
ffmpeg -r 1/5 -i img%03d.png -c:v libx264 -vf "fps=25,format=yuv420p" out.mp4
I tested below parameters, it worked for me
"e:\ffmpeg\ffmpeg.exe" -r 1/5 -start_number 0 -i "E:\images\01\padlock%3d.png" -c:v libx264 -vf "fps=25,format=yuv420p" e:\out.mp4
below parameters also worked but it always skips the first image
"e:\ffmpeg\ffmpeg.exe" -r 1/5 -start_number 0 -i "E:\images\01\padlock%3d.png" -c:v libx264 -r 30 -pix_fmt yuv420p e:\out.mp4
making a video from images placed in different folders
First, add image paths to imagepaths.txt like below.
# this is a comment details https://trac.ffmpeg.org/wiki/Concatenate
file 'E:\images\png\images__%3d.jpg'
file 'E:\images\jpg\images__%3d.jpg'
Sample usage as follows;
"h:\ffmpeg\ffmpeg.exe" -y -r 1/5 -f concat -safe 0 -i "E:\images\imagepaths.txt" -c:v libx264 -vf "fps=25,format=yuv420p" "e:\out.mp4"
-safe 0 parameter prevents Unsafe file name error
Related links
FFmpeg making a video from images placed in different folders
FFMPEG An Intermediate Guide/image sequence
Concatenate – FFmpeg
Simple Version from the Docs
Works particularly great for Google Earth Studio images:
ffmpeg -framerate 24 -i Project%03d.png Project.mp4
cat *.png | ffmpeg -f image2pipe -i - output.mp4
from wiki
Your files should be named depth_00001.png depth_00002.png etc which ensures the correct order
step 1) If they are called depth_1.png depth_2.png then you can batch rename them to the required naming with this command
for f in depth_[0-9]*; do mv "$f" "$(printf 'depth_%05d' "${f#depth_}" 2> /dev/null)"; done; for f in depth_[0-9]*; do mv "$f" "$f.png"; done;
step 2) Then run ffmpeg using standard options
ffmpeg -framerate 30 -i depth_%05d.png -pix_fmt yuv420p -c:v libx264 depth.mp4
step 3) If that fails (it did for me on Windows) then try this instead
cat depth_*.png | ffmpeg -f image2pipe -framerate 30 -i - -pix_fmt yuv420p -c:v libx264 depth.mp4
NOTE: step 2 failed when I used PNGs - but when I used image magick to convert the PNGs to JPGs step 2 worked
Here's the command I used to do the conversion
for image in *.png; do magick convert "$image" "${image%.*}.jpg"; done;
Also, I found this command useful to verify that the length of the output video was as expected
ffprobe -v quiet -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 depth.mp4
As the glob command is not available on windows, because its a POSIX implementation, the workaround is to use sequence as a pattern. For this to work, one needs to rename their files with sequence numbers - like
gym01.jpg
gym02.jpg
...
Then we can use the command below on Windows - NOTE the gym%02d.jpg, where if your sequence contains more than 2 chars (eg, gym00001.jpg), change it accordingingly (gym%05d.jpg)
ffmpeg -framerate 1 -pattern_type sequence -i gym%02d.jpg -s:v 1920x1080 -c:v libx264 -pix_fmt yuv420p out.mp4
To create frames from video:
ffmpeg\ffmpeg -i %video% test\thumb%04d.jpg -hide_banner
Optional: remove frames you don't want in output video
(more accurate than trimming video with -ss & -t)
Then create video from image/frames eg.:
ffmpeg\ffmpeg -framerate 30 -start_number 56 -i test\thumb%04d.jpg -vf format=yuv420p test/output.mp4
For me to create video with audio it worked, you need to specify:
the normal frames: -framerate 30
the audio -i audio/audio.ogg
and the library libx264
system("ffmpeg -framerate 30 -i #{out_dir}/%03d.png -i audio/audio.ogg
-c:a copy -shortest -c:v libx264 -pix_fmt yuv420p out/final
/#{out_dir.sub("out/", "")}.mp4")
if you want to create a loop, for example 3 times -stream_loop 2 because of 0,1,2
system("ffmpeg -stream_loop 2 -framerate 30 -i
#{out_dir}/%03d.png -i audio/audio.ogg -c:a copy -shortest -c:v
libx264 -pix_fmt yuv420p -b:v 50M out/final/#{out_dir.sub("out/",
"")}.mp4")
I found this helpful and tried it
ffmpeg -framerate 1 -pattern_type glob -i '*.jpg' -c:v libx264 -r 30 -pix_fmt yuv420p output.mp4
Source : https://shotstack.io/learn/use-ffmpeg-to-convert-images-to-video/

Ffmpeg video overlay

I am trying to create a video output from multiple video cameras.
Following the example given here Presenting more than 2 videos using FFmpeg
and other similar examples.
but Im getting the error
Output pad "default" for the filter "src" of type "buffer" not connected to any destination
when i run
ffmpeg -i /dev/video1 -i /dev/video0 -filter_complex "[0:0]pad=iw*2:ih[a];[a][1:0]overlay=w[b];[b][2:0]overlay=w:h" -shortest output.mp4
Im not really sure what this means or how to fix it.
Any help would be greatly appreciated!
Thanks.
When using the "padding" option, you have to specify which is the size of the output image and where you want to put the input image
[0:0]pad=iw*2:ih:0:0
tested under windows 7 with file of same size
ffmpeg -i out.avi -i out.avi -filter_complex "[0:0]pad=iw*2:ih:0:0[a];[a][1:0]overlay=w" -shortest output.mp4
and with WebCam Cap (vfwcap) and a still picture (as i have only o=1 WebCam). BTW you can see how to scale one the source to fit in the target (just in case your source have different resolution)
ffmpeg -y -f vfwcap -r 10 -i 0 -loop 1 -i photo.jpg -filter_complex "[0:0]pad=iw*2:ih:0:0[a];[1:0]scale=640:480[b];[a][b]overlay=w" -shortest output.mp4
under Linux:
ffmpeg -i /dev/video1 -i /dev/video0 -filter_complex "[0:0]pad=iw*2:ih:0:0[[a];a][1:0]overlay=w" -shortest output.mp4
if it doesn't work test a simple record of video 1 and after of video 0 and check their properties (type, resolution, fps).
ffmpeg -i /dev/video1 -shortest output1.mp4
ffmpeg -I output1.mp4
If you still have issue, update your question with ffmpeg console output (as text) for video and video 0 capture and also of the call with the overlay

Overlay animated images with transparency over a static background image using ffmpeg?

I'm looking to create a video using a set of png images that have transparency merged with a static background.
After doing a lot of digging I seems like it's definitely possible by using the filters library.
My initial video making without including the background is:
ffmpeg -y -qscale 1 -r 1 -b 9600 -loop -i bg.png -i frame_%d.png -s hd720 testvid.mp4
Using -vf I can apply the background as overlay:
ffmpeg -y -qscale 1 -r 1 -b 9600 -i frame_%d.png -vf "movie=bg.png [wm];[in][wm] overlay=0:0 [out]" -s hd720 testvid.mp4
However the problem is it's overlaying the background over the input. According libacfilter I can split the input and play with it's content. I'm wondering if I can somehow change the overlay order?
Any help greatly appreciated!
UPDATE 1:
I'm trying to make the following filter work but I'm getting the movie without the background:
ffmpeg -y -qscale 1 -r 1 -b 9600 -i frame_%d.png -vf "movie=bg.png [bg]; [in] split [T1], fifo, [bg] overlay=0:0, [T2] overlay=0:0 [out]; [T1] fifo [T2]" -s hd720 testvid.mp4
UPDATE 2:
Got video making using -vf option. Just piped the input slit it applied image over it and overlayed the two split feeds! Probably not the most efficient way... but it worked!
ffmpeg -y -r 1 -b 9600 -i frame_%d.png -vf "movie=bg.png, scale=1280:720:0:0 [bg]; [in] format=rgb32, split [T1], fifo, [bg] overlay=0:0, [T2] overlay=0:0 [out]; [T1] fifo [T2]" -s hd720 testvid.mp4
The overlay order is controlled by the order of the inputs, from the ffmpeg docs
[...] takes two inputs and one output, the first input is the "main" video on which the second input is overlayed.
You second command thus becomes:
ffmpeg -y -loop 1 -qscale 1 -r 1 -b 9600 -i frame_%d.png -vf "movie=bg.png [wm];[wm][in] overlay=0:0" -s hd720 testvid.mp4
With the latest versions of ffmpeg the new -filter_complex command makes the same process even simpler:
ffmpeg -loop 1 -i bg.png -i frame_%d.png -filter_complex overlay -shortest testvid.mp4
A complete working example:
The source of our transparent input images (apologies for dancing):
Exploded to frames with ImageMagick:
convert dancingbanana.gif -define png:color-type=6 over.png
(Setting png:color-type=6 (RGB-Matte) is crucial because ffmpeg doesn't handle indexed transparency correctly.) Inputs are named over-0.png, over-1.png, over-2.png, etc.
Our background image (scaled to banana):
Using ffmpeg version N-40511-g66337bf (a git build from yesterday), we do:
ffmpeg -loop 1 -i bg.png -r 5 -i over-%d.png -filter_complex overlay -shortest out.avi
-loop loops the background image input so that we don't just have one frame, crucial!
-r slows down the dancing banana a bit, optional.
-filter_complex is a very recently added ffmpeg feature making handling of multiple inputs easier.
-shortest ends encoding when the shortest input ends, which is necessary as looping the background means that that input will never end.
Using a slightly less cutting-edge build, ffmpeg version 0.10.2.git-d3d5e84:
ffmpeg -loop 1 -r 5 -i back.png -vf 'movie=over-%d.png [over], [in][over] overlay' -frames:v 8 out.avi
movie doesn't allow rate setting, so we slow down the background instead which gives the same effect. Because the overlaid movie isn't a proper input, we can't use -shortest and instead explicitly set the number of frames to output to how many overlaid input frames we have.
The final result (output as a gif for embedding):
for references in the future as of 17/02/2015, the command-line is :
ffmpeg -loop 1 -i images/background.png -i images/video_overlay%04d.png -filter_complex overlay=shortest=1 testvid.mp4
thanks for llogan who took the time to reply here : https://trac.ffmpeg.org/ticket/4315#comment:1

Resources