240

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.

1
  • 1
    You can use this script on Github that uses FFMPEG and generates intermediate color palette for better picture quality.
    – NG_
    Apr 24, 2019 at 8:36

4 Answers 4

307

ffmpeg 3.4.4 can do it directly on Ubuntu 18.04

You likely want to use something like:

sudo apt install ffmpeg
wget -O opengl-rotating-triangle.mp4 https://github.com/cirosantilli/media/blob/master/opengl-rotating-triangle.mp4?raw=true
ffmpeg \
  -i opengl-rotating-triangle.mp4 \
  -r 15 \
  -vf scale=512:-1 \
  -ss 00:00:03 -to 00:00:06 \
  opengl-rotating-triangle.gif

opengl-rotating-triangle.gif

enter image description here

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:

ffmpeg \
  -i opengl-rotating-triangle.mp4 \
  -r 15 \
  -vf "scale=512:-1,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
  -ss 00:00:03 -to 00:00:06 \
  opengl-rotating-triangle-palettegen.gif

opengl-rotating-triangle-palettegen.gif

enter image description here

Image info: 979K, 45 frames, 512x512 apparent size, coalesced, conversion time on a Lenovo P51: 3.5s.

So we see that:

  • the dotting pattern is much less visible now
  • GIF size roughly doubled. TODO: why does simply choosing a palette increase the image size? Is it because now more colors so we need more bits per color? How to observe each palette?
  • generation time was 7x slower, presumably because ffmpeg is first scanning through the entire video to determine an optimal palette

We could also play with documented palettegen parameters like palettegen=max_colors=16 to achieve different size quality trade-off points.

Argument breakdown

Video camera footage example

If you want to see the result quality of a video camera video from Wikimedia Commons with a similar command:

wget https://upload.wikimedia.org/wikipedia/commons/f/f9/STS-132_Liftoff_Space_Shuttle_Atlantis.ogv
ffmpeg -i STS-132_Liftoff_Space_Shuttle_Atlantis.ogv -r 15 -vf scale=512:-1 \
  -ss 00:00:17 -to 00:00:22 STS-132_Liftoff_Space_Shuttle_Atlantis.gif

STS-132_Liftoff_Space_Shuttle_Atlantis.gif

enter image description here

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:

enter image description here

Image info: 1.5MB, 30 frames, 512x288 apparent size, conversion time on a Lenovo P51: 43s.

A more direct:

sudo apt-get install ffmpeg
ffmpeg -i in.mp4 out.gif

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 files

ffmpeg could not handle GIF previously. The best I had was something along:

sudo apt-get install ffmpeg imagemagick
ffmpeg -i opengl-rotating-triangle.mp4 -r 15 -vf scale=512:-1 \
  -ss 00:00:03 -to 00:00:06 -f image2pipe -vcodec ppm - |
  convert -deconstruct -delay 5 -loop 0 - opengl-rotating-triangle-image-magick.gif

opengl-rotating-triangle-image-magick.gif

enter image description here

Image info: 995kB, 45 frames, 512x512 apparent size, coalesced.

For the Atlantis shuttle footage, and analogous:

ffmpeg -i STS-132_Liftoff_Space_Shuttle_Atlantis.ogv -r 15 -vf scale=512:-1 \
  -ss 00:00:17 -to 00:00:22 -f image2pipe -vcodec ppm - |
  convert -deconstruct -delay 5 -loop 0 - STS-132_Liftoff_Space_Shuttle_Atlantis_512x.gif

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:

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:

convert input.mp4 rpi2-bare-metal-blink.gif

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.:

sudo snap install gifski
mkdir -p frames
ffmpeg \
  -i opengl-rotating-triangle.mp4 \
  -r 15 \
  -vf scale=512:-1 \
  -ss 00:00:03 -to 00:00:06 \
  frames/%04d.png
