Skip to content

Instantly share code, notes, and snippets.

@residentsummer
Created February 25, 2017 16:15
Show Gist options
  • Save residentsummer/3f2c0c26eced38be06708d1f03ad9fbb to your computer and use it in GitHub Desktop.
Save residentsummer/3f2c0c26eced38be06708d1f03ad9fbb to your computer and use it in GitHub Desktop.
Script to stabilize shaky GoPro footage with ffmpeg and libvidstab
#!/bin/bash
# Run without args to see usage
##### Configuration #####
# Maximum shakiness and accuracy
DETECT_OPTS="shakiness=10:accuracy=15"
# Fish-eye correction for GoPro H3+B 16:9 Wide
# http://stackoverflow.com/questions/30832248/is-there-a-way-to-remove-gopro-fisheye-using-ffmpeg/40659507#40659507
# I can barely see the difference, though :(
PRE_STAGES="lenscorrection=cx=0.5:cy=0.5:k1=-0.227:k2=-0.022"
# Zoom: dynamic/static/no. Dynamic may produce strange results.
# TRANSFORM_OPTS="smoothing=30:zoom=10:optzoom=2:zoomspeed=1:interpol=bicubic"
TRANSFORM_OPTS="smoothing=30:zoom=10:interpol=bicubic"
# TRANSFORM_OPTS="smoothing=30:interpol=bicubic"
# As recommended by vidstab author
POST_STAGES="unsharp=5:5:0.8:3:3:0.4"
# h.264 output options
VOUT_OPTS="-vcodec libx264 -preset slow -tune film -crf 18"
# Compare central regions of two videos side-by-side
SBS_PIPELINE="[0:v] crop=out_w=iw/2:x=iw/4, pad=width=iw*2 [a];[1:v] crop=out_w=iw/2:x=iw/4 [b]; [a][b] overlay=x=W/2"
##### Script support funcs (just skip to the next section) #####
declare -a ACTIONS
declare -a USAGE=("Usage:")
add-action () {
ACTIONS+=($1)
USAGE[${#USAGE[@]}]=`echo " " $BASENAME $@`
}
usage () {
for ((i = 0; i < ${#USAGE[@]}; i++)); do
echo "${USAGE[$i]}"
done
}
main () {
action=$1
shift
if [[ -z "${action// /}" ]]; then
usage && exit
fi
for a in ${ACTIONS[@]}; do
if [[ $action == $a ]]; then
$a $@
exit
fi
done
usage
}
##### Functional part #####
add-action stab-detect "<IN:video> <OUT:vectors> - analyze <video> to calculate transform <vectors>"
function stab-detect () {
VIDEO="$1"
VECTORS="$2"
ffmpeg -i "${VIDEO}" -vf "vidstabdetect=${DETECT_OPTS}:result=${VECTORS}" -f null -
}
add-action stab-transform "<IN:video> <IN:vectors> <OUT:stabilized> - produce <stabilized> version of <video> using transform <vectors>"
function stab-transform () {
VIDEO="$1"
VECTORS="$2"
STABILIZED="$3"
ffmpeg -i "${VIDEO}" \
-vf "${PRE_STAGES},vidstabtransform=input=${VECTORS}:${TRANSFORM_OPTS},${POST_STAGES}" \
${VOUT_OPTS} -acodec copy "${STABILIZED}"
}
add-action stabilize "<IN:video> <OUT:stabilized> - combined detect and transform"
function stabilize () {
VIDEO="$1"
STABILIZED="$2"
VECTORS="${VIDEO%.*}.trf"
stab-detect "${VIDEO}" "${VECTORS}" && \
stab-transform "${VIDEO}" "${VECTORS}" "${STABILIZED}"
}
add-action compare "<IN:video1> <IN:video2> <OUT:output> - make side-by-side comparison video"
function compare () {
ffmpeg -i "$1" -i "$2" -filter_complex "${SBS_PIPELINE}" ${VOUT_OPTS} "$3"
}
main $@
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment