Search

Ubuntu 14.04 - Rotate & Stabilize your video with MLT and Vid.stab

Contents[Hide]

dropcap-ubuntu-stabilize

Since availability of Ubuntu Xenial 16.04, this procedure is obsolete and is not updated.
Please use Ubuntu 16.04 - Rotate & Stabilize your video with MLT and Vid.stab instead.

Nowadays, street video shooting is becoming a reality.  With any modern smartphone, point-and-shoot camera or even a GoPro camera, you can shoot any video anywhere.

These devices are affordable, light-weight, very compact and easy to use. Whatever happens around you, you are able to record it on the spot. But, on the other end, as these devices are compact and light, they are not very steady. Your recordings tend to be shaky !

Another problem you can encounter when shooting from a smartphone is that your video may be recorded upside-down or even rotated by 90°.

Till date, I did not find any very simple solution under Linux to simply stabilize (unshake) and/or rotate my day-to-day videos.

Hopefully, thanks to MLT framework, it is possible to use a command line tool melt and some specific plugins (vid.stab to stabilize and affine to rotate) to do the job.

This article explains how to easily post-process any group of video files to :

  • read important metadata
  • rotate video if needed
  • stabilize video if needed
  • transcode it to h264 & aac

It also explains how to integate this tool straight from your desktop menu and from Nautilus. A simple right click on a video file will show a menu to post-process it !

If you don't need any technical explanation and you  just want to stabilize your video straight from Nautilus file manager, you can jump to Complete installation procedure. It will provide a complete and simple installation script.

Following procedures have been designed and tested on Ubuntu Gnome Trusty 14.04 LTS. It should be applicable to any 14.04+ Ubuntu distro.
It has also been tested on Fedora 20 & 21 (even if package installation is not applicable).

1. Needed Packages

The stabilization script needs to use melt 0.9.2+ as this is the first version to come with a vidstab plugin. With prior versions, you'll only get deprecated videostab2 and videostab filters.

It uses a dynamically linked library called vid.stab. This library should be installed and from latest vid.stab version 0.98+.

Under Ubuntu, these up-to-date packages are provided by PPA sunab/kdenlive-release. At the time of this article, it provides following releases : melt 0.9.3 and vid.stab library 0.98b.

Another advantage of using versions provided by this PPA is that they are compiled with avconv instead of ffmpeg. And avconv replaces ffmpeg in modern Ubuntu distro ...

Terminal
# sudo add-apt-repository ppa:sunab/kdenlive-release
# sudo apt-get update
# sudo apt-get install libvidstab1.0 x264 melt

YAD (Yet Another Dialog) is a fork of Zenity with many improvements, such as custom buttons, additional dialogs, pop-up menu in notification icon and more.

We will be using YAD advanced capabilities in the main transcoding script.

As it is not available in Ubuntu official repositories, we need to install it thru PPA WebUpd8.

Terminal
# sudo add-apt-repository ppa:webupd8team/y-ppa-manager
# sudo apt-get update
# sudo apt-get install yad

To collect metadata from original video file (like rotation, width, height, ...) we will use exiftool.

x264 will be used to handle h264 transcoding.

opencv-data package is not strictly needed, but it may avoid some strange missing depencies errors that have been encountered by few people.

All these packages are available from official repositories :

Terminal
# sudo apt-get install libimage-exiftool-perl x264 opencv-data

2. How to Rotate & Stabilize your Video

We now have everything to rotate and unshake our video files.

The section explains how to process files thru command line, in a step-by-step approach.

In case of trouble with the automatic script, this section will also help you to point out where the problem can be.

The stabilization process is done in 3 steps :

2.1. Collect Video Metadata

First step is done with the help of exiftool.

This tool analyse the video file and extract important metadata like image width & height or rotation tag.

Terminal
# exiftool -s3 -rotation -imagewidth -imageheight -avgbitrate input.mp4
90
1920
1080
19.1 Mbps

This video is 1920x1080, with average bitrate of 19.1 Mbits/s and is 90° rotated (it has been taken from a smartphone held vertically).

2.2. Calculate Stabilization parameters

Next step is done with the help of melt tool.

