I want make an animated .gif
from an .mp4
video. I would prefer to do it from the command line, so please only list command line tools.
I want make an animated .gif
from an .mp4
video. I would prefer to do it from the command line, so please only list command line tools.
ffmpeg
3.4.4 can do it directly on Ubuntu 18.04You likely want to use something like:
opengl-rotating-triangle.gif
Image info: 426kB, 45 frames, 512x512 apparent size, coalesced, conversion time on a Lenovo P51: 0.5s.
The above conversion also worked after a
ulimit -Sv 1000000
(DRAM usage limited to 1GB), so it does "not consume huge amounts of memory" like previous attempts I did with Imagemagick which almost killed my machine. 500MB however failed because ffmpeg failed to load its shared libraries... time to upgrade your RAM ;-)?Test data generation procedure described on this post.
The output has a visible dotting pattern, which is not as visible in "ffmpeg + convert" method below. We can try to improve the image quality with methods described at:
E.g. using the
palettegen
filter:opengl-rotating-triangle-palettegen.gif
Image info: 979K, 45 frames, 512x512 apparent size, coalesced, conversion time on a Lenovo P51: 3.5s.
So we see that:
We could also play with documented
palettegen
parameters likepalettegen=max_colors=16
to achieve different size quality trade-off points.Argument breakdown
-ss 00:00:03 -to 00:00:06
: start and end time to cut the video from.No, GIFs are not the best way to
piratedistribute videos online.See also: https://stackoverflow.com/questions/18444194/cutting-the-videos-based-on-start-and-end-time-using-ffmpeg
-vf scale=512:-1
: make the output512
pixels in height, and adjust width to maintain the aspect ratio.This is a common use case for images for the web, which tend to have much smaller resolution than video.
If you remove this option, the output GIF has the same height as the input video.
The original video height can be found for example with
ffprobe
: https://superuser.com/questions/595177/how-to-retrieve-video-file-information-from-command-line-under-linux/1035178#1035178 and is 1024 x 1024 in our case.-r 15
: sampling FPS.For example, the original video was 30 FPS, so
-r 15
means thatffmpeg
will pick one frame in every 2 (= 30 / 15
).The perceived output FPS is adjusted to match the input however, so you won't notice a speedup, only greater granularity.
The input FPS can be found with
ffprobe
, and the total number of input frames can be found withmediainfo
as explained at: https://superuser.com/questions/84631/how-do-i-get-the-number-of-frames-in-a-video-on-the-linux-command-line/1044894#1044894I recommend this option because video formats usually have a higher framerate due to the larger resolution. With smaller GIFs, the lower framerate is less noticeable, and so we can skip some frames and make smaller GIFs.
Video camera footage example
If you want to see the result quality of a video camera video from Wikimedia Commons with a similar command:
STS-132_Liftoff_Space_Shuttle_Atlantis.gif
Image info: 1.3MB, 75 frames, 512x288 apparent size, coalesced (has minimal effect however, because footage pans slightly from the start), conversion time on a Lenovo P51: 2.3s.
Here is a version with
palettegen
but only 2 seconds to fit the 2MiB upload limit:Image info: 1.5MB, 30 frames, 512x288 apparent size, conversion time on a Lenovo P51: 43s.
A more direct:
also works, but the output GIF would be way larger than the input video, because video formats can compress more efficiently across frames with advanced algorithms, while GIF can only does a simple rectangular frame diff.
Before 18.04:
ffmpeg
+convert
one-liner without intermediate filesffmpeg
could not handle GIF previously. The best I had was something along:opengl-rotating-triangle-image-magick.gif
Image info: 995kB, 45 frames, 512x512 apparent size, coalesced.
For the Atlantis shuttle footage, and analogous:
produced better looking output, but the final GIF was considerably larger at 6.2MB, so I can't upload it.
Explanation of some of the arguments:
-loop 0
: add the Netscape Gif extension Loop count field to the output. 0 means infinite loop as described at: http://www.vurdalakov.net/misc/gif/netscape-looping-application-extensioneog
,firefox
and chromium all loop infinitely by default even without it, so I'm not sure how necessary it is anymore.-delay 5
: time waited before showing the next frame, in hundreths of second, as described at: https://en.wikipedia.org/wiki/GIF#Animated_GIF byte 324. So100
means 1 FPS,5
means1 / 0.5 == 20FPS
.-deconstruct
: compress across frames with rectangular diffs, see also: how can I resize an animated GIF file using ImageMagick?Even if you reduce the height and framerate, the output GIF may still be larger than the video, since "real" non-GIF video formats compress across frames, while GIF only compresses individual frames.
A direct:
worked, but almost killed my computer because of memory overflow, and produced an ouptput 100x larger for my 2s 1Mb input file. Maybe one day ImageMagick will catch up.
See also: https://superuser.com/questions/556029/how-do-i-convert-a-video-to-gif-using-ffmpeg-with-reasonable-quality
Tested on Ubuntu 17.10.
Gifski
https://gif.ski/
This is another option that was brought to my attention and which claims intelligent algorithms, so let's try it out.
First we need to convert the video to a sequence of images, and then feed that into gifsky, e.g.:
opengl-rotating-triangle-gifski.gif
Image info: 954K, 45 frames, 512x512 apparent size, not coalesced, conversion time on a Lenovo P51: 4.8s.
And the 2s STS:
Image info: 1.6M, 30 frames, 512x288 apparent size, not coalesced, conversion time on a Lenovo P51: 2.8s.
So for me, subjectively, this did not appear to offer significant benefit over ffmpeg's
palettegen
.Two steps:
Extract Images from Video
Create a directory called frames in the same directory with your
.mp4
file. Use command:source
Convert Images to gif
Docs: convert gif options
You will end up with an rather big file, have a look at the image magick guide to optimize gif on options you can add to the second step command to obtain a smaller file.
gifify is an all-in-one node-based utility that simplifies the conversion. It depends on
nodejs
,npm
,ffmpeg
, andimagemagick
which are all available in the repos.Once you have
npm
installed you can installgifify
globally with:A video can be converted to a .GIF with:
You can also optionally set a start and end position in the video and add a text caption:
❗️ It can take several minutes for the conversion to complete even with smaller videos.
I have started to put together a tool to provide a simplified interface to common actions.
You can convert an MP4 to GIF like this:
You can change the start and end time, and the
--fps
and--width
as well.It requires ffmpeg be installed.
If nothing else check out the source and see how to write your own script to do this in JavaScript.
Full Disclosure: This is my project.
If you are using linux, you can use linux-mpv-gif-generator
You will need ffmpeg, kdialog & mpv.
You have to place
mpv-gif.lua
in$HOME/.config/mpv/scripts
Now when you run a video on mpv, you will be able to use g to set start frame, G to set end frame, Ctrl+g to create gif. When you press Ctrl+g, it will ask where you want to save the gif.