Linux – webp animation to gif animation (cli)

animationarch linuxgifimagemagickwebp

I was surprised today to find apparently how difficult it is to go from a webp animation to gif animation. My GIMP 2.8.22 and ImageMagick 7.0.7-21 on linux 4.14.13-1-ARCH don't seem to support the format, and the only tool available in repos seem to be libwebp 0.4.1 which includes a decode tool that lets you extract individual frames to some image formats, none of them being gif (It's a licensing problem maybe?)

Anyway, I used the following script:

#!/bin/bash

DELAY=${DELAY:-10}
LOOP=${LOOP:-0}
r=`realpath $1`
d=`dirname $r`
pushd $d > /dev/null
f=`basename $r`
n=`webpinfo -summary $f | grep frames | sed -e 's/.* \([0-9]*\)$/\1/'`
pfx=`echo -n $f | sed -e 's/^\(.*\).webp$/\1/'`
if [ -z $pfx ]; then
    pfx=$f
fi

echo "converting $n frames from $f 
working dir $d
file stem '$pfx'"

for ((i=0; i<$n; i++)); do
    webpmux -get frame $i $f -o $pfx.$i.webp
    dwebp $pfx.$i.webp -o $pfx.$i.png
done

convert $pfx.*.png -delay $DELAY -loop $LOOP $pfx.gif
rm $pfx.[0-9]*.png $pfx.[0-9]*.webp
popd > /dev/null

Which creates a gif animation from the extracted frames of the file supplied in the first argument.

I tried it on this file and the resulting file was kind of artifacty. Is it proper form to post in this forum for suggestions of improvement of the procedure/invocations?

And: If there are custom tools for this conversion, please share your knowledge! 🙂

Best Answer

Your script works just fine, but you need to zero pad your individual frame names; otherwise it creates the gif with frames in a jumbled order. I fixed that and tried it on a few giphy webp animations (including your example) and the output is what you'd expect.

Below is just your script with two changes. First, an altered for loop to zero pad those frame filenames. Second, I added another webpinfo check to grab the frame duration and use that (if > 0) for DELAY (naively assuming that people aren't using variable frame durations):

#!/bin/bash

DELAY=${DELAY:-10}
LOOP=${LOOP:-0}
r=`realpath $1`
d=`dirname $r`
pushd $d > /dev/null
f=`basename $r`
n=`webpinfo -summary $f | grep frames | sed -e 's/.* \([0-9]*\)$/\1/'`
dur=`webpinfo -summary $f | grep Duration | head -1 |  sed -e 's/.* \([0-9]*\)$/\1/'`

if (( $dur > 0 )); then
    DELAY = dur
fi

pfx=`echo -n $f | sed -e 's/^\(.*\).webp$/\1/'`
if [ -z $pfx ]; then
    pfx=$f
fi

echo "converting $n frames from $f 
working dir $d
file stem '$pfx'"

for i in $(seq -f "%05g" 1 $n)
do
    webpmux -get frame $i $f -o $pfx.$i.webp
    dwebp $pfx.$i.webp -o $pfx.$i.png
done

convert $pfx.*.png -delay $DELAY -loop $LOOP $pfx.gif
rm $pfx.[0-9]*.png $pfx.[0-9]*.webp
popd > /dev/null
Related Question