The command line tool is provided with MLT framework and it provides use 2 very powerful plugins :

  • affine to rotate & resize video if needed
  • vidstab to calculate stabilization correction parameters

You can check what stabilization plugin is available from your melt client :

Terminal
# melt -query filters | grep stab
- videostab
- videostab2
- vidstab

Following command will start the stabilization analysis using vidstab plugin and will generate a input.mlt XML file, containing all the processing parameters :

Terminal
# melt input.mp4 -filter affinetransition.fix_rotate_x=450transition.scale_x=1transition.scale_y=1 -filter vidstab shakiness=8 smoothing=20 -consumer xml:input.mlt all=1

affine filter parameters are in blue. This filter recognises some specific parameters described in MLT Affine filter page. For example here :

  • transition.fix_rotate_x : rotation angle in degre x 5 (90° becomes 450). Don't ask me why !
  • transition.scale_x & transition.scale_y : scaling factor to apply when rotating a rectangular video to fit the largest size in the smallest one.

vidstab filter parameters are in red. This filter recognises some specific parameters described in MLT Vidstab filter page. For example here :

  • shakiness
  • smoothing

If vidstab plugin is not available, you can use videostab2 or videostab plugins. But quality of stabilization algorithm won't the same.

2.3. Encode Final Video

Once the input.mlt file is available, we can start the final encoding with melt second pass.

This second pass will encode the final video with the results of the first analysis pass.

For the final video, we will use :

  • video from previous stage processing
  • audio from original video

In this example, the final video will be encoded with h264 video at 5 Mbits and aac audio at 128 Kbits.

Terminal
# melt input.mlt -audio-track input.mp4 -consumer avformat:input-stab.mp4 vcodec=libx264 b=5000k acodec=aac ab=128k tune=film preset=slow

Specific x264 encoding parameters can be added at the end of the command line. Here I've added a  tune=film preset=slow parameter.

All available parameters can be found with the command x264 --fullhelp.

You now have a input-stab.mp4 file with your stabilized video !

3. Automated script

Now that we've done a stabilization process thru command line, we can create a script which will be in charge of :

  • selection of stabilization and encoding parameters
  • encoding with stabilization

Before processing the video file, you will get a dialog box to precisely define rotation & stabilization parameters.

ubuntu-video-stabilize-options

During processing, a progress dialog box keeps you informed with the video file transcoding progression.

ubuntu-video-stabilize-analyse

ubuntu-video-stabilize-encode

You can cancel the processing at any time.

Main stabilization script algorithm is quite simple :

  1. It checks that all needed tools are available
  2. It analyses all input videos to extract important metadata
  3. It asks you to define main parameters for every input video
  4. It calculates the rotation and/or stabilization parameters
  5. It encodes all final videos in a mp4 container with h264 video & aac audio

3.1. Script

Processing of input video files is done by one main script /usr/local/bin/video-stabilize .

/usr/local/bin/video-stabilize
#!/bin/bash
# -------------------------------------------------------
#  Video Stabilizer based on MLT and vid.stab
#  For installation instructions, please check
#  http://bernaerts.dyndns.org/linux/74-ubuntu/329-ubuntu-trusty-rotate-stabilize-video-melt-vidstab
#  
#  Depends on :
#    * melt (from ppa:sunab/kdenlive-release)
#    * vidstab (libvidstab1.0 package from ppa:sunab/kdenlive-release)
#    * yad (from ppa:webupd8team/y-ppa-manager)
#    * exiftool (from libimage-exiftool-perl package)
#    * avconv
#    * x264
#
#  Revision history :
#    04/03/2012, V1.0 - Creation by N. Bernaerts
#    04/04/2012, V1.1 - Add codecs as parameters
#    17/01/2015, V2.0 - Completle rewrite for Ubuntu 14.04 LTS 
#                       Handle rotation as well thanks to Guy Eagling
#    19/01/2015, V2.1 - Manage per process .trf file to allow parallel execution
#    19/01/2015, V2.2 - Add .pid file to handle processing cancellation
#    23/01/2015, V3.0 - Check tools availability, 
#                       Detect available stabilization filters (vidstab, videostab2 or videostab)
#                       Add Fedora compatibility (mlt-melt) thanks to Guy Eagling
#    06/03/2015, V3.1 - Externalize parameters to ~/.config/video-stabilize.conf
#                       Add multiple files processing thanks to Hingo's idea
#    10/03/2015, V3.2 - Update exiftool handling for MKV files
#    12/03/2015, V3.3 - Add extra parameters to dialog box 
#                       Change progress calculation to avoid errors
#    29/05/2015, V3.4 - Check presence of ~/.config/video-stabilize.conf 
#    26/07/2015, V3.5 - Change options of first pass to avoid some errors (thanks to Gustavo Lapido Loureiro)
#                       Add number of thread as encoder option
#                       Kill process and parent process in case of cancellation
#    22/09/2015, V3.6 - Correction of a bug in final encoding options (thanks to Ted Bartlett)
#    21/02/2016, V3.7 - Handle scientific notation for video rate (thanks to Aslanex)
# -------------------------------------------------------

