Stabilize Shaky Video With ffmpeg and vidstab


On my walking and hiking tours i often do not carry my camera but only my Android phone. Unlike the camera, the phone features no image stabilization mechanism whatsoever. In the past i have used the option offered by Google’s YouTube to apply a transformation that compensates for the most unfriendly effects of my hands being a bit shaky after some 10 or 20 miles of hiking. Since i am now moving forward to a more self-hosted approach of presenting my videos, i would like to have a similar procedure available locally.

For the ffmpeg software, which i use to convert A/V streams into internet-friendly output formats such as VP8 and Ogg Vorbis, there is a plugin „vidstab“ that is capable of doing the same thing.

In this article i describe a „two-pass“ procedure of applying „vidstab“ during a video conversion procedure, and i present some initial results i had when experimenting with the plugin’s parameters.

Using ffmpeg and „vidstab“

I define the names of some files that will be used by the conversion procedure:

input=goats.3gp # Available input stream file.
output=goats.webm # Intended output stream file.
trf=vidstab.trf # Temporary file; created by ffmpeg's vidstab filter.

For the sake of readability of the following examples, i define conversion parameters affecting codecs and quality of the conversion procedure in a shell variable convopts; they are only used when performing the final pass that results in the output file:

convopts="-c:v libvpx -crf 10 -b:v 1M -c:a libvorbis"

I perform the first pass of the shakyness reduction by using ffmpeg’s video filter vidstabdetect; the stream output is discarded and the detection results are saved to the file given by $trf.

ffmpeg -i $input -vf vidstabdetect=shakiness=10:accuracy=15:result="$trf" -f null -

I perform the second pass of the shakyness reduction; it will apply the results found in the first pass into geometrical transformations that compensate for „shaky“ movements:

ffmpeg -i $input $convopts -vf vidstabtransform=input="$trf" $output

While increasing the interior stability of the video, this procedure might result in „shaky borders“ surrounding the picture, with black background shifting in and out of the visible area as it is geometrically transformed.

To compensate for this phenomenon, vidstabtransform offers an option optzoom, which, when set to the value 2 , will attempt to zoom in and out of the content to keep visible black borders outside the visible area („optzoom“ means „optimal zoom“). The above commandline could be extended to the following to apply this addditional transformation:

ffmpeg -i $input $convopts -vf vidstabtransform=optzoom=2:input="$trf" $output

If the result is not satisfying in terms of zoom or pan of the visible area, as an alternative, a static zoom level can also be specified manually using the zoom option. A positive value of 5 meant „set zoom level to 105 percent“ (a negative value of -5 meant „set zoom level to 95 percent“):

ffmpeg -i $input $convopts -vf vidstabtransform=zoom=5:input="$trf" $output

Example Video

The original video:

A version of the video that has been converted to .webm using vidstab with zoom=25 as described above: