Create animated gif from a set of jpeg images - windows

I need something that can be scripted on windows 7. This image will be used in banners.

Simon P Stevens' answer almost got me there:
ffmpeg -f image2 -i image%d.jpg video.avi
ffmpeg -i video.avi -pix_fmt rgb24 -loop_output 0 out.gif
Let's see if we can neaten this up.
Going via an avi is unnecessary. A -pix_fmt of rgb24 is invalid, and the -loop_output option prevents looping, which I don't want. We get:
ffmpeg -f image2 -i image%d.jpg out.gif
My input pictures are labeled with a zero-padded 3-digit number and I have 30 of them (image_001.jpg, image_002.jpg, ...), so I need to fix the format specifier
ffmpeg -f image2 -i image_%003d.jpg out.gif
My input pictures are from my phone camera, they are way too big! I need to scale them down.
ffmpeg -f image2 -i image_%003d.jpg -vf scale=531x299 out.gif
I also need to rotate them 90 degrees clockwise
ffmpeg -f image2 -i image_%003d.jpg -vf scale=531x299,transpose=1 out.gif
This gif will play with zero delay between frames, which is probably not what we want. Specify the framerate of the input images
ffmpeg -f image2 -framerate 9 -i image_%003d.jpg -vf scale=531x299,transpose=1 out.gif
The image is just a tad too big, so I'll crop out 100 pixels of sky. The transpose makes this tricky, I use the post-rotated x and y values:
ffmpeg -f image2 -framerate 9 -i image_%003d.jpg -vf scale=531x299,transpose=1,crop=299,431,0,100 out.gif
The final result - I get to share my mate's awesome facial expression with the world:

You can do this with ffmpeg
First convert the images to a video:
ffmpeg -f image2 -i image%d.jpg video.avi
(This will convert the images from the current directory (named image1.jpg, image2.jpg...) to a video file named video.avi.)
Then convert the avi to a gif:
ffmpeg -i video.avi -pix_fmt rgb24 -loop_output 0 out.gif
You can get windows binaries for ffmpeg here.
You can also do a similar thing with mplayer. See Encoding from multiple input image files.
I think the command line would be something like:
mplayer mf://*.jpg -mf w=800:h=600:type=jpg -vf scale=160:120 -vo gif89a:fps=3:output=out.gif
(Where 800 & 600 are your source width and height and 160 & 120 are the target width and height.out.gif is your target file name)
I've just tested both of these and they both work fine. However I got much better results from mplayer as I was able to specify the resolution and framerate. Your milage may vary and I'm sure you could find more options for ffmpeg if you looked.

With ImageMagick:
convert *.png a.gif

The ffmpeg to .avi and .avi to .gif worked, but the only thing to note is that your images must be named in perfect increasing numeric order to work, with no gaps. I cooked up a quick python script to rename all of my images accordingly so that this ffmpeg recipe would work:
import os
files = [ f for f in os.listdir('.') if os.path.isfile(os.path.join('.',f)) and f.endswith('.jpg') ]
for i, file in enumerate(sorted(files)):
os.rename(file, 'image%03d.jpg' % i)
And then I stumbled upon a much simpler approach than ffmpeg for doing the conversion, which is simply using ImageMagick's command line convert tool like this
convert image%03d.jpg[0-198] animated_gif.gif
Doesn't get much simpler than that folks.
Gist here: https://gist.github.com/3289840

Based on the answers of Simon P Stevens and dwurf I came up with this simplified solution:
ffmpeg -f image2 -framerate 1 -i image%d.jpg video.gif
This results in a rate of 1 second per image. Adjust the framerate value according to your needs.

I'd just like to add to dwurf's answer, that this will generate a gif with the standard 256-colors palette, which does not look very visually pleasing.
I've found two blog-posts and adapted them to my needs, in order to improve the visual quality by using a custom palette for your animation:
Generate the color palette:
ffmpeg -f image2 -i image%d.jpg -vf scale=900:-1:sws_dither=ed,palettegen palette.png
Convert images into a regular video with the desired framerate, because the third command only worked with a single input video and not a bunch of images
ffmpeg -f image2 -framerate 1.2 -i image%d.jpg video.flv
Now convert the generated video with the generated palette into a more beautiful gif:
ffmpeg -i video.flv -i palette.png -filter_complex "fps=1.2,scale=900:-1:flags=lanczos[x];[x][1:v]paletteuse" video.gif

Related

ffmpeg output scale not work with framerate