# -------------------------------------------------
#          Check tools availability
# -------------------------------------------------

# check melt (ubuntu) or mlt-melt (fedora)
CMD_MELT="melt"
command -v $CMD_MELT >/dev/null 2>&1 || { CMD_MELT="mlt-melt"; }
command -v $CMD_MELT >/dev/null 2>&1 || { zenity --error --text="Please install Melt from MLT framework"; exit 1; }

# check yad, exiftool and x264
command -v yad >/dev/null 2>&1 || { zenity --error --text="Please install Yad"; exit 1; }
command -v exiftool >/dev/null 2>&1 || { zenity --error --text="Please install ExifTool"; exit 1; }
command -v x264 >/dev/null 2>&1 || { zenity --error --text="Please install x264"; exit 1; }

# -------------------------------------------------------
#      Read parameters from configuration file
# -------------------------------------------------------

# Configuration file : ~/.config/video-stabilize.conf
FILE_CONF="$HOME/.config/video-stabilize.conf"

# check configuration file
[ -f "$FILE_CONF" ] || { zenity --error --text="Please create and configure ${FILE_CONF}"; exit 1; }

# Load configuration file
ARR_EXT=($(cat "${FILE_CONF}" | grep "extension" | cut -d'=' -f 2- | cut -d ";" --output-delimiter=" " -f 1-))
STAB_SHAKINESS=$(cat "${FILE_CONF}" | grep "shakiness" | cut -d'=' -f2)
STAB_SMOOTHING=$(cat "${FILE_CONF}" | grep "smoothing" | cut -d'=' -f2)
STAB_OPTZOOM=$(cat "${FILE_CONF}" | grep "optzoom" | cut -d'=' -f2)
STAB_EXTRA=$(cat "${FILE_CONF}" | grep "extra" | cut -d'=' -f2-)
VIDEO_CODEC=$(cat "${FILE_CONF}" | grep "video-codec" | cut -d'=' -f2)
AUDIO_CODEC=$(cat "${FILE_CONF}" | grep "audio-codec" | cut -d'=' -f2)
VIDEO_RATE=$(cat "${FILE_CONF}" | grep "video-rate" | cut -d'=' -f2)
AUDIO_RATE=$(cat "${FILE_CONF}" | grep "audio-rate" | cut -d'=' -f2)
ENCODE_OPTION=$(cat "${FILE_CONF}" | grep "option" | cut -d'=' -f2-)
ENCODE_THREAD=$(cat "${FILE_CONF}" | grep "thread" | cut -d'=' -f2-)

# -------------------------------------------------------
#          Retrieve or select video file
# -------------------------------------------------------

IFS=$'\n'

# loop thru arguments to check that they are video files
for arg
do
  # get file name and extension
  FILE_PATH="$arg"
  FILE_EXT=$(echo "${FILE_PATH}" | sed 's/^.*\.\(.*\)$/\1/')

  # check if file extension given in parameter is in the allowed extension list
  [ -f "$FILE_PATH" ] && EXT_OK=$(echo "${ARR_EXT[@]}" | grep --ignore-case ${FILE_EXT}) || EXT_OK=""

  # if ok, add it to the video files array
  [ -n "$EXT_OK" ] && ARR_VIDEO=("${ARR_VIDEO[@]}" "${FILE_PATH}")
