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:
- First pass —
vidstabdetectfilter: 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). - Second pass —
vidstabtransformfilter: Reads the transform file, smooths the motion, and produces the stabilized video. It's recommended to add FFmpeg'sunsharpfilter 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
mpdecimatein 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 (defaulttransforms.trf)shakiness— 1 (little shake) to 10 (strong shake); default 5accuracy— detection precision, 1 (low) to 15 (high); default 15stepsize— search step in pixels; default 6mincontrast— measurement fields below this contrast are ignored; 0–1, default 0.3tripod— 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 (defaulttransforms.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.0simulates a static camera.optalgo—gauss(Gaussian low-pass, default) oravg(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) orblack(fill borders with black)invert— invert transforms if set to 1relative— treat transforms as relative to previous frame (1) or absolute (0); default 0zoom— percentage zoom (positive = in, negative = out); default 0optzoom— automatic zoom to avoid borders: 0 = off, 1 = static optimal zoom (default), 2 = adaptive zoom per frame (useszoomspeed)zoomspeed— max zoom change per frame as percentage, 0–5, default 0.25interpol— interpolation type:no,linear(horizontal only),bilinear(both directions, default),bicubic(slow)tripod— virtual tripod mode if set to 1 (equivalent torelative=0:smoothing=0); must match pass-1 settingdebug— more verbose logging and writes detected global motions toglobal_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.
관련
- 프로젝트
- 프로젝트
- 프로젝트
- 프로젝트