CLI:
ffmpeg -i 0.mov -vf scale=256x256 -filter:v fps=5 1.gif
OUTPUT: Video frame rate 5 Size 512x512 "Original Size"Webp will be better but that web server only accpet gif and i need small sizeSo Any Help ?
You need to combine all your filters into one filtergraph (or chain). Try:
ffmpeg -i 0.mov -vf scale=256x256,fps=5 1.gif
Meanwhile, both size and framerate can be adjusted w/out explicitly defining a filterchain. The following should do the same thing:
ffmpeg -i 0.mov -s 256x256 -r 5 1.gif

make image from movie proportional when scaled?

What would be the best way to take a screenshot with ffmeg ( say the first frame of movie ) and then
make a 200x200 image from it?
Im not sure what method to look for in docs or api to accomplish these tasks.
EDIT #1
Seems that:
ffmpeg -i 001.mp4 -ss 3 -f image2 -vframes 1 -s 600x600 output.png
Does convert to an image, but... this is not scaled (squased together)
what would be the correct way to have the image proportional?
Copied and modified from elsewhere on Stackoverflow...
You want something like this: ffmpeg -i video filename -vcodec video codec -vframes 1 -an -s 200x200 -f rawvideo output.jpg

ffmpeg images-to-video script anyone? [duplicate]

This question already has answers here:
How to create a video from images with FFmpeg?
(9 answers)
Closed 3 years ago.
I'm wanting to take a bunch of images and make a video slideshow out of them. There'll be an app for that, right? Yup, quite a few it seems. The problem is I want the slides synced to a piece of music, and all the apps I've seen only allow you to show each slide for a multiple of a whole second. I want them to show for multiples of 1.714285714 seconds to fit with 140 bpm.
The tools I've seen generally seem to have ffmpeg under the hood, so presumably this kind of thing could be done with a script. But ffmpeg has sooo many options...I'm hoping someone will have something close.
I'll have up to about 100 slides, the ones that have to show for 3.428571428 secs or whatever I guess I can simply show twice.
For very recent versions of ffmpeg (roughly from the end of year 2013)
The following will create a video slideshow (using video codec libx264 or webm) from all the png images in the current directory. The command accepts image names numbered and ordered in series (img001.jpg, img002.jpg, img003.jpg) as well as random bunch of images.
(each image will have a duration of 5 seconds)
ffmpeg -r 1/5 -pattern_type glob -i '*.png' -c:v libx264 out.mp4 # x264 video
ffmpeg -r 1/5 -pattern_type glob -i '*.png' out.webm # WebM video
For older versions of ffmpeg
This will create a video slideshow (using video codec libx264 or webm) from series of png images, named img001.png, img002.png, img003.png, …
(each image will have a duration of 5 seconds)
ffmpeg -f image2 -r 1/5 -i img%03d.png -vcodec libx264 out.mp4 # x264 video
ffmpeg -f image2 -r 1/5 -i img%03d.png out.webm # WebM video
You may have to slightly modify the following commands if you have a very recent version of ffmpeg
This will create a slideshow in which each image has a duration of 15 seconds:
ffmpeg -f image2 -r 1/15 -i img%03d.png out.webm
If you want to create a video out of just one image, this will do (output video duration is set to 30 seconds):
ffmpeg -loop 1 -f image2 -i img.png -t 30 out.webm
If you don't have images numbered and ordered in series (img001.jpg, img002.jpg, img003.jpg) but rather random bunch of images, you might try this:
cat *.jpg | ffmpeg -f image2pipe -r 1 -vcodec mjpeg -i - out.webm
or for png images:
cat *.png | ffmpeg -f image2pipe -r 1 -vcodec png -i - out.webm
That will read all the jpg/png images in the current directory and write them, one by one, using the pipe, to the ffmpeg's input, which will produce the video out of it.
Important: All images in a series need to be of the same size (x and y dimensions) and format.
Explanation: By telling FFmpeg to set the input file's FPS option (frames per second) to some very low value, we made FFmpeg duplicate frames at the output and thus we achieved to display each image for some time on screen. You have seen, that you can set any fraction as framerate. 140 beats per minute would be -r 140/60.
Source: The FFmpeg wiki
For creating images from a video use
ffmpeg -i video.mp4 img%03d.png
This will create images named img001.png, img002.png, img003.png, …
You can extract images from a video, or create a video from many
images:
For extracting images from a video:
ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg
This will extract one video frame per second from the video and will
output them in files named 'foo-001.jpeg', 'foo-002.jpeg', etc. Images
will be rescaled to fit the new WxH values. If you want to extract
just a limited number of frames, you can use the above command in
combination with the -vframes or -t option, or in combination with -ss
to start extracting from a certain point in time. For creating a video
from many images:
ffmpeg -f image2 -i foo-%03d.jpeg -r 12 -s WxH foo.avi
The syntax foo-%03d.jpeg specifies to use a decimal number composed
of three digits padded with zeroes to express the sequence number. It
is the same syntax supported by the C printf function, but only
formats accepting a normal integer are suitable.
This is an excerpt from the documentation, for more info check on the documentation page of ffmpeg.
I wound up using this:
mencoder "mf://html/*.png" -ovc x264 -mf fps=1.16666667 -o output.avi
and changing the sample rate afterwards in LiVES.
a load more details (and the end result video) at: http://hyperdata.org/hackit/ (mirror)

How to extract the 1st frame and restore as an image with ffmpeg?

Anyone knows the trick?
And how to install ffmpeg ? yum install mpeg only returns this:
======================================================================================== Matched: mpeg ========================================================================================
libiec61883.i386 : Streaming library for IEEE1394
libiec61883.x86_64 : Streaming library for IEEE1394
qffmpeg-devel.i386 : Development package for qffmpeg
qffmpeg-devel.x86_64 : Development package for qffmpeg
qffmpeg-libs.i386 : Libraries for qffmpeg
qffmpeg-libs.x86_64 : Libraries for qffmpeg
I've cobbled up this command line from various answers that works great for me to get the absolutely first frame out from a video. I use this to save a thumbnail screenshot for the video.
ffmpeg -i inputfile.mkv -vf "select=eq(n\,0)" -q:v 3 output_image.jpg
Explanation:
The select filter -vf "select=eq(n\,0)" is to select only frame #0.
-q:v allows you to set the quality of the output jpeg between 1 and 31. Lower the number, higher the quality. 2 - 5 works good, I use 3.
Note: This will get you an image with the same size as the video. To get a thumbnail, you can use the scale filter to get a thumbnail to fit whatever width you need, like so:
ffmpeg -i inputfile.mkv -vf "select=eq(n\,0)" -vf scale=320:-2 -q:v 3 output_image.jpg
The above command will give you a thumbnail jpeg that will be scaled to match width of 320, and height will be calculated to match the aspect ratio.
It's on the manpage:
* You can extract images from a video, or create a video from many
images:
For extracting images from a video:
ffmpeg -i foo.avi -r 1 -s WxH -f image2 foo-%03d.jpeg
This will extract one video frame per second from the video and will
output them in files named foo-001.jpeg, foo-002.jpeg, etc. Images
will be rescaled to fit the new WxH values.
If you want to extract just a limited number of frames, you can use
the above command in combination with the -vframes or -t option, or in
combination with -ss to start extracting from a certain point in time.
But of course you have to install it first. I'm on Debian and don't use yum.
[update for the other question]
i=1
for avi in *.avi; do
ffmpeg -i $avi -vframes 1 -f image2 /tmp/$i.jpg; i=$((i+1))
done
Tested and works.
[update for yet another question...]
for flv in *.flv; do
ffmpeg -i $flv -vframes 1 -f image2 ${flv%%.flv}.jpg
done
An easy to grok solution that works for me is
ffmpeg -i <input> -vframes 1 <output>.jpeg
Note that I do get an error "[swscaler # 0x111652000] deprecated pixel format used, make sure you did set range correctly" but according to a little reading (see for example https://stackoverflow.com/a/43038480/1241736) that can safely be ignored.
It's works for me
ffmpeg -i sample-mp4-file.mp4 -ss 1 -vframes 1 output.jpg

ffmpeg -is it possible to increase a clip duration?

I currently have a jpeg file which I converted to an flv using the following command:
ffmpeg -r 10 -b 180000 -i test.jpg test.mp4
Now, I want to increase the duration of this .mp4 clip, so the picture stays on the screen for more than a split second. Eventually, I hope to merge a stream of these files to create a slide show out of jpeg files.
Does anyone know how to increase the duration of a clip in ffmpeg?
Looping the input and setting a duration should achieve the effect you want:
ffmpeg -loop_input -i test.jpg -t 10 test.mp4
Doing something like this should work (at least for a single image):
ffmpeg -loop_input -i picture.jpg -r 1 -vcodec flv -b 192k -i Music.mp3 -acodec copy -shortest output.flv
I bet you could get it working with multiple images by adding more inputs though I haven't tested.
(http://forum.videohelp.com/threads/280695-FFMPEG-Loop-input-video)

Resources