11

I am using ffmpeg to convert high quality videos to gif, most of the videos are 60fps and over 720p, but when I use the code below, to convert the video to gif, I get very low fps for the gif output,

#!/usr/bin/env
palette=/tmp/pallete.png
filter="fps=50,scale=480:-1:flags=lanczos"

ffmpeg -y  -i test.mov -vf $filter,palettegen=stats_mode=diff $palette
ffmpeg -y -i test.mov -i $palette -lavfi "$filter [x]; [x][1:v] paletteuse" test.gif

another issue I have noted is - as the width increases e.g 720 instead of 480 I get even lower fps.

here is output log example, the output fps is lower than the assigned 50fps

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/tmp/201631203815.mp4':
Metadata:
 major_brand     : isom
 minor_version   : 512
 compatible_brands: isomiso2avc1mp41
 encoder         : Lavf56.36.100
Duration: 00:00:05.48, start: 0.016000, bitrate: 1579 kb/s

Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 1334x1334, 1576 kb/s, 60.18 fps, 60 tbr, 1000k tbn, 50 tbc (default)
Metadata:
  handler_name    : VideoHandler

Input #1, png_pipe, from '/tmp/pallete.png':
   Duration: N/A, bitrate: N/A
Stream #1:0: Video: png, rgba(pc), 16x16 [SAR 1:1 DAR 1:1], 25 tbr, 25 tbn, 25 tbc

Output #0, gif, to '/tmp/201631203815.gif':
Metadata:
  major_brand     : isom
  minor_version   : 512
  compatible_brands: isomiso2avc1mp41
  encoder         : Lavf56.40.101
Stream #0:0: Video: gif, pal8, 480x480, q=2-31, 200 kb/s, 50 fps, 100 tbn, 50 tbc (default)
Metadata:
  encoder         : Lavc56.60.100 gif
Stream mapping:
   Stream #0:0 (h264) -> fps
   Stream #1:0 (png) -> paletteuse:palette
  paletteuse -> Stream #0:0 (gif)
Press [q] to stop, [?] for help

frame=  275 fps= 32 q=-0.0 Lsize=    2480kB time=00:00:05.50 bitrate=3693.5kbits/s    

How do I ensure that the output fps is always whats set by the user? Any resource on this is highly appreciated.

UPDATE

i have also noticed that the use of a higher fps eg filter="fps=90,scale=480:-1:flags=lanczos" has the effect of slowing down the gif,like a slow motion effect, the output fps is still lower around 15fps,

Muhia NJoroge
  • 539
  • 1
  • 5
  • 16
  • You probably mean `scale=-1:480` instead of `scale=480:-1`. 720p and 480p refers to the Y vertical resolution. Also your computer may be too slow to decode and view the high frame rate GIF (or at least your browser is slow with it). Try VLC Media Player or XnView to view them. Animated GIFs are not as optimized as real movie files, and developers are unlikely to optimize the decoding beyond simple animated graphics. – Chloe Sep 28 '18 at 21:54

2 Answers2

10

setting the fps value explicitly gave the same lower fps output results frame= 346 fps= 24 q=-0.0 Lsize= 6506kB time=00:00:06.92 bitrate=7701.8kbits/s

This is not the output fps! It's the encoding speed. Most players don't properly play GIFs with a fps higher than 50. See the demo showing this behaviour.

Gyan
  • 85,394
  • 9
  • 169
  • 201
5

I'm not experienced in making GIF files with FFmpeg, but as far as I know, the fps filter has an idividual "fps" parameter for the actual framerate value, so I think it may not work correctly if you omit that.

Just to make sure the filter gets the correct value, you should explicitly set the fps value:

filter="fps=fps=50,scale=480:-1:flags=lanczos"

If it doesn't working, I'd try the regular "rate" option too:

ffmpeg -y -i test.mov -i $palette -lavfi "$filter [x]; [x][1:v] paletteuse" -r 50 test.gif

Otherways, your console output looks good (it indicates the output will be 50fps), so the phenomena is a little bit mysterious.


Working Solution:

All you need to do is to break the process into three individual steps, and use the "-framerate" demux-option.

First, let's generate the palette file:

ffmpeg -i <input_file> -filter_complex "scale=w=480:h=-1:flags=lanczos, palettegen=stats_mode=diff" palette.png

Secondly, break the video frames into image files:

ffmpeg -i <input_file> -r 50 -f image2 image_%06d.png

And finally, join said images into one GIF sequence: (the important part here is the image2 demuxer's framerate option!)

ffmpeg -framerate 50 -i image_%06d.png -i palette.png -filter_complex "[0]scale=w=400:h=-1[x];[x][1:v] paletteuse" -pix_fmt rgb24 output.gif

Edit: Finally find the answer!

You need to use image2 demuxer's -framerate option! (answer edited accordingly)

Alternative methods:

  • gifsickle - convert images to gif, can set frame delay
  • ImageMagic - can convert video to gif directly, excellent gif quality control options.
Bob Fanger
  • 28,949
  • 7
  • 62
  • 78
Gergely Lukacsy
  • 2,881
  • 2
  • 23
  • 28
  • FFmpeg filters don't need the key name if you supply the values in the order specified in the source code. – Gyan Jun 01 '16 at 09:03
  • setting the fps value explicitly gave the same lower fps output results ```frame= 346 fps= 24 q=-0.0 Lsize= 6506kB time=00:00:06.92 bitrate=7701.8kbits/s ``` – Muhia NJoroge Jun 02 '16 at 00:35
  • using the regular "rate" option `-r 50` gave a similar low fps output result `frame= 346 fps= 20 q=-0.0 Lsize= 6506kB time=00:00:06.92 bitrate=7701.8kbits/s ` ffmpeg completely ignores the set fps and seems to calculate the output fps based on something, i cant find in the docs, anything about this behavior. – Muhia NJoroge Jun 02 '16 at 00:41
  • @GergelyLukacsy what other tools do you use? – Muhia NJoroge Jun 02 '16 at 01:07
  • @MuhiaNJoroge for conversion, I use FFmpeg only. Have you tried to break the video into images, then joining them together into a gif? I updated my answer accordingly. Also, some professional video editor tools have the ability to export to gif (I think Adobe Premiere Pro has). – Gergely Lukacsy Jun 02 '16 at 08:37
  • it take a bit more time when the videos are broken into images, its not ideal for lots of videos conversion, also i prefer command line tools so i guess Adobe Premiere Pro is out. – Muhia NJoroge Jun 02 '16 at 09:15
  • convert also take lots of time for lower quality so i think it is not ideal for conversion in this case, – Muhia NJoroge Jun 02 '16 at 09:17
  • the convert option created more than 150MB gif from a 8MB mov file, so i dont think that is an ideal solution, i will test gifsicle and let you know – Muhia NJoroge Jun 02 '16 at 09:20
  • use imagick's palette and dithering options, it will save you a lot of space... Also, i found the FFmpeg only solution, so updated my answer again. – Gergely Lukacsy Jun 02 '16 at 09:25