How to compress gif effectively to reduce size? - ffmpeg

We use gifs for our blog extensively. We used to embed tenor nano gifs(90px height maintaining aspect ratio, used for GIF previews and shares on mobile) in it. Now we wanted to create our own gifs and are using the following command to convert mp4 to gif while maintaining the properties of tenor's nano gif. using ffmpeg version 4.1.4
But we observed a huge difference in size between the gif we created and the one created using tenor.
ffmpeg -i input.mp4 -filter_complex "[0:v]fps=10,scale=-1:90:flags=lanczos,split [a][b];[a] palettegen [p];[b][p] paletteuse" -y output.gif
[Original MP4] - 845KB
Tenor Nano gif - 42KB
ffmpeg gif - 106KB
We even tried changing dithering algorithm to further reduce size but it ended up adding noise and damaged the gif quality
paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle
We tried tweaking colour quantization in gifsicle as well but it was of no use.
gifsicle --resize _x90 --colors 256 --color-method diversity --dither=ordered --resize-method sample input.gif > output.gif

What worked for me was specifying a lower frame rate (-r 10) for the output gif. Probably not what you want if you're after quality but if you're after quality file size may be the compromise.

Try this bat file. I wrote it for myself. I have Windows os.
It converts FFmpeg mp4 to gif
Create two packages Your_files and Result put the bat file next to the folders.
Put these folders and baht file next to ffmpeg.exe
Drag your files (file) to the Your_files folder
Run bat file
We take the finished files from the Result folder
color a
#echo off
set a="Your_files\*.mp4"
set b="Result\%%~na.gif"
set c=ffmpeg
set f=-filter_complex "[0:v] fps=10,scale=-1:-1:flags=full_chroma_int,split [a][b];[a] palettegen=max_colors=255:reserve_transparent=1:stats_mode=diff [p];[b][p] paletteuse=dither=none:bayer_scale=5:diff_mode=rectangle:new=1:alpha_threshold=128" -gifflags -offsetting
for %%a in (%a%) do (%c% -y -i "%%a" %f% %b%)
If it crashes, remove these lines: -gifflags -offsetting

Related

imagemagick -auto-level in ffmpeg

I've been looking for a solution to perform the equivalent of magick -auto-level in ffmpeg but am unable to find anything. There are some references stating I should first manually discover the levels using other software like GIMP, however, I'm looking for an automated and simpler solution. Any ideas how to address this?
I've tried the following - the first enhanced the image which was initially prettry dark, but the second over-exposed it, causing it to become mostly white:
convert img.jpg -auto-level img2.jpg
ffmpeg -i img.jpg -vf "normalize" -y img2.jpg
Note: I apologize I cannot share the image as it is restricted by privacy policy

FFMPEG - Strange issue with video copy

