Configure FFmpeg Vidstabtransform Smoothing

This article explains how to configure the smoothing factors for translation, rotation, and zoom using the vidstabtransform filter in FFmpeg. By understanding how to manipulate the primary smoothing window alongside translation, rotation, and zoom constraints, you can eliminate camera shake while maintaining control over the composition of your output video.

The Two-Step Stabilization Process

To use vidstabtransform, you must first run a detection pass using the vidstabdetect filter. This pass analyzes the video for motion and writes the camera path data to a file (usually transforms.trf). The second pass uses vidstabtransform to read this file and apply the stabilization.

# Step 1: Detect motion
ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=10:accuracy=15:result=transforms.trf -f null -

# Step 2: Transform/Stabilize video
ffmpeg -i input.mp4 -vf vidstabtransform=smoothing=30:maxshift=100:maxangle=0.1:optzoom=1 output.mp4

Configuring the Smoothing Parameters

Unlike some stabilization tools that use separate smoothing sliders for translation, rotation, and zoom, the vidstabtransform filter uses a unified smoothing parameter to set the temporal window, while relying on specific constraint parameters (maxshift, maxangle, and zoom) to fine-tune each individual transformation type.

1. General Smoothing (smoothing)

The smoothing parameter defines the number of frames (the radius of the low-pass filter window) used to smooth the camera path. This single value applies to translation, rotation, and zoom. * Default: 15 * How it works: A higher value (e.g., 30 or 50) results in a smoother camera path but requires more cropping to hide the resulting black borders. A lower value (e.g., 5 or 10) retains more of the original camera motion but requires less cropping.

2. Controlling Translation (maxshift)

To limit or fine-tune how much the image is allowed to translate (shift horizontally and vertically) to compensate for camera shake, use the maxshift parameter. * Syntax: maxshift=pixels (Default: -1, which means no limit) * Usage: Set this to a positive integer (e.g., maxshift=100) to limit the maximum translation in pixels. Lowering this value prevents the video from shifting too far from the center, which helps minimize the required crop area at the expense of translation stabilization.

3. Controlling Rotation (maxangle)

To control how aggressively the filter corrects camera roll (rotation), use the maxangle parameter. * Syntax: maxangle=radians (Default: -1, which means no limit) * Usage: Set this in radians (e.g., maxangle=0.08 is roughly 4.5 degrees) to cap the maximum rotation correction. Restricting the rotation stabilization prevents extreme tilts and reduces the amount of dynamic zooming needed to cover empty corners.

4. Controlling Zoom (zoom and optzoom)

Because stabilizing translation and rotation creates empty black borders, the video must be zoomed in. You can configure zooming behavior with these two parameters: * optzoom (Optimal Zoom): * Set optzoom=1 (default) to let the filter automatically calculate the optimal, static zoom factor needed to hide black borders throughout the video. * Set optzoom=2 for dynamic zoom, which adjusts the zoom factor on a frame-by-frame basis depending on how much stabilization is happening at that moment. * zoom (Manual Zoom percentage): * Syntax: zoom=percent (Default: 0, which means no extra manual zoom). * If you set optzoom=0 (disabled), you can manually define a static zoom percentage (e.g., zoom=5 for a 5% zoom) to crop the borders yourself.

Practical Configuration Example

If you want aggressive smoothing on a highly shaky video while preventing extreme rotational tilts and minimizing crop size, use the following configuration:

ffmpeg -i input.mp4 -vf vidstabtransform=smoothing=45:maxshift=120:maxangle=0.05:optzoom=1 output.mp4

In this setup, smoothing=45 provides a large smoothing window, while maxshift=120 and maxangle=0.05 prevent the stabilizer from pushing the frame too far horizontally, vertically, or rotationally. Finally, optzoom=1 automatically handles the ideal zoom to hide any borders created by these limits.