georgmartius/vid.stab

Video stabilization library

VidStab is a library that removes unwanted shaking from video — the kind you get filming with a hand-held camera, or from a moving vehicle like a bike or surfboard. It isn't a standalone program; it plugs into FFmpeg and works as two special filters.


Why it exists

Hand-held video has constant jitter. VidStab detects the tiny movements (side-to-side translation and rotation) between consecutive frames, smooths them out, and produces video that looks steadier — like it was shot on a tripod or a dolly.


What it can do

  • Detect translation and rotation between frames, up to a configurable extent
  • Smooth the camera path with a low-pass filter (adjustable smoothing horizon)
  • L1-optimal camera path: instead of a simple smooth curve, it builds a path of straight and parabolic segments — giving a more professional look. This is solved with a built-in solver, so no extra dependency is needed
  • A contrast-based measurement-field algorithm for reliable motion detection
  • Clip options: fill empty borders with black, or reuse information from previous frames
  • Optional on-screen visualization of the detected motion for analysis
  • Automatic zooming to hide jiggling borders
  • Multiple interpolation algorithms for the final image
  • Virtual tripod mode: removes all movement to keep the camera perfectly still

System requirements

  • Linux
  • FFmpeg source code (you rebuild FFmpeg with VidStab enabled)
  • CMake

The built-in linear-programming solver needs nothing external; optionally you can use GLPK instead (via the -DVIDSTAB_LPSOLVER=glpk CMake flag), and the test suite cross-checks against both.


How it works: two-pass mode

VidStab must run in two passes with FFmpeg:

  1. First pass — vidstabdetect filter: Analyzes the video and writes the per-frame motion data to a transform file (default: transforms.trf). No video output is produced (-f null - makes it faster).
  2. Second pass — vidstabtransform filter: Reads the transform file, smooths the motion, and produces the stabilized video. It's recommended to add FFmpeg's unsharp filter afterward for sharpening.

The transform file contains one entry per frame in order. This leads to a critical rule:

Both passes must see exactly the same frames.

If any filter before vidstabtransform changes the frame count, order, or rate (e.g. fps, minterpolate, select, trim) — and that same filter didn't run before vidstabdetect — the transformation data won't line up, and you'll get an unstabilized result with a warning: not enough transforms found, use last transformation!. If you do modify the frame rate, do it in both passes (shown in the README with minterpolate).

Two related gotchas:

  • Duplicated frames (e.g. a 25 fps video stored as 30 fps) appear as zero motion and cause visible jerks — drop them with mpdecimate in both passes.
  • Concatenated inputs can have irregular timestamps — verify both passes report the same frame count.

More warnings from the README

  • Interlaced video must be deinterlaced first (e.g. with yadif) in both passes. VidStab treats each input as a single progressive image; interlaced fields show different motion and confuse the detection.
  • 10-bit 4:2:2 video must be converted to 8-bit 4:2:0 (with format=yuv420p) to avoid color distortion — again in both passes.

First-pass options (vidstabdetect)

  • result — output file for transforms (default transforms.trf)
  • shakiness — 1 (little shake) to 10 (strong shake); default 5
  • accuracy — detection precision, 1 (low) to 15 (high); default 15
  • stepsize — search step in pixels; default 6
  • mincontrast — measurement fields below this contrast are ignored; 0–1, default 0.3
  • tripod — reference frame number for tripod mode (0 disables). Frames before the reference aren't stabilized; the view snaps to the reference pose when it's reached. If used in pass 1, must also be used in pass 2.
  • show — 0–2, visualization intensity of fields and transforms (0 disables)

Second-pass options (vidstabtransform)

  • input — path to the transform file (default transforms.trf)
  • smoothing — number of frames (value×2+1) for low-pass filtering; default 10 means 21 frames (10 past + 10 future). Larger = smoother but limits pan/tilt speed. 0 simulates a static camera.
  • optalgo — gauss (Gaussian low-pass, default) or avg (simple averaging)
  • maxshift — max pixels to translate (default -1 = no limit)
  • maxangle — max rotation angle in radians (default -1 = no limit)
  • crop — keep (reuse previous frame's borders, default) or black (fill borders with black)
  • invert — invert transforms if set to 1
  • relative — treat transforms as relative to previous frame (1) or absolute (0); default 0
  • zoom — percentage zoom (positive = in, negative = out); default 0
  • optzoom — automatic zoom to avoid borders: 0 = off, 1 = static optimal zoom (default), 2 = adaptive zoom per frame (uses zoomspeed)
  • zoomspeed — max zoom change per frame as percentage, 0–5, default 0.25
  • interpol — interpolation type: no, linear (horizontal only), bilinear (both directions, default), bicubic (slow)
  • tripod — virtual tripod mode if set to 1 (equivalent to relative=0:smoothing=0); must match pass-1 setting
  • debug — more verbose logging and writes detected global motions to global_motions.trf

Example command pair

# First pass (analyze)
ffmpeg -i input.mp4 -vf vidstabdetect -f null -

# Second pass (stabilize + sharpen)
ffmpeg -i input.mp4 -vf vidstabtransform,unsharp=5:5:0.8:3:3:0.4 out_stabilized.mp4

The README shows many variations: custom transform files, higher shakiness, more smoothing, extra zoom, and the format=yuv420p downsampling workaround.


Note on FFmpeg's GPL flag

VidStab itself is licensed LGPL-2.1-or-later, but FFmpeg's configure script still requires --enable-gpl to enable the --enable-libvidstab option. That's an FFmpeg packaging decision, not a license requirement of VidStab.


Contributing

The project welcomes pull requests — bug fixes, new features, documentation, or example clips where VidStab underperforms. The transform-file format is documented in docs/trf-format.md for those who want to supply custom camera paths.

関連

  • プロジェクト
  • プロジェクト
  • プロジェクト
  • プロジェクト