I'm new here.
I have a set of TIF frames that equal 1 minute and 25 seconds of a video.
I'm attempting to copy the frames without re-encoding using the "-c:v copy" function to avoid visible quality loss for a process I'm doing on my side. The command is as follows:
ffmpeg -r 23.977 -i %06d.tif -c:v copy out.mkv
However for some reason, the timing does not seem to be accurate and the video is slightly desynced from the original, ending at 1 minute and 22 seconds instead.
When I use the following command:
ffmpeg -r 23.977 -i %06d.tif out.mkv
It comes out with the proper timing at 1 minute and 25 seconds, however, I did not appreciate the quality loss that came with it.
Is there a workaround to this or is there something I'm missing?
I used both Command Line and Windows Terminal.
In general, it would make sense to transcode when you go from tiff to video format. (I'm surprised it actually works.) You can set encoding quality to your own liking. See [this FFmpeg Wiki article[(https://trac.ffmpeg.org/wiki/Encode/H.264).

How to add telemetry data from a video to jpg file?

I have a 360deg video that is created by Go Pro Fusion and has telemetry data in it. I want to extract the telemetry data and put inside of jpg file.
I am extracting images using ffmpeg:
ffmpeg -i VIDEO.mp4 -r 5 img%d.jpg
How can i extract metadata(including telemetry data) for each frame and put that metadata inside jpg image of that frame.
I tried using
exiftool -ee -a -u -U -TagsFromFile video.mp4 img1.jpg
But all the metadata that appear in video does not appear in image.
I tried this:
exiftool -track1:VideoFrameRate=29.97 img1.jpg
But getting this warning:
Warning: Sorry, Track1:VideoFrameRate doesn't exist or isn't writable
Nothing to do.
<Track1:VideoFrameRate>20.00</Track1:VideoFrameRate>
I get this from video. But unable to set in jpg as mentioned above.
And how to ensure that the images are assigned with the exact GPS data?

ffmpeg: how to add pixellate effect?

I need to blur some uploaded videos and encoded them.
Infact by blur, it means pixellate them so "big squares" appear and blur it.
Any idea on how I can do that ? (ffmpeg would be great, by any command line windows tool should be ok)
Thanks.
FFmpeg can support the frei0r filters which includes pixeliz0r
Example:
ffmpeg -i input -vf "frei0r=filter_name=pixeliz0r:filter_params=0.02|0.02" output
The two pixeliz0r filter_params parameters are:
BlockSizeX: horizontal size of one "pixel"
BlockSizeY: vertical size of one "pixel"
Larger values will create larger blocks.
Where to get ffmpeg with frei0r support
Windows users can get the "full build" from gyan.dev.
Linux users can download or compile:
Download ffmpeg with frei0r support at johnvansickle.com.
Or compile ffmpeg by installing whatever package provides frei0r.h (such as frei0r-plugins-dev in Ubuntu or frei0r-devel in CentOS) and then add --enable-frei0r to your ffmpeg configure. See FFmpeg Wiki: Compile Guides.
macOS users can use Homebrew. You may need the --with-frei0r option.
More info
frei0r homepage
FFmpeg frei0r filter documentation
If you don't want to install the frei0r plugin for this, there's an alternative way.
dimensions=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of "csv=p=0:s=\:" input)
ffmpeg -i input -filter_complex \
"[0:v] scale='iw/15:-1', scale='$dimensions:flags=neighbor'" output
This scales down the input size (in this example, by 15) and then scales it back up to the original dimensions. The flags=neighbor tells ffmpeg to use the nearest neighbor rescaling algorithm which results in the pixelated effect. You can change the block size by changing the number 15.
The first line is needed to find out the input's original dimensions and scale back directly to it, otherwise the scaling down and scaling up might result in rounding errors that slightly alter the size of the output.

FFMPEG not able to extract thumbnails of images larger than .6 MB

ffmpeg.exe -i "imageLarge.jpg" -y -f mjpeg -s 72x92 -vframes 1 -an thumbnail7292.jpg
We are using this command to generate thumbnails of image files using FFmpeg but found that it is not able to generate thumbnails of files larger than .6 MB can somebody suggest something on this.
It isn't clear what exactly the problem with ffmpeg is, but in any case I'd recommend using the convert utility from imagemagick. It's much simpler:
convert imageLarge.jpg -resize 72x92 thumbnail7292.jpg
If you give a description of the actual error, then more people will be able to help you.
EDIT
The OP's error is:
swScaler: Compile time max width is 2048
change VOF/VOFW and recompile
Cannot get resampling context
It's quite clear what the problem is. Your JPEG files are too big for your current build of ffmpeg. You will have to recompile ffmpeg or get a newer version if you want to work with larger images.
This is from src/libswscale/swscale_internal.h (version: FFmpeg SVN-r26402).
#if ARCH_X86
#define VOFW 5120
#else
#define VOFW 2048 // faster on PPC and not tested on others
#endif
That's the file you need to edit if you want to change the limits.
What version of ffmpeg are you using? This problem seems to have been addressed over a year ago.
If you don't want to rebuild ffmpeg, you could just use convert, like I originally advised.

Resources