What command would I use to convert an mp4 or mv4 video file to an animated gif, and vice versa. That is, convert a animated gif to a mp4 or mv4.
7 Answers
Here's what worked for me:
ffmpeg -i animated.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" video.mp4 movflags – This option optimizes the structure of the MP4 file so the browser can load it as quickly as possible.
pix_fmt – MP4 videos store pixels in different formats. We include this option to specify a specific format which has maximum compatibility across all browsers.
vf – MP4 videos using H.264 need to have a dimensions that are divisible by 2. This option ensures that’s the case.
- 5Thanks this is the only version that worked for me on osx.Pykler– Pykler2016-07-14 23:52:43 +00:00Commented Jul 14, 2016 at 23:52
- 2This worked for me on Ubuntu 16.10 with ffmpeg 3.0.2, where the top answer didn'tcat– cat2016-10-23 22:54:39 +00:00Commented Oct 23, 2016 at 22:54
- 6May as well crop instead of scaling (replace
scalewithcrop), as you're only going to be cutting off at most 1 pixel. Scaling might make things blurryJezzamon– Jezzamon2018-02-01 08:12:17 +00:00Commented Feb 1, 2018 at 8:12 - This cut off the last few seconds for me. Resulting mp4 ended early.callum– callum2018-02-22 13:06:13 +00:00Commented Feb 22, 2018 at 13:06
- 1What's the reasoning behind truncating, dividing and multiplying? How does this ensure "divisible by 2"-ness, and why does trunc alone not suffice? — Also: as far as I know, you can just write
"trunc(iw/2)*2:-2"and the height automatically becomes divisible by 2 while respecting the aspect ratio. (Except:cropdoes not accept negative values …)WoodrowShigeru– WoodrowShigeru2021-02-12 10:25:22 +00:00Commented Feb 12, 2021 at 10:25
In my case, using ffmpeg directly did the trick and provided the best result:
$ ffmpeg -f gif -i infile.gif outfile.mp4 - 9produced a blank (corrupted) video on os xPykler– Pykler2016-07-14 23:53:03 +00:00Commented Jul 14, 2016 at 23:53
- 2@Pykler you should probably increase verbosity and/or check the log file to understand what's happening.BenC– BenC2016-07-17 19:02:40 +00:00Commented Jul 17, 2016 at 19:02
- 2Me too, probably the "divisible by 2 dimensions" suggested in vico Vault's answer. (which worked for me)lapo– lapo2016-10-24 11:20:42 +00:00Commented Oct 24, 2016 at 11:20
- This method worked perfectly for me. (The top answer caused 3 seconds to be cut off the end.) EDIT: oh but it doesn't play on iOS :(callum– callum2018-02-22 13:07:38 +00:00Commented Feb 22, 2018 at 13:07
- A web page says you should just add -pix_fmt yuv420pbeefeather– beefeather2018-08-20 16:06:33 +00:00Commented Aug 20, 2018 at 16:06
A side note: the important thing is to specify -pix_fmt yuv420p lest your video might seem a black rectangle in various tools:
$ ffmpeg -i animated.gif -pix_fmt yuv420p output.mp4 References
- Not just Apple, but also Windows media player sometimes can't play the output if you don't specify that option. And if you try playing it with other players, it would be a comeple gray screen with artifacts showing on video.Shayan– Shayan2019-12-01 13:28:21 +00:00Commented Dec 1, 2019 at 13:28
- 1I get
height not divisible by 2 (260x373)andError initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or heighterror message. But this answer works for me.林果皞– 林果皞2019-12-20 15:36:39 +00:00Commented Dec 20, 2019 at 15:36 - 1observation - isn't the OP about taking animated gif as input (and/or output)? your answer has no gif as input or outputnhed– nhed2020-07-24 03:31:25 +00:00Commented Jul 24, 2020 at 3:31
- 1@nhed thanks, I slightly reworded it to put it back into the contextbeefeather– beefeather2020-07-28 12:14:28 +00:00Commented Jul 28, 2020 at 12:14
If you want to make the output in "n loops", look at this solution in one shot
So, let's convert a normal.gif to loop.mp4
for 2 loops movie example:
ffmpeg -stream_loop 2 -i normal.gif loop.gif -y;ffmpeg -i loop.gif -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" loop.mp4 -y for 5 loops movie example:
ffmpeg -stream_loop 5 -i my.gif loop.gif -y;ffmpeg -i loop.gif -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" loop.mp4 -y be aware: There's a -y option, so the output files will be overwritten
the -vf option is to resolve the ratio proportionality [width vs height]
- If you run the first
ffmpegcommand without-y, you'll have much less chance of accidentally overwriting something you don't want to. (There's also probably a way to getffmpegto pipe video into itself, and do this in one piped command without the intermediate file and the overwrite.)FeRD– FeRD2019-09-18 19:15:49 +00:00Commented Sep 18, 2019 at 19:15 - Thanks, exactly what I needed. But be careful, -stream_loop takes the number of EXTRA loops, so passing 2 will play the animation 3 times. 0 for no loop (single pass), -1 for infinite loop (erm... probably makes sense with other options to cut the movie after a certain duration).hsandt– hsandt2024-05-03 20:38:11 +00:00Commented May 3, 2024 at 20:38
Another way to convert GIF animation to video:
ffmpeg -i your_gif.gif -c:v libvpx -crf 12 -b:v 500K output.mp4 -crf values can go from 4 to 63. Lower values mean better quality. -b:v is the maximum allowed bitrate. Higher means better quality.
Warning: all the other answers at the current time will give you bad results.
The main reason for that is that most of them suggest you use -pix_fmt yuv420p gifs use rgb, bgr or pal pixel formats and converting them to yuv420p will not give you right colors, the result will usually turn a bit yellow or green. And not a single one of them has any quality options, so all of them will use default quality settings of ffmpeg which will result in low or middling quality.
If you want to create a gif from a video, rather than convert a gif to a video, here's my explanation for that: How do I convert a video to GIF using ffmpeg, with reasonable quality?
If you want to create a video or mp4 from a gif, I'm going to assume two things.
- You want to preserve the gif's original colors
- You want to minimize quality loss in the conversion process
To that effect, here are some actually good copy-pasteable commands.
h264 lossless:
This isn't truly lossless, but it's as close as you can get with h264, it's basically visually lossless.
Filesize will probably be bigger than the original gif.
ffmpeg -i <in.gif> -c:v libx264rgb -colorspace rgb -color_primaries bt709 -color_trc bt709 -qp 0 <out.mp4> h264 quality optimized:
I tried to get as close to visually lossless as possible without using the official lossless setting i did above.
ffmpeg -i <in.gif> -c:v libx264rgb -colorspace rgb -color_primaries bt709 -color_trc bt709 -crf 14 -preset veryslow <out.mp4> If you want to target a specific filesize, just increase the crf value by 1 incrementally until you get the desired size, every increase will cause a relatively dramatic reduction in filesize.
h265 lossless:
This isn't truly lossless, but it's as close as you can get with h265, it's basically visually lossless.
Filesize will probably be bigger than the original gif.
ffmpeg -i <in.gif> -c:v libx265 -x265-params lossless=1 <out.mp4> h265 quality optimized:
I tried to get as close to visually lossless as possible without using the official lossless setting i did above.
ffmpeg -i <in.gif> -c:v libx265 -crf 14 -preset veryslow -pix_fmt gbrp <out.mp4> If you want to target a specific filesize, just increase the crf value by 1 incrementally until you get the desired size, every increase will cause a relatively dramatic reduction in filesize.
av1 lossless:
This isn't truly lossless, but it's as close as you can get with av1, it's basically visually lossless.
Filesize will probably be bigger than the original gif.
ffmpeg -i <in.gif> -c:v libaom-av1 -aom-params lossless=1 -pix_fmt gbrp <out.mp4> av1 quality optimized:
I tried to get as close to visually lossless as possible without using the official lossless setting i did above.
ffmpeg -i <in.gif> -c:v libx265 -crf 14 -preset veryslow -pix_fmt gbrp <out.mp4> If you want to target a specific filesize, just increase the crf value by 1 incrementally until you get the desired size, every increase will cause a relatively dramatic reduction in filesize.
nvenc lossless:
This is the furthest from lossless of all the lossless options.
Replace <codec_nvenc> with one of the following:
- h264_nvenc
- hevc_nvenc
- av1_nvenc
_
ffmpeg -i <in.gif> -c:v <codec_nvenc> -tune lossless -pix_fmt bgr0 -sws_flags lanczos <out.mp4> nvenc quality optimized:
Replace <codec_nvenc> with one of the following:
- h264_nvenc
- hevc_nvenc
- av1_nvenc
_
ffmpeg -i <in.gif> -c:v <codec_nvenc> -preset p7 -rc constqp -qp 19 -spatial-aq 1 -multipass fullres -pix_fmt bgr0 -sws_flags lanczos <out.mp4> Additional info
libx264rgb's output will not render correctly in chromium or electron based applications without the color settings I included in those commands (everythiung would be green otherwise).
If you want to use hardware encoding (can't imagine why for a gif since gif duration tends to be measured in seconds at most, so you'd barely save any time)
You can use nvenc, vaapi is a bit murkier with great variation between gpus whether they support pixel formats like gbrp or bgra, (the one I have available to me only supports nv12 and yuv420p for example, neither outputs correct colors).
But with nvenc it's as simple as using the -pix_fmt bgr0 or -pix_fmt gbrp option.
None of my commands need -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" because all the codecs I suggested with the exception of hevc_nvenc and av1_nvenc support resolutions not divisible by 2. (and those two automatically do the conversion)
If you need to use this filter for a codec you're using, make sure to change it to this to get better quality:
-vf "scale=trunc(iw/2)*2:trunc(ih/2)*2:flags=lanczos" The -sws_flags lanczos I used with nvenc effectively does the same thing for the two codecs that need it. It upscales and downscales using the lanczos algorithm which gives very high quality results. Ideally though you want to avoid codecs that need this because this distorts your output (it'll stretch in one direction or the other, even if it's just by 1 pixel, it'll be noticeable.
If you're interested in learning more about the other quality options I made a thorough answer about it over here: https://unix.stackexchange.com/a/796176/72554