gifski -o opengl-rotating-triangle-gifski.gif frames/*.png

opengl-rotating-triangle-gifski.gif

enter image description here

Image info: 954K, 45 frames, 512x512 apparent size, not coalesced, conversion time on a Lenovo P51: 4.8s.

And the 2s STS:

enter image description here

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.

20
  • 1
    Your delay does not match your -r value (the resulting gif is 2x speed). Also you added a scale argument for no apparent reason (it makes the gif really small).
    – asmeurer
    Oct 21, 2016 at 17:51
  • 2
    I agree. Small size gifs are better for web. Thanks for scale=320:-1
    – zombic
    Oct 26, 2016 at 8:26
  • 2
    For those who are wondering: removing -r 10 will bring the GIF back to normal speed.
    – Mitch
    Feb 13, 2017 at 8:05
  • 3
    I got a gif 20% bigger than the mp4 :O
    – goldylucks
    May 11, 2017 at 2:39
  • 1
    @CiroSantilli华涌低端人口六四事件法轮功 After the process had been running for 3 minutes it had used 30% of all memory, according to top, after 4 minutes it was at 50%, etc. As I only had 8GB of RAM, that made my computer start stuttering for all operations, due to it needing to use the swap disk. We'll see how far it goes, right now the convert process is using 5.5GB of RAM ... Storing the entire in-process file in-memory doesn't seem very clever.
    – oligofren
    Jan 31, 2018 at 12:35
132

Two steps:

  • Extract Images from Video

    Create a directory called frames in the same directory with your .mp4 file. Use command:

    ffmpeg -i video.mp4  -r 5 'frames/frame-%03d.jpg'
    


    -r 5 stands for FPS value
        for better quality choose bigger number
        adjust the value with the -delay in 2nd step
        to keep the same animation speed
    
    %03d gives sequential filename number in decimal form
    

    source

  • Convert Images to gif

    cd frames
    convert -delay 20 -loop 0 *.jpg myimage.gif
    


    -delay 20 means the time between each frame is 0.2 seconds
       which match 5 fps above.
       When choosing this value
           1 = 100 fps
           2 = 50 fps
           4 = 25 fps
           5 = 20 fps
           10 = 10 fps
           20 = 5 fps
           25 = 4 fps
           50 = 2 fps
           100 = 1 fps
           in general 100/delay = fps
    
    -loop 0 means repeat forever
    

    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.

5
  • 1
    great answer- some additional info: ffmpeg can be installed using directions here
    – chepyle
    Mar 29, 2016 at 2:02
  • 4
    Keep in mind that the frames folder must exist for the first command to work.
    – totymedli
    Jun 7, 2017 at 15:09
  • 4
    For those that want a quick way to optimize that generally works and are too lazy to read the link, just add -layers Optimize to the last convert command, before *.jpg. Check the output though, it might be affected. For me it reduced the gif size from 5 MB to 700 KB without any perceivable loss in quality :)
    – cpury
    Jul 10, 2017 at 8:54
  • Thanks that was an interesting process, a 5.6MB mp4 ended up a 236MB gif, not sure I'll be putting that one up on my website ;) Possibly a gif needs to be limited to seconds rather than a minute.
    – cardamom
    Sep 12, 2017 at 9:37
  • 3
    Instead of using the JPG file format, very lossy with the default settings, I'd recommend using PNG for the initial file export. ffmpeg -i video.mp4 -r 5 'frames/frame-%03d.png'.
    – Pierre F
    Jun 7, 2018 at 11:15
14

gifify is an all-in-one node-based utility that simplifies the conversion. It depends on nodejs, npm, ffmpeg, and imagemagick which are all available in the repos.

Once you have npm installed you can install gifify globally with:

    npm install -g gifify

A video can be converted to a .GIF with:

    gifify video.mp4 -o video.gif

You can also optionally set a start and end position in the video and add a text caption:

    gifify clip.mp4 -o clip.gif --from 01:48:23.200 --to 01:48:25.300 --text 'we are the knights who say nip!'

❗️ It can take several minutes for the conversion to complete even with smaller videos.

NOTE: ffmpeg and imagemagick might need to be compiled with some specific libraries (i.e. libass and fontconfig accordingly).

4
  • Doesn't handle approx > 40 sec clips: github.com/vvo/gifify/issues/99
    – oligofren
    Jan 30, 2018 at 16:03
  • 1
    19.04: Another required package is gifsicle, but then another problem occurs: github.com/vvo/gifify/issues/95 Also, would you mind telling us npm novices in what directory to run npm install and whether to run it as root or not? Thanks! Apr 18, 2019 at 4:13
  • @NicolasRaoul It's extremely rare to need to run npm as root.
    – RyanNerd
    Feb 13, 2022 at 22:19
  • You have to install gifsicle globally, then ffmpeg from npm globally as well, I don't think using npm is the best solution here. because if the developer of the package gifify wanted this package to be executed from command line for daily use, he would have made it a command-line utility by adding the sh-bang at the first line. and hence, this package is only meant to be used in applications, for programmers, not for daily use.
    – Normal
    Sep 27, 2022 at 22:01
0

Full Disclosure: This is my project.

If you are using linux, you can use linux-mpv-gif-generator

You will need ffmpeg, kdialog & mpv.

sudo apt install 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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .