Vidstab is a video stabilization library which can be plugged-in with Ffmpeg.
Why is it needed
A video acquired using a hand-held camera or a camera mounted on a vehicle, typically suffers from undesirable shakes and jitters. Activities such as surfing, skiing, riding and walking while shooting videos are especially prone to erratic camera shakes. Vidstab targets these video contents to help create smoother and stable videos.
Some of the features include:
- Fast detection of subsequent transformations e.g. translation and rotations up to a given extent.
- Low pass filtered smoothing with adjustable horizon.
- L1-optimal camera path (Grundmann et al., CVPR 2011): the stabilized path is
composed of static, linear and parabolic segments, giving a result that looks
like it came off a dolly or a crane rather than off a low-pass filter. Solved
as a linear program with a built-in solver, so it needs no extra dependency.
It is steered by the usual knobs:
zoom/optzoomgive it the crop budget it may spend,smoothingthe horizon over which the path should stay rigid. - Smart and fast multi measurement fields detection algorithm with contrast selection.
- Clipping options: keep blank (black) or keep from previous frames.
- Optional drawing of measurement fields and detected transformations for visual analysis.
- Zooming possible to get rid of jiggling borders (automatic mode).
- Resulting images are interpolated (different algorithms).
- Virtual-tripod-mode to get a tripod experience.
NOTE: This readme covers using vidstab with Ffmpeg. Questions are welcome at georg dot martius @ web dot de
- A Linux-based system
- ffmpeg source code
- Cmake
The L1-optimal camera path is solved with a built-in interior point solver and
needs nothing else. GLPK can be used instead with cmake -DVIDSTAB_LPSOLVER=glpk;
the test suite runs against either and cross-checks both against the reference
implementation in docs/l1campath-reference.py.
For using vidstab library with ffmpeg, ffmpeg must to be configured using --enable-libvidstab option.
cd path/to/vid.stab/dir/
cmake .
make
sudo make installcd path/to/ffmpeg/dir/
./configure --enable-gpl --enable-libvidstab <other configure options>
make
sudo make installOn --enable-gpl: vidstab itself is LGPL-2.1-or-later and does not require
it, but ffmpeg's configure still gates --enable-libvidstab behind
--enable-gpl, so it remains necessary when building ffmpeg. It is an ffmpeg
packaging decision, not a licence requirement of this library.
cd path/to/vid.stab/dir/
cmake -DCMAKE_INSTALL_PREFIX:PATH=path/to/install_dir/
make
sudo make installcd path/to/ffmpeg/dir/
PKG_CONFIG_PATH="path/to/install_dir/lib/pkgconfig" \
./configure --enable-gpl --enable-libvidstab <other optionalconfigure options>
make
sudo make installBefore running ffmpeg for the first time, make sure to export LD_LIBRARY_PATH to point to vidstab library, e.g.,
export LD_LIBRARY_PATH=path/to/install_dir/lib:$LD_LIBRARY_PATHCurrently with ffmpeg, vidstab library must run in two-pass mode. The first pass employs the vidstabdetect filter and the second pass uses the vidstabtransform filter.
If you need a single pass, ffmpeg's own deshake filter can do that, though the vidstab two-pass filters give superior results.
The vidstabdetect filter (in first pass) will generate a file with relative-translation and rotation-transform information about subsequent frames. This information will then be read by vidstabtransform filter (in second pass) to compensate for the jerky motions and produce a stable video output.
Make sure that you use unsharp filter provided by ffmpeg for best results (only in second pass).
The transform file holds one entry per frame, in order, and the second pass consumes them in that order. It has no way to tell which frame it is looking at, so if the two passes are fed different frames the transforms silently stop lining up with the picture.
In practice this means: do not put any filter that changes the number, order
or rate of frames before vidstabtransform unless the exact same filter also
ran before vidstabdetect. The usual culprits are fps, minterpolate,
select, mpdecimate, trim and -r.
# WRONG: detect sees 30 fps, transform sees 48 -- transforms run out early
ffmpeg -i in.mp4 -vf vidstabdetect -f null -
ffmpeg -i in.mp4 -vf minterpolate=fps=48,vidstabtransform out.mp4
# RIGHT: change the rate first, in both passes
ffmpeg -i in.mp4 -vf minterpolate=fps=48,vidstabdetect -f null -
ffmpeg -i in.mp4 -vf minterpolate=fps=48,vidstabtransform out.mp4If it happens you get this warning, and everything after that point is unstabilized:
[vidstabtransform] not enough transforms found, use last transformation!
Two related traps:
- Duplicated frames in the source (a 25 fps recording stored as 30 fps, for
example) are detected as exactly zero motion, which shows up as a regular
jerk in the stabilized result. Drop them with
mpdecimate— in both passes — or work at the true frame rate. - Concatenated input (
-f concat) can present irregular timestamps; check that both passes report the same frame count before blaming the stabilization.
NOTE: 10-bit 4:2:2 video must be downsampled to 8-bit 4:2:0 to avoid distortions like chroma shift or color bleed/smearing (see format=yuv420p example below).
See the list of ffmpeg filters to know more about vidstabdetect, vidstabtransform and all other filters available with ffmpeg.
Deinterlace before stabilizing. Vidstab has no notion of fields: it treats every input frame as one progressive image. Feeding it interlaced material means the two fields — half a frame period apart, and thus showing different motion — are analysed as a single picture, so the comb artefacts are measured as image content and the detected motion is a meaningless average of the two fields. Transforming then shifts both fields together, which does not undo the shake and smears the combing across the frame.
Put a deinterlacer before vidstabdetect in both passes, e.g. with
yadif:
ffmpeg -i input.mkv -vf yadif,vidstabdetect -f null -
ffmpeg -i input.mkv -vf yadif,vidstabtransform,unsharp=5:5:0.8:3:3:0.4 out_stabilized.mp4Use the same deinterlacer settings in both passes, since the transforms are
measured in pixels of the frames the first pass saw. If you deinterlace to
double rate (yadif=1, one frame per field) that is fine — just do it in both
passes so the frame counts line up. Stabilizing and re-interlacing to keep an
interlaced deliverable is not supported.
The .trf file written by the first pass is documented in
docs/trf-format.md — both encodings, the meaning of the
stored values, and how to supply a camera path of your own.
- result
- Set the path to the file used to write the transforms information. Default value is transforms.trf.
- shakiness
- Set the shakiness of input video or quickness of camera. It accepts an integer in the range 1-10, a value of 1 means little shakiness, a value of 10 means strong shakiness. Default value is 5.
- accuracy
- Set the accuracy of the detection process. It must be a value in the range 1-15. A value of 1 means low accuracy, a value of 15 means high accuracy. Default value is 15.
- stepsize
- Set stepsize of the search process. The region around minimum is scanned with 1 pixel resolution. Default value is 6.
- mincontrast
- Set minimum contrast. Any measurement field having contrast below this value is discarded. Must be a floating point value in the range 0-1. Default value is 0.3.
- tripod
- Set reference frame number for tripod mode. If enabled, the motion of the frames is compared to a reference frame in the filtered stream, identified by the specified number. The intention is to compensate all movements in a more-or-less static scene and keep the camera view absolutely still. If set to 0, it is disabled. The frames are counted starting from 1.
Frames before the reference frame are not stabilized: no correction is applied to them (they are still zoomed/cropped like the rest of the clip), and stabilization begins at the reference frame, where the view snaps to the reference pose.
NOTE: If this mode is used in first pass then it should also be used in second pass. - show
- Show fields and transforms in the resulting frames for visual analysis. It accepts an integer in the range 0-2. Default value is 0, which disables any visualization.
In tripod mode, frames before the reference frame show no overlay, since no motion is measured for them.
Use default values:
ffmpeg -i input.mp4 -vf vidstabdetect -f null --f null - makes sure that no output is produced as this is just the first pass. This in-turn results in faster speed.
Analyzing strongly shaky video and putting the results in file mytransforms.trf:
ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=10:accuracy=15:result="mytransforms.trf" -f null -Visualizing the result of internal transformations in the resulting video:
ffmpeg -i input.mp4 -vf vidstabdetect=show=1 dummy_output.mp4Analyzing a video with high shakiness:
ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=10 dummy_output.mp4Downsampling a 10-bit 4:2:2 file to 8-bit 4:2:0 to avoid distortion like chroma shift and color bleed/smearing:
ffmpeg -i input.mp4 -vf format=yuv420p,vidstabdetect -f null -- input
- Set path to the file used to read the transforms. Default value is transforms.trf.
- smoothing
- Set the number of frames (value*2 + 1), used for lowpass filtering the camera movements. Default value is 10.
For example, a number of 10 means that 21 frames are used (10 in the past and 10 in the future) to smoothen the motion in the video. A larger value leads to a smoother video, but limits the acceleration of the camera (pan/tilt movements). 0 is a special case where a static camera is simulated. - optalgo
- Set the camera path optimization algorithm. Accepted values are:
gauss: Gaussian kernel low-pass filter on camera motion (default).
avg: Averaging on transformations. - maxshift
- Set maximal number of pixels to translate frames. Default value is -1, meaning: no limit.
- maxangle
- Set maximal angle in radians (degree*PI/180) to rotate frames. Default value is -1, meaning: no limit.
- crop
- Specify how to deal with empty frame borders that may be shrinked-in due to movement compensation. Available values are:
keep: Keep image information from previous frame (default).
black: Fill the border-areas black. - invert
- Invert transforms if set to 1. Default value is 0.
- relative
- Consider transforms as relative to previous frame if set to 1, absolute if set to 0. Default value is 0.
- zoom
- Set percentage to zoom. A positive value will result in a zoom-in effect, a negative value in a zoom-out effect. Default value is 0 (no zoom).
- optzoom
- Set optimal zooming to avoid blank-borders. Accepted values are:
0: Disabled.
1: Optimal static zoom value is determined (only very strong movements will lead to visible borders) (default).
2: Optimal adaptive zoom value is determined (no borders will be visible), see zoomspeed.
Note that the value given at zoom is added to the one calculated here. - zoomspeed
- Set percent to zoom maximally each frame (enabled when optzoom is set to 2). Range is from 0 to 5, default value is 0.25.
- interpol
- Specify type of interpolation. Available values are:
no: No interpolation.
linear: Linear only horizontal.
bilinear: Linear in both directions (default).
bicubic: Cubic in both directions (slow speed). - tripod
- Enables virtual tripod mode if set to 1, which is equivalent to relative=0:smoothing=0. Default value is 0.
The stored transforms are used as-is: no smoothing or accumulation is applied, they are simply passed through, including the leading zero transforms for frames before the reference frame. Which frames are not stabilized is decided during the first pass.
NOTE: If this mode has been used in first pass then it should also be used in second pass. - debug
- Increase log verbosity if set to 1. Also the detected global motions are written to the temporary file global_motions.trf . Default value is 0.
Using default values:
ffmpeg -i input.mp4 -vf vidstabtransform,unsharp=5:5:0.8:3:3:0.4 out_stabilized.mp4Note the use of the ffmpeg's unsharp filter which is always recommended.
Zooming-in a bit more and load transform data from a given file:
ffmpeg -i input.mp4 -vf vidstabtransform=zoom=5:input="mytransforms.trf" out_stabilized.mp4Smoothening the video even more:
ffmpeg -i input.mp4 -vf vidstabtransform=smoothing=30:input="mytransforms.trf" out_stabilized.mp4Downsampling a 10-bit 4:2:2 file to 8-bit 4:2:0 to avoid distortion like chroma shift and color bleed/smearing:
ffmpeg -i input.mp4 -vf format=yuv420p,vidstabtransform out_stabilized.mp4Vidstab is an open source library - pull requests are very welcome. Some things you might like to help us out with:
- Specific video clips where vidstab is not up-to the mark.
- Bugs/fixes.
- New features and improvements.
- Documentation.
GNU Lesser General Public License, version 2.1 or later (COPYING.LESSER). Releases up to v1.1.2 were GPL; see RELICENSE.md.