done

# if there is no candidate files
if [ ${#ARR_VIDEO[@]} -eq 0 ]
then
  # generate allowed extension list
  LIST_EXT=$(echo "*.${ARR_EXT[@]}" | sed 's/ / *\./g')

  # open multiple files selection dialog box
  LST_VIDEO=$(yad --center --width=800 --height=500 --window-icon "video" --image "stabilizer" \
                  --file --multiple --file-filter="Video file (${LIST_EXT[@]})|${LIST_EXT[@]}" \
                  --title="Select video file to stabilize")

  # generate video files array
  ARR_VIDEO=($(echo "${LST_VIDEO}" | tr "|" "\n"))
fi 

# ---------------------------------------------------------
#   Analyse video files and select processing parameters
# ---------------------------------------------------------

# loop thru selected video files
for FILE_PATH in "${ARR_VIDEO[@]}"
do
  # generate temporary exif file
  FILE_EXIF=$(mktemp -t stab-XXXXXXXX.exif)

  # get video metadata
  exiftool "${FILE_PATH}" > ${FILE_EXIF}
  FILE_WIDTH=$(cat ${FILE_EXIF} | grep "^Image Width" | cut -d':' -f2 | xargs)
  FILE_HEIGHT=$(cat ${FILE_EXIF} | grep "^Image Height" | cut -d':' -f2 | xargs)
  FILE_BITRATE=$(cat ${FILE_EXIF} | grep "^Avg Bitrate" | cut -d':' -f2 | xargs)
  FILE_ROTATE=$(cat ${FILE_EXIF} | grep "^Rotation" | cut -d':' -f2 | xargs)
  [ "${FILE_BITRATE}" == "" ] && FILE_BITRATE="Unknown"
  [ "${FILE_ROTATE}" == "" ] && FILE_ROTATE="0"

  # remove temporary exif file
  rm ${FILE_EXIF}

  # get encoding parameters using local number decimal separator (, or .)
  SEPARATOR=$(printf "%'.2f" 1 | sed 's/^1\(.\).*$/\1/')
  VIDEO_RATIO=$(echo "scale=2; ${FILE_WIDTH} / ${FILE_HEIGHT}" | bc | sed 's/[\.\,]/'${SEPARATOR}'/g')
  [ "$FILE_ROTATE" = "0" -o "$FILE_ROTATE" = "180" ] && LST_RATIO="1|${VIDEO_RATIO}" || LST_RATIO="${VIDEO_RATIO}|1" 

  # detect if rotation needed
  [ "$FILE_ROTATE" = "0" ] && CHECK_ROTATE="FALSE" || CHECK_ROTATE="TRUE"

  # set title and text of dialog box
  TITLE="${FILE_PATH}"
  TEXT="Select transformation parameters :\n ( size = ${FILE_WIDTH}x${FILE_HEIGHT}, rate = ${FILE_BITRATE} )\n"

  # get list of stabilization filters available from current melt version
  ARR_FILTER=$(${CMD_MELT} -query filters | grep stab | awk '{print $2}' | sort -r)
  LST_FILTER=$(echo ${ARR_FILTER} | sed 's/ /|/g')

  # display dialog box
  CHOICE=$(yad --title "${TITLE}" --text "${TEXT}" --center --window-icon "video" --image "stabilizer" --width 500 \
    --form --item-separator='|' \
    --field="Rotate:CHK" "${CHECK_ROTATE}" \
    --field="  - Angle (${FILE_ROTATE}° detected):NUM" "${FILE_ROTATE}|0..359" \
    --field="  - Resize ratio (${VIDEO_RATIO} for 90°):CB" "${LST_RATIO}" \
    --field="Stabilize:CHK" "TRUE" \
    --field="  - Stabilization filter:CB" "${LST_FILTER}" \
    --field="  - Shakiness [ 0 ... 10 ]:NUM" "${STAB_SHAKINESS}|1..10" \
    --field="  - Smoothing [ 0 ... 100 ]:NUM" "${STAB_SMOOTHING}|0..100"  \
    --field="  - Optimal Zoom [ 0, 1, 2 ]:NUM" "${STAB_OPTZOOM}|0..2" \
    --field="  - Extra stabilize options" "${STAB_EXTRA}" \
    --field="Encoder:LBL" "final" \
    --field="  - ${VIDEO_CODEC} video bitrate (Kbits/s):NUM" "${VIDEO_RATE}|1..50000|100" \
    --field="  - ${AUDIO_CODEC} audio bitrate (Kbits/s):NUM" "${AUDIO_RATE}|1..320" \
    --field="  - Extra encoder parameters" "${ENCODE_OPTION}" )

  # retrieve parameters
  ROTATE=$(echo ${CHOICE} | cut -d'|' -f1)
  ROTATE_ANGLE=$(echo ${CHOICE} | cut -d'|' -f2)
  ROTATE_RATIO=$(echo ${CHOICE} | cut -d'|' -f3)
  STABILIZE=$(echo ${CHOICE} | cut -d'|' -f4)
  STAB_FILTER=$(echo ${CHOICE} | cut -d'|' -f5)
  STAB_SHAKINESS=$(echo ${CHOICE} | cut -d'|' -f6)
  STAB_SMOOTHING=$(echo ${CHOICE} | cut -d'|' -f7)
  STAB_OPTZOOM=$(echo ${CHOICE} | cut -d'|' -f8)
  STAB_EXTRA=$(echo ${CHOICE} | cut -d'|' -f9)
  VIDEO_RATE=$(echo ${CHOICE} | cut -d'|' -f11 | tr ',' '.' | awk '{ print sprintf("%.0f", $1); }')
  AUDIO_RATE=$(echo ${CHOICE} | cut -d'|' -f12)
  ENCODE_OPTION=$(echo ${CHOICE} | cut -d'|' -f13)

  # if it is needed, add file to processing queue
  if [ "$STABILIZE" = "TRUE" ] || [ "$ROTATE" = "TRUE" ];
  then
    ARR_FILE=("${ARR_FILE[@]}" "${FILE_PATH}")
    ARR_ROTATE=("${ARR_ROTATE[@]}" "${ROTATE}")
    ARR_ROTATE_ANGLE=("${ARR_ROTATE_ANGLE[@]}" "${ROTATE_ANGLE}")
    ARR_ROTATE_RATIO=("${ARR_ROTATE_RATIO[@]}" "${ROTATE_RATIO}")
    ARR_STABILIZE=("${ARR_STABILIZE[@]}" "${STABILIZE}")
    ARR_STAB_FILTER=("${ARR_STAB_FILTER[@]}" "${STAB_FILTER}")
    ARR_STAB_SHAKINESS=("${ARR_STAB_SHAKINESS[@]}" "${STAB_SHAKINESS}")
    ARR_STAB_SMOOTHING=("${ARR_STAB_SMOOTHING[@]}" "${STAB_SMOOTHING}")
    ARR_STAB_OPTZOOM=("${ARR_STAB_OPTZOOM[@]}" "${STAB_OPTZOOM}")
    ARR_STAB_EXTRA=("${ARR_STAB_EXTRA[@]}" "${STAB_EXTRA}")
    ARR_VIDEO_RATE=("${ARR_VIDEO_RATE[@]}" "${VIDEO_RATE}")
    ARR_AUDIO_RATE=("${ARR_AUDIO_RATE[@]}" "${AUDIO_RATE}")
    ARR_ENCODE_OPTION=("${ARR_ENCODE_OPTION[@]}" "${ENCODE_OPTION}")
  fi
done

# -------------------------------------------------------
#     Process files for rotation and stabilization 
# -------------------------------------------------------

# loop thru video files to process
NUM_FILE=${#ARR_FILE[@]}
for ((INDEX=0; INDEX < NUM_FILE; INDEX++))
do
  # --------------------------------
  #         Get file data
  # --------------------------------
  # get current file path 
  FILE_PATH="${ARR_FILE[$INDEX]}"

  # generate the filenames
  FILE_BASE="$(echo "${FILE_PATH}" | sed 's/^\(.*\)\..*$/\1/')"
  FILE_STAB="${FILE_BASE}-stab.mp4"

  # generate temporary files
  DIR_TMP=$(mktemp -d "$HOME/.stab-XXXXXXXX")
  FILE_TRF="${DIR_TMP}/video.trf"
  FILE_PID="${DIR_TMP}/video.pid"
  FILE_MLT="${DIR_TMP}/video.mlt"
  FILE_LOG="${DIR_TMP}/video.log"

  # get parameters
  ROTATE="${ARR_ROTATE[$INDEX]}"
  ROTATE_ANGLE="${ARR_ROTATE_ANGLE[$INDEX]}"
  ROTATE_RATIO="${ARR_ROTATE_RATIO[$INDEX]}"
  STABILIZE="${ARR_STABILIZE[$INDEX]}"
  STAB_FILTER="${ARR_STAB_FILTER[$INDEX]}"
  STAB_SHAKINESS="${ARR_STAB_SHAKINESS[$INDEX]}"
  STAB_SMOOTHING="${ARR_STAB_SMOOTHING[$INDEX]}"
  STAB_OPTZOOM="${ARR_STAB_OPTZOOM[$INDEX]}"
  STAB_EXTRA="${ARR_STAB_EXTRA[$INDEX]}"
  VIDEO_RATE="${ARR_VIDEO_RATE[$INDEX]}"
  AUDIO_RATE="${ARR_AUDIO_RATE[$INDEX]}"
  ENCODE_OPTION="${ARR_ENCODE_OPTION[$INDEX]}"

  (
  # initilize transformation arrays
  unset ARR_STABILIZE
  unset ARR_ROTATE
  unset ARR_ENCODE

  # ------------------------------------------------
  #    PREPARATION : Setup processing parameters
  # ------------------------------------------------

  # initial display
  echo "# Computing parameters"
  echo "0"

  # if needed, generate stabilizer parameters array
  ARR_EXTRA=($(echo "${STAB_EXTRA}" | cut -d ";" --output-delimiter=" " -f 1-))
  [ "$STABILIZE" = "TRUE" ] && ARR_STABILIZE=("-filter" "${STAB_FILTER}" "filename=${FILE_TRF}" "shakiness=${STAB_SHAKINESS}" \
                                              "smoothing=${STAB_SMOOTHING}" "optzoom=${STAB_OPTZOOM}" "${ARR_EXTRA[@]}")

  # if needed, set rotation filter
  if [ "$ROTATE" = "TRUE" ]
  then
    # convert angle for filter use
    X_ANGLE=$((10 * ${ROTATE_ANGLE} / 2))

    # set rotation filter
    ARR_ROTATE=("-filter" "affine" "transition.fix_rotate_x=${X_ANGLE}")

    # if different than 1, set transformation ratio
    [ "${ROTATE_RATIO}" != "1" ] && ARR_ROTATE=("${ARR_ROTATE[@]}" "transition.scale_x=${ROTATE_RATIO}" "transition.scale_y=${ROTATE_RATIO}")
  fi

  # ----------------------------------------------
  #   PASS 1 : Rotation / Stabilization analysis
  # ----------------------------------------------

  # information display
  echo "# Analysing file"

  # launch analysis command
  ${CMD_MELT} -progress "${FILE_PATH}" ${ARR_ROTATE[@]} ${ARR_STABILIZE[@]} -consumer xml:"${FILE_MLT}" all=1 2>"${FILE_LOG}" &

  # save current process and melt command process id
  PID=$(ps aux | grep "${CMD_MELT}" | grep "${FILE_PATH}" | awk '{print $2}')
  echo "${BASHPID}" > "${FILE_PID}"
  echo "${PID}" >> "${FILE_PID}"

  while [ "$PID" != "" ] 
  do    
    # check if process is still running
    PID=$(ps aux | awk '{print $2}' | grep ${PID})

    # calculate process completion
    LOG_LINE="$(tail --bytes=50 ${FILE_LOG} | grep 'Frame' | grep 'percentage')"
    LOG_FRAME=$(echo "${LOG_LINE}" | sed 's/^.*Frame[ :]*\([0-9]*\).*$/\1/')
    LOG_PERCENT=$(echo "${LOG_LINE}" | sed 's/^.*percentage[ :]*\([0-9]*\).*$/\1/')

    # if percentage has been retrieved from log, display process completion
    [[ ${LOG_FRAME} == +([0-9]) ]] && echo "# Analysing frame ${LOG_FRAME}"
    [[ ${LOG_PERCENT} == +([0-9]) ]] && echo $((${LOG_PERCENT} / 2))

    # wait for 2 seconds
    sleep 2
  done

  # ------------------------------------------
  #   PASS 2 : Final result encoding
  # ------------------------------------------

  # information display
  echo "# Generating file"

  # generate encoder parameters array
  ARR_OPTION=($(echo "${ENCODE_OPTION}" | cut -d ";" --output-delimiter=" " -f 1-))
  ARR_ENCODE=("vcodec=${VIDEO_CODEC}" "b=${VIDEO_RATE}k" "acodec=${AUDIO_CODEC}" "ab=${AUDIO_RATE}k" "${ARR_OPTION[@]}" )

  # launch generation command
  ${CMD_MELT} -progress "${FILE_MLT}" -audio-track "${FILE_PATH}" -consumer avformat:"${FILE_STAB}" ${ARR_ENCODE[@]} real_time=-${ENCODE_THREAD} 2>"${FILE_LOG}" &

  # save current process and melt command process id
  PID=$(ps aux | grep "${CMD_MELT}" | grep "${FILE_MLT}" | awk '{print $2}')
  echo "${BASHPID}" > "${FILE_PID}"
  echo "${PID}" >> "${FILE_PID}"

  # follow the stabilization progress
  while [ "$PID" != "" ] 
  do    
    # check if process is still running
    PID=$(ps aux | awk '{print $2}' | grep ${PID})

    # calculate process completion
    LOG_LINE="$(tail --bytes=50 ${FILE_LOG} | grep 'Frame' | grep 'percentage')"
    LOG_FRAME=$(echo "${LOG_LINE}" | sed 's/^.*Frame[ :]*\([0-9]*\).*$/\1/')
    LOG_PERCENT=$(echo "${LOG_LINE}" | sed 's/^.*percentage[ :]*\([0-9]*\).*$/\1/')

    # if percentage has been retrieved from log, display process completion
    [[ ${LOG_FRAME} == +([0-9]) ]] && echo "# Generating frame ${LOG_FRAME}"
    [[ ${LOG_PERCENT} == +([0-9]) ]] && echo $((50 + (${LOG_PERCENT} / 2)))

    # wait for 2 seconds
    sleep 2
  done

  # remove PID file
  rm "${FILE_PID}"

  # declare end of processing
  echo "# File processed and available"
  echo "100"
  ) | yad --center --width=600 --window-icon "video" --image "stabilizer" --progress --auto-close --title "[$((${INDEX} + 1))/${NUM_FILE}] ${FILE_PATH}"

  # -----------------------------------------
  #   END : Final process and files cleanup
  # -----------------------------------------

  # if process is still running (operation has been canceled), kill the process
  [ -f "${FILE_PID}" ] && kill -9 $( cat "${FILE_PID}" )

  #  cleaning-up of all temporary files
  rm -R ${DIR_TMP}

done

This script uses a configuration file (described below) and its own icon.

To install the script, its default configuration and declare the icon, just run these commands :

Terminal
# mkdir -p $HOME/.config
# wget -O $HOME/.config/video-stabilize.conf https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-stabilize.conf
# sudo wget -O /usr/local/bin/video-stabilize https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/b04669761f49fec81db250d46059b85b7db4fcd3/video/video-stabilize
# sudo chmod +x /usr/local/bin/video-stabilize
# sudo wget -O /usr/share/icons/stabilizer.png https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/stabilizer.png

3.2. Configuration

All important parameters of this script are defined in ~/.config/video-stabilize.conf configuration file.

These parameters include

  • stabilization standard options (shakiness, smoothing, optzoom)
  • stabilization advanced options
  • video & audio codec (should not be modified)
  • video & audio default bitrate
  • x264 advanced options
  • number of threads to use during h264 encoding

~/.config/video-stabilize.conf
[file]
extension=3gp;avi;dv;m4v;mov;mkv;movie;mp4;mpeg;mpg;qt

[stabilize]
shakiness=4
smoothing=15
optzoom=1
extra=show=0;crop=0

[encoder]
video-codec=libx264
audio-codec=aac
video-rate=20000
audio-rate=128
option=tune=film;preset=slow
thread=1

These parameters are quite self explanatory and are coming from vidstab to set stabilization correction parameters and from x264 for h264 encoding .

By default, number of threads to use during final encoding is set to thread=1. If your processor is multi-core, it is advisable to set the number of threads to your number of cores - 1.

You can get your processor number of cores with this simple command :

Terminal
# nproc
4

To modify  if you want to modify any default parameter just edit this file.

4. Desktop Integration

It is now time to fully integrate video rotate & stabilization in your desktop environment.

4.1. Menu declaration

To get Video Rotation and Stabilization tool available from your desktop Application / Sound & Video menu, you just need to declare /usr/share/applications/video-stabilize.desktop.

/usr/share/applications/video-stabilize.desktop
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Exec=/usr/local/bin/video-stabilize
Name=Video rotation and stabilization
Categories=GNOME;AudioVideo;AudioVideoEditing;
MimeType=video/*;
Icon=stabilizer

It will be avaibale from Application / Sound & Video menu.

If you start Video Rotation and Stabilization you'll then be able to :

  • select one or multiple video files
  • set stabilization and encoding parameters for every selected file
  • process every selected file according to its individual parameters

4.2. Nautilus integration

To be able to add extensions to Nautilus right click menu on a file, you need to install nautilus-actions extensions, which is not installed by default under Ubuntu.

{displayconsole class=ubuntu}# sudo apt-get install nautilus-actions {/displayfile}

You will then be able to start the auto-rotation & stabilization of any video file from a simple right click in Nautilus.

ubuntu-video-stabilize-menu

Then, to get a right click menu entry on any video file from Nautilus, you need to declare ~/.local/share/file-manager/actions/video-stabilize-action.desktop specific action.

~/.local/share/file-manager/actions/video-stabilize-action.desktop
[Desktop Entry]
Type=Action
Icon=stabilizer
Name[C]=Rotation and stabilization
Name[en]=Rotation and stabilization
Name[en_US]=Rotation and stabilization
Name[fr_FR]=Rotation et stabilisation 
Tooltip[C]=Tool to rotate and stabilize video shootings
Tooltip[en]=Tool to rotate and stabilize video shootings
Tooltip[en_US]=Tool to rotate and stabilize video shootings
Tooltip[fr_FR]=Outil de rotation et de stabilisation de video
Profiles=stabilize_video;

[X-Action-Profile stabilize_video]
Exec=video-stabilize %F
MimeTypes=video/*;
Capabilities=Local
Name[C]=Default profile
Name[en]=Default profile
Name[en_US]=Default profile
Name[fr_FR]=Profil par défaut

This will make the Video Rotation and Stabilization tool accessible from the right menu on any video file whose mimetypes is declared in the .desktop file.

To install the package and declare the .desktop files, just run these commands :

Terminal
# sudo wget -O /usr/share/applications/video-stabilize.desktop https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-stabilize.desktop
# mkdir --parents $HOME/.local/share/file-manager/actions
# wget -O $HOME/.local/share/file-manager/actions/video-stabilize-action.desktop https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-stabilize-action.desktop

5. Complete installation procedure

If you want to install all needed tools and configuration files in one go, you can run an all-in-one installation script.

This script has been written for Ubuntu 14.04. It will do whatever operation have been described earlier in this article.

Terminal
# wget https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-stabilize-install.sh
# chmod +x video-stabilize-install.sh
# ./video-stabilize-install.sh

After next login, you should be able to rotate, stabilize and re-encode your video files from a simple right click.

In case you detect any bug or if you have some update ideas which can benefit everybody, don't hesitate to contact me by email or to fork it on GitHub.

Hope it helps.

Signature Technoblog

This article is published "as is", without any warranty that it will work for your specific need.
If you think this article needs some complement, or simply if you think it saved you lots of time & trouble,
just let me know at This email address is being protected from spambots. You need JavaScript enabled to view it.. Cheers !

icon linux icon debian icon apache icon mysql icon php icon piwik icon googleplus