DEV Community

Besworks
Besworks

Posted on

1

Convert Video to Animated WebP Using FFmpeg With Auto-Cropping

Recently I had a need to clip a compilation video into a series of short looping animations. I could have used trusty ole gif format for this, but I wanted to use the more modern WebP, sister to the popular WebM format for video.

I couldn't find any decent tools or guides to do what I needed, so I decide to whip one together. The big features that I wanted were a) ease of use, and b) able to crop black bars automatically. The compilation I was working with was a mix of both portrait and landscape so this was a must.

As usual, FFmpeg has everything necessary to handle this baked right in. First we need a basic command to actually convert a video to WebP.

$ ffmpeg -i <in_file> -loop 1 -an -vf fps=fps=20 <out_file>
Enter fullscreen mode Exit fullscreen mode

I know that fps=fps=20 looks like a typo, but that is the actual syntax for this filter. A value of 20 here is a good balance between smooth playback and small filesize. So now we can convert an entire video into a looping WebP. But what if we want to clip just a specific portion?

$ ffmpeg -i <in_file> -ss <start_time> -to <end_time> -loop 1 -an -vf fps=fps=20 <out_file>
Enter fullscreen mode Exit fullscreen mode

-ss sets the start timestamp, -to sets the end timestamp. This can be simply # of seconds like 77, or full timestamp notation "00:01:17". But this command is getting a bit bulky. So let's wrap it in a script.

#!/bin/bash
start=""
end=""

if [ ! -z "$2" ]; then
  start="-ss $2"
fi

if [ ! -z "$3" ]; then
  end="-to $3"
fi

ffmpeg -i "$1" $start $end -loop 1 -an -vf fps=fps=20 "$4"
Enter fullscreen mode Exit fullscreen mode

Then we can use it like :

$ vid2webp infile.mp4 10 20 outfile.webp
Enter fullscreen mode Exit fullscreen mode

That's a lot leaner. Using this we can quickly and easily cut clips from a video into a series of animated WebP files. That satisfies requirement a. But we can't stop there. The next requirement is to detect the black bars, for this we need the cropdetect filter. The snippet blow seeks to the clip start time, samples 10 frames and extracts the video dimensions from the crop= output.

crop=$(ffmpeg $start -i "$1" -vframes 10 -vf cropdetect -f null -  2>&1 | grep -m 1 -oP 'crop=\K[0-9:]+')
Enter fullscreen mode Exit fullscreen mode

From that we can extract the height/width values using cut.

width=$(echo "$crop" | cut -d':' -f1)
height=$(echo "$crop" | cut -d':' -f2)
Enter fullscreen mode Exit fullscreen mode

Then apply scaling. The bc command is used here for "basic calculations" with floating point numbers, which bash can't do on it's own. Afterwards, we will generate a value to use in the scale filter, based on the larger of the x/y dimensions. The -2 value opposite this will tell FFmpeg to keep the aspect ratio but adjust the value to be divisible by 2. That way we don't get any odd numbers like 487.2 or something if the cropped dimensions aren't perfect.

scale=0.8
width=$(echo "$width * $scale" | bc)
height=$(echo "$height * $scale" | bc)
if [ "$height" -gt "$width" ]; then
  scale="-2:$height"
else
  scale="$width:-2"
fi
Enter fullscreen mode Exit fullscreen mode

And finally add these parameters to our ffmpeg command :

ffmpeg -i "$1" $start $end -loop 1 -an -vf crop="$crop",scale="$scale",fps=fps="$fps" "$4"
Enter fullscreen mode Exit fullscreen mode

Now, when we run our script multiple times on a compilation video we always get back a perfecftly cropped output with no black bars.

$ vid2webp infile.mp4 0 10 a.webp
$ vid2webp infile.mp4 10 18 b.webp
$ vid2webp infile.mp4 18 25 c.webp
Enter fullscreen mode Exit fullscreen mode

I built on this concept with few a additional features like error checking, overriding defaults with ENV vars and automatic sequential filename output. You can grab the final version from my Github Repo or install via AUR for Arch users.

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

DEV shines when you're signed in, unlocking a customized experience with features like dark mode!

Okay