Search


Warning: file(https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-convert2mkvaac.desktop): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /mnt/data/home/www/www-bernaerts/plugins/content/displayfile/displayfile.php on line 121

Warning: Invalid argument supplied for foreach() in /mnt/data/home/www/www-bernaerts/plugins/content/displayfile/displayfile.php on line 123

Warning: file(https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-convert2mkvaac-action.desktop): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /mnt/data/home/www/www-bernaerts/plugins/content/displayfile/displayfile.php on line 121

Warning: Invalid argument supplied for foreach() in /mnt/data/home/www/www-bernaerts/plugins/content/displayfile/displayfile.php on line 123

Ubuntu - Transcode your video to MKV / AAC the simple way

Contents[Hide]

dropcap-ubuntu-stabilize

If you sometimes end up grabbing some video files from internet, you may have encountered some playback troubles :

  • Video container may not be playable on some devices (AVI, MOV, ...)
  • Some copyrighted audio codecs like DTS, AC3, E-AC3, ... may give play back problem on some of your devices
  • On multi-channels audio tracks, general audio level may vary widely between talks and action scenes (you end up changing volume level at every scene change)

So, to be able to play your video on any type of device and in any type of environment, an elegant option is to :

  • use MKV container as it is open source and recognized by almost all modern players
  • convert all audio tracks to AAC as it is playable on almost any modern devices
  • add some midnight mode audio channels side to the multi-tracks channels to allow smooth listening even without a home cinema system

This article explains how to setup a post-processing environment for your Linux desktop to be able to :

  • generate MKV video file from any video file
  • convert all audio tracks to AAC format (stereo and multi-channels)
  • add some associated Midnight Mode audio tracks (if selected)
  • add an embedded video cover (if present)

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

It has been designed and tested on an Ubuntu 14.04 LTS workstation, but it should be applicable to any Linux distribution, as long as the needed tools are available.

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

1. Install Packages

Main transcoding script uses various tools :

  • yad, a fork of zenity, to display advanced selection dialog boxes
  • mediainfo to read video files characteristics
  • avconv to convert audio tracks to plain WAV
  • sox (a sound processing swiss army knife) to generate midnightmode audio tracks by applying DRC and normalization
  • fdkaac (based on fdk-aac) to transcode audio tracks to ACC (best transcoder at the time of this article)
  • mkvmerge to extract audio tracks and to multiplex final MKV file

As yad 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

Same operation with fdkaac, which is not yet available in Ubuntu official repositories.

Terminal
# sudo add-apt-repository -y ppa:mc3man/fdkaac-encoder
# sudo apt-get update
# sudo apt-get install fdkaac-encoder aac-enc

All other tools are available in official repositories and can be directly installed :

Terminal
# sudo apt-get install mediainfo libav-tools sox mkvtoolnix

2. Transcoding script

We now have everything to transcode audio tracks embedded in various video files and to generate some midnight mode version of these tracks.

Audio tracks transcoding procedure is following these simple steps :

  • it checks all tools availability
  • if no input file is given, it proposes a file selection dialog box
  • it allows to select encoding rates (different if stereo, multi-channels or midnight mode)
  • if already AAC, tracks are kept untouched
  • if not AAC, audio tracks are transcoded to AAC
  • if selected, midnight mode tracks are generated side to the original ones
  • all audio tracks are multiplexed back to a final MKV file

ubuntu mkvaac select parameters

For embedded tracks other than audio, behaviour is as follow :

  • all subtitle tracks are kept untouched
  • all attachments are removed
  • if a video cover is found, it is added as a "cover" attachment
  • general video name is deduced from the filename

When looking for video cover, the script looks for an image file in video file directory in this order :

  1. VideoFilename.tbn
  2. cover.jpg
  3. folder.jpg

Transcoding script provides a different behaviour when launched with a single video file or with multiple files to process :

  • In case of a single file, it allows a fine tuning of audio tracks. It proposes you to keep or drop original audio tracks (they will be transcoded if non AAC) and it offers the possibilty to select whichever audio track should be transcoded as a complementary midnight mode track.
  • In case of multiple files, no selection is available. It works in batch mode. All audio tracks are processed and converted to ACC and no midnight mode complementary track is generated.

ubuntu mkvaac select tracks

During transcoding process (which may takes a long time according to number of tracks to convert), a progress dialog keeps you informed of current step.

ubuntu mkvaac progress

Main default parameters are defined in ~/.config/video-convert2mkvaac.conf configuration file.

Parameters are self explanatory :

  • different encoding rates (in kbits/s)
  • video cover extension

So if you want to modify any default parameter, just edit this file before running the tool.

~/.config/video-convert2mkvaac.conf
[rate]
available=64|128|160|192|256|384
midnight=160
stereo=192
multi=384

[cover]
extension=tbn

Transcoding script should be placed under /usr/local/bin/video-convert2mkvaac :

/usr/local/bin/video-convert2mkvaac
#!/usr/bin/env bash
# -------------------------------------------------------
#  Convert video to MKV container and
#   transcode audio to AAC with optionnal midnight mode audio track
#  
#  Usage is explained at http://www.bernaerts-nicolas.fr/linux/74-ubuntu/336-ubuntu-transcode-video-mkv-aac-nautilus
#
#  Depends on :
#    * yad
#    * mediainfo
#    * ffmpeg
#    * sox
#    * fdkaac
#    * mkvmerge (mkvtoolnix)
#  
#  Revision history :
#    23/01/2015, V1.0 - Creation by N. Bernaerts
#    24/01/2015, V1.1 - Properly handle progress cancellation
#                       Change video file detection algorithm
#    19/07/2015, V2.0 - Handle multiple file selection
#                       Add GUI mode to select tracks
#                       and to add midnight mode tracks
#    20/07/2015, V2.1 - Switch to YAD and select rates
#    12/12/2015, V2.2 - Make track langage editable
#    13/12/2015, V2.3 - Add default track selection
#    18/12/2015, V2.4 - Correct nasty bug with PID < 10000
#    03/06/2016, V2.5 - Remove any multi-threaded option to avoid audio time shift
#    05/06/2016, V2.6 - Add audio tracks description
#    05/08/2018, V2.7 - Switch to ffmpeg instead of avconv
#    26/05/2020, V2.8 - Ubuntu Focal 20.04 compatibility
#    30/05/2020, V3.0 - Rewrite mediainfo data extraction
# -------------------------------------------------------

# ------------------
#   Parameters
# ------------------

# if no argument, display help
if [ $# -eq 0 ] 
then
  echo "Convert video to MKV container and"
  echo "transcode audio to AAC with optionnal midnight mode audio track"
  echo "Parameters are :"
  echo "  --video <file>      Video file"
  exit
fi

# loop to retrieve arguments
while test $# -gt 0
do
  case "$1" in
    "--video") shift; FILE_VIDEO="$1"; shift; ;;
    *) shift; ;;
   esac
done

# check inut file
[ "${FILE_VIDEO}" = "" ] && { zenity --error --width=500 --text="Video file compulsory (--file)"; exit 1; }

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

# check mediainfo, mkvmerge, ffmpeg and fdkaac
command -v yad >/dev/null 2>&1 || { zenity --error --text="Please install yad [yad from ppa:webupd8team/y-ppa-manager]"; exit 1; }
command -v mediainfo >/dev/null 2>&1 || { zenity --error --text="Please install mediainfo"; exit 1; }
command -v ffmpeg >/dev/null 2>&1 || { zenity --error --text="Please install ffmpeg"; exit 1; }
command -v sox >/dev/null 2>&1 || { zenity --error --text="Please install sox"; exit 1; }
command -v fdkaac >/dev/null 2>&1 || { zenity --error --text="Please install fdkaac [fdkaac-encoder from ppa:mc3man/fdkaac-encoder]"; exit 1; }
command -v mkvmerge >/dev/null 2>&1 || { zenity --error --text="Please install mkvmerge [mkvtoolnix]"; exit 1; }

# -----------------------
#   Generate file names
# -----------------------

FILE_DIR=$(dirname "${FILE_VIDEO}")
FILE_BASE=$(basename "${FILE_VIDEO}")
FILE_NAME="${FILE_BASE%.*}"
FILE_EXT="${FILE_BASE##*.}"

FILE_MKV="${FILE_DIR}/${FILE_NAME}.mkv"

FILE_COVER="${FILE_DIR}/${FILE_NAME}.${COVER_EXT}"
[ -f "${FILE_COVER}" ] || FILE_COVER="${FILE_DIR}/cover.jpg"
[ -f "${FILE_COVER}" ] || FILE_COVER="${FILE_DIR}/folder.jpg"

# generate temporary files and directory
TMP_DIR=$(mktemp -t -d "video-XXXXXXXX")
TMP_ORIGINAL="${TMP_DIR}/original.${FILE_EXT}"
TMP_TARGET="${TMP_DIR}/target.mkv"
TMP_INFO="${TMP_DIR}/info.txt"
TMP_AUDIO="${TMP_DIR}/audio.txt"

# ---------------------
#  Read configuration
# ---------------------

# Configuration file : ~/.config/video-convert2mkvaac.conf
FILE_CONF="$HOME/.config/video-convert2mkvaac.conf"
[ -f "$FILE_CONF" ] || { zenity --error --text="Please create and configure ${FILE_CONF}"; exit 1; }

# Load configuration
RATE_AVAILABLE=$(cat "${FILE_CONF}" | grep "available" | cut -d'=' -f2)
RATE_DRC=$(cat "${FILE_CONF}" | grep "midnight" | cut -d'=' -f2)
RATE_STEREO=$(cat "${FILE_CONF}" | grep "stereo" | cut -d'=' -f2)
RATE_MULTI=$(cat "${FILE_CONF}" | grep "multi" | cut -d'=' -f2)
COVER_EXT=$(cat "${FILE_CONF}" | grep "extension" | cut -d'=' -f2)

# -------------------------
#   Select encoding rates
# -------------------------

# set main parameters
ARR_PARAM_CONFIG=( "--field=File:RO" "${FILE_BASE}" "--field=\nTranscode rates (kbits/s)\n:LBL" "rate" "--field=Midnight mode:CB" "${RATE_DRC}|${RATE_AVAILABLE}" "--field=Stereo:CB" "${RATE_STEREO}|${RATE_AVAILABLE}" "--field=Multi channels:CB" "${RATE_MULTI}|${RATE_AVAILABLE}")

# display dialog box selection
CHOICE=$(yad --center --width=400 --height=200 --window-icon "video" --image "video" --title="MKV/AAC multiplexer" --form --item-separator='|' "${ARR_PARAM_CONFIG[@]}")

# get parameters
[ "${CHOICE}" = "" ] && exit 1
RATE=$(echo "${CHOICE}" | cut -d'|' -f3)
[ "${RATE}" != "" ] && RATE_DRC="${RATE}"
RATE=$(echo "${CHOICE}" | cut -d'|' -f4)
[ "${RATE}" != "" ] && RATE_STEREO="${RATE}"
RATE=$(echo "${CHOICE}" | cut -d'|' -f5)
[ "${RATE}" != "" ] && RATE_MULTI="${RATE}"

# ---------------------------------------------------------------------
# variable initialisation
# ---------------------------------------------------------------------

(

#IFS=$'\n'

# initialize file list with original file (for video track)
ARR_FILE=("0:0")

# initialize arrays
ARR_AAC_ID=( )
ARR_PARAM_AAC=( )
ARR_PARAM_AUDIO=( )
ARR_PARAM_COVER=( )

# ----------------------
#   Copy original file
# ----------------------

# copy input file to temporary folder
echo "# Copy of original file ..."
gio copy "${FILE_VIDEO}" "${TMP_ORIGINAL}"

# ----------------------
#   Analyse video file
# ----------------------

# get file properties to check it is a video file
echo "# Check video file"
mediainfo --Output=JSON "${TMP_ORIGINAL}" | xargs | sed "s|@type:|\n|g" > "${TMP_INFO}" 

# extract video data
VIDEO_ID=$(grep " Video," "${TMP_INFO}" | tail -n 1 | tr "," "\n" | grep " ID:" | cut -d ":" -f2 | xargs)
echo "# Video #${VIDEO_ID} detected"

# if file contains a video track
if [ "${VIDEO_ID}" != "" ]
then
    # -----------------------------
    #  extraction of audio tracks
    # -----------------------------

    grep " Audio," "${TMP_INFO}" > "${TMP_AUDIO}"
    while read LINE           
    do 
        TRACK_ID=$(echo "${LINE}" | tr "," "\n" | grep -i " ID:" | cut -d ":" -f2 | xargs)
        TRACK_LANGUAGE=$(echo "${LINE}" | tr "," "\n" | grep -i " Language:" | cut -d ":" -f2 | xargs)
        TRACK_FORMAT=$(echo "${LINE}" | tr "," "\n" | grep -i " Format:" | cut -d ":" -f2 | xargs)
        TRACK_CHANNEL=$(echo "${LINE}" | tr "," "\n" | grep -i " Channels:" | cut -d ":" -f2 | xargs)
        TRACK_RATE=$(echo "${LINE}" | tr "," "\n" | grep -i " BitRate:" | cut -d ":" -f2 | xargs)
        TRACK_DEFAULT=$(echo "${LINE}" | tr "," "\n" | grep -i " Default:" | cut -d ":" -f2 | xargs)
        TRACK_TITLE=$(echo "${LINE}" | tr "," "\n" | grep -i " Title:" | cut -d ":" -f2 | xargs)
        TRACK_DELAY=$(echo "${LINE}" | tr "," "\n" | grep -i " Delayrelativetovideo:" | cut -d ":" -f2 | xargs)

        # format data
        TRACK_ID=$((TRACK_ID - VIDEO_ID));
        [ "${TRACK_LANGUAGE}" = "" ] && TRACK_LANGUAGE="und"
        [ "${TRACK_DELAY}" = "" ] && TRACK_DELAY=0

        echo "# Audio #${TRACK_ID} detected (${TRACK_FORMAT})"
        ARR_TRACK=("${ARR_TRACK[@]}" "${TRACK_ID}|${TRACK_LANGUAGE}|${TRACK_FORMAT}|${TRACK_CHANNEL}|${TRACK_RATE}|${TRACK_DEFAULT}|${TRACK_DELAY}|${TRACK_TITLE}")
    done < "${TMP_AUDIO}"

    # -----------------------------------------
    #  loop to prepare audio tracks selection
    # -----------------------------------------

    ARR_SELECT=( )
    for TRACK in "${ARR_TRACK[@]}"
    do  
        # get track characteristics
        TRACK_ID=$(echo "${TRACK}" | cut -d'|' -f1)
        TRACK_LANGUAGE=$(echo "${TRACK}" | cut -d'|' -f2)
        TRACK_FORMAT=$(echo "${TRACK}" | cut -d'|' -f3)
        TRACK_CHANNEL=$(echo "${TRACK}" | cut -d'|' -f4)
        TRACK_RATE=$(echo "${TRACK}" | cut -d'|' -f5)
        TRACK_DEFAULT=$(echo "${TRACK}" | cut -d'|' -f6)
        TRACK_TITLE=$(echo "${TRACK}" | cut -d'|' -f8)

        # set if track is a default one
        [ "${TRACK_DEFAULT}" = "Yes" ] && TRACK_DEFAULT="TRUE" || TRACK_DEFAULT="FALSE" 

        # add current track to dialog selection array
        ARR_SELECT=("${ARR_SELECT[@]}" "${TRACK_ID}" "${TRACK_DEFAULT}" "TRUE" "FALSE" "${TRACK_LANGUAGE}" "${TRACK_FORMAT}" "${TRACK_CHANNEL}" "${TRACK_RATE}" "${TRACK_TITLE}") 

        # set current track as candidate, without midnight mode and given langage (${TRACK_TITLE})
        ARR_DEFAULT[${TRACK_ID}]="${TRACK_DEFAULT}"
        ARR_LANGAGE[${TRACK_ID}]="${TRACK_LANGAGE}"
        ARR_CANDIDATE[${TRACK_ID}]="TRUE"
        ARR_NIGHTMODE[${TRACK_ID}]="FALSE"
    done

    # dialog box to select audio tracks to mux
    ARR_COLUMN=( "--column=Number:NUM" "--column=Default:RD" "--column=Select:CHK" "--column=Midnight:CHK" "--column=Langage:TEXT" "--column=Format:TEXT" "--column=Channels:NUM" "--column=Rate:NUM" "--column=Description:TEXT" )
    ARR_CHOICE=( $(yad --center --title "${FILE_NAME}" --text="\nSelect tracks to mux in final MKV container\n" --width=800 --height=300 --list --editable --print-all "${ARR_COLUMN[@]}" "${ARR_SELECT[@]}") )

    # if dialog has been canceled, exit
    [ -z "${ARR_CHOICE[0]}" ] && exit 0

    # loop thru choices to setup selected tracks and midnight mode tracks
    for CHOICE in "${ARR_CHOICE[@]}"
    do
        # get choices
        TRACK_ID=$(echo "${CHOICE}" | cut -d'|' -f1)
        TRACK_DEFAULT=$(echo "${CHOICE}" | cut -d'|' -f2)
        TRACK_CANDIDATE=$(echo "${CHOICE}" | cut -d'|' -f3)
        TRACK_NIGHTMODE=$(echo "${CHOICE}" | cut -d'|' -f4)
        TRACK_LANGAGE=$(echo "${CHOICE}" | cut -d'|' -f5)

        # set track as selected and/or midnight mode and given langage
        ARR_DEFAULT[${TRACK_ID}]="${TRACK_DEFAULT}"
        ARR_CANDIDATE[${TRACK_ID}]="${TRACK_CANDIDATE}"
        ARR_NIGHTMODE[${TRACK_ID}]="${TRACK_NIGHTMODE}"
        ARR_LANGAGE[${TRACK_ID}]="${TRACK_LANGAGE}"
    done

    # -----------------------------------------------
    #  apply AAC conversion and DRC to audio tracks
    # -----------------------------------------------
    NEWTRACK_INDEX=1
    for TRACK in "${ARR_TRACK[@]}"
    do
        # get track characteristics
        TRACK_ID=$(echo "${TRACK}" | cut -d'|' -f1)
        TRACK_FORMAT=$(echo "${TRACK}" | cut -d'|' -f3)
        TRACK_CHANNEL=$(echo "${TRACK}" | cut -d'|' -f4)
        TRACK_DELAY=$(echo "${TRACK}" | cut -d'|' -f7)
        TRACK_TITLE=$(echo "${TRACK}" | cut -d'|' -f8)

        # get if track is selected, with midnight mode and its langage
        TRACK_DEFAULT=${ARR_DEFAULT[${TRACK_ID}]}
        TRACK_LANGUAGE=${ARR_LANGAGE[${TRACK_ID}]}
        TRACK_CANDIDATE=${ARR_CANDIDATE[${TRACK_ID}]}
        TRACK_NIGHTMODE=${ARR_NIGHTMODE[${TRACK_ID}]}
    
        # generate temporary filenames
        FILE_TMP_MKA="${TMP_DIR}/${TRACK_ID}.mka"
        FILE_TMP_WAV="${TMP_DIR}/${TRACK_ID}.wav"
        FILE_TMP_AAC="${TMP_DIR}/${TRACK_ID}.m4a"
        FILE_DRC_WAV="${TMP_DIR}/${TRACK_ID}-drc.wav"
        FILE_DRC_AAC="${TMP_DIR}/${TRACK_ID}-drc.m4a"
        FILE_NRM_WAV="${TMP_DIR}/${TRACK_ID}-nrm.wav"

        # if track is selected
        if [ "${TRACK_CANDIDATE}" = "TRUE" ]
        then
            # if format is already AAC, add current track ID to AAC track array
            if [ "${TRACK_FORMAT}" = "AAC" ]
            then
                # add current track ID to the array of AAC tracks
                ARR_AAC_ID=("${ARR_AAC_ID[@]}" "${TRACK_ID}")

                # determine if current track is default audio
                [ "${TRACK_DEFAULT}" = "TRUE" ] && ARR_PARAM_AAC=("${ARR_PARAM_AAC[@]}" "--default-track" "${TRACK_ID}:1") || ARR_PARAM_AAC=("${ARR_PARAM_AAC[@]}" "--default-track" "${TRACK_ID}:0")

                # generate track langage and name option
                ARR_PARAM_AAC=("${ARR_PARAM_AAC[@]}" "--language" "${TRACK_ID}:${TRACK_LANGUAGE}" "--track-name" "${TRACK_ID}:${TRACK_LANGUAGE} (${TRACK_CHANNEL} channels)")
        
                # else format is not AAC, convert it to AAC
            else
                # extract audio track to MKA audio file
                echo "# Audio #${TRACK_ID} : Extraction of ${TRACK_FORMAT} stream"
                mkvmerge -o "${FILE_TMP_MKA}" --no-video --audio-tracks "${TRACK_ID}" --no-subtitles --no-attachments --no-global-tags --no-chapters --no-track-tags --no-buttons "${TMP_ORIGINAL}"

                # convert track to WAV format
                echo "# Audio #${TRACK_ID} : Conversion to WAV"
                ffmpeg -y -i "${FILE_TMP_MKA}" "${FILE_TMP_WAV}"

                # determine encoding rate
                [ $TRACK_CHANNEL -ge 5 ] && TRACK_RATE=$RATE_MULTI || TRACK_RATE=$RATE_STEREO

                # convert WAV file to AAC
                echo "# Audio #${TRACK_ID} : Convertion to AAC (${TRACK_RATE}k)"
                fdkaac -o "${FILE_TMP_AAC}" -b "${TRACK_RATE}k" "${FILE_TMP_WAV}" 

                # determine if current track is default audio
                [ "${TRACK_DEFAULT}" = "TRUE" ] && ARR_PARAM_AUDIO=("${ARR_PARAM_AUDIO[@]}" "--default-track" "0:1") || ARR_PARAM_AUDIO=("${ARR_PARAM_AUDIO[@]}" "--default-track" "0:0")

                # gererate track options for current track
                ARR_PARAM_AUDIO=("${ARR_PARAM_AUDIO[@]}" "--sync" "0:${TRACK_DELAY}" "--language" "0:${TRACK_LANGUAGE}" "--track-name" "0:${TRACK_LANGUAGE} (${TRACK_CHANNEL} channels)" "${FILE_TMP_AAC}")

                # add current audio to the general track order list
                ARR_FILE=("${ARR_FILE[@]}" "${NEWTRACK_INDEX}:0")
                NEWTRACK_INDEX=$((NEWTRACK_INDEX+1))
            fi
        fi

        # if nightmode track is needed, generate AAC stereo night mode track
        if [ "${TRACK_NIGHTMODE}" = "TRUE" ]
        then
            # if not already done, extract audio track to MKA audio file
            echo "# Audio #${TRACK_ID} : Extraction of ${TRACK_FORMAT} stream"
            [ -f "${FILE_TMP_MKA}" ] || mkvmerge -o "${FILE_TMP_MKA}" --no-video --audio-tracks "${TRACK_ID}" --no-subtitles --no-attachments --no-global-tags --no-chapters --no-track-tags --no-buttons "${TMP_ORIGINAL}"

            # convert WAV file to stereo
            echo "# Audio #${TRACK_ID} : Conversion to stereo WAV"
            ffmpeg -y -i "${FILE_TMP_MKA}" -ac 2 "${FILE_TMP_WAV}"

            # apply night mode correction
            echo "# Audio #${TRACK_ID} : Conversion to Midnight Mode"
            sox --temp "${TMP_DIR}" "${FILE_TMP_WAV}" "${FILE_DRC_WAV}" compand 0.0,1 6:-70,-50,-20 -6 -90 0.1

            # normalize audio track
            echo "# Audio #${TRACK_ID} : Normalization of Midnight Mode"
            sox --temp "${TMP_DIR}" --norm "${FILE_DRC_WAV}" "${FILE_NRM_WAV}"

            # convert WAV file to AAC
            echo "# Audio #${TRACK_ID} : Conversion of Midnight Mode to AAC (${RATE_DRC}k)"
            fdkaac -o "${FILE_DRC_AAC}" -b "${RATE_DRC}k" "${FILE_NRM_WAV}" 

            # gererate track options for current track
            ARR_PARAM_AUDIO=("${ARR_PARAM_AUDIO[@]}" "--default-track" "0:0"  "--sync" "0:${TRACK_DELAY}" "--language" "0:${TRACK_LANGUAGE}" "--track-name" "0:${TRACK_LANGUAGE} Night Mode" "${FILE_DRC_AAC}")

            # add current audio to the general track order list
            ARR_FILE=("${ARR_FILE[@]}" "${NEWTRACK_INDEX}:0")
            NEWTRACK_INDEX=$((NEWTRACK_INDEX+1))
        fi
    done

    # ----------------------------------------------------
    #   generate audio track arrays used for final merge
    # ----------------------------------------------------

    # if needed, generate list of AAC audio tracks
    LIST_AAC=$(echo "${ARR_AAC_ID[@]}" | tr " " ",")
    [ "$LIST_AAC" != "" ] && ARR_PARAM_AAC=("--audio-tracks" "${LIST_AAC}" "${ARR_PARAM_AAC[@]}") || ARR_PARAM_AAC=("--no-audio" )

    # generate list of ACC track index
    LIST_FILE=$(echo "${ARR_FILE[@]}" | tr " " ",")

    # ------------------------------------------
    #   if video cover, include in final merge
    # ------------------------------------------

    if [ -f "${FILE_COVER}" ]
    then
        echo "# ${FILE_NAME} - Addition of video cover"
        ARR_PARAM_COVER=("--attachment-description" "Movie cover" "--attachment-mime-type" "image/jpg" "--attachment-name" "cover.jpg" "--attach-file" "${FILE_COVER}") 
    fi

    # ---------------
    #   final merge
    # ---------------

    # generate final MKV including original file and transcoded tracks
    echo "# Generation of final MKV"
    mkvmerge --title "${FILE_NAME}" --track-order "${LIST_FILE}" "${ARR_PARAM_COVER[@]}" --output "${TMP_TARGET}" "${ARR_PARAM_AAC[@]}" --no-buttons --no-attachments "${TMP_ORIGINAL}" "${ARR_PARAM_AUDIO[@]}"

    # copy generated file to final file
    echo "# Backup of original MKV ..."
    [ "${FILE_EXT}" = "mkv" ] && gio move "${FILE_VIDEO}" "${FILE_DIR}/${FILE_NAME}-original.${FILE_EXT}"
    echo "# Copy of target file ..."
    gio copy "${TMP_TARGET}" "${FILE_MKV}" 
fi

) | zenity --window-icon=video --width=500 --title="Conversion to MKV with AAC audio" --progress --pulsate --auto-close &

# get zenity process and child proces which is parent of all running tasks 
PID_ZENITY=${!}
PID_CHILD=$(pgrep -o -P $$)

# loop to check that progress dialog has not been cancelled
while [ "$PID_ZENITY" != "" ]
do
    # after 1 second, get PID of running processes for the children
    sleep 1
    PID_TASKS=$(pgrep -d ' ' -P "${PID_CHILD}")

    # check if process is still running
    PID_ZENITY=$(ps h -o pid --pid ${PID_ZENITY} | xargs)
done

# if some running tasks are still there, kill them
[ "${PID_TASKS}" != "" ] && kill -9 ${PID_TASKS}

# remove temporary directory
rm -r "${TMP_DIR}"

You can install and test the script from command line :

Terminal
# mkdir --parents $HOME/.config
# wget -O $HOME/.config/video-convert2mkvaac.conf https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-convert2mkvaac.conf
# sudo wget -O /usr/local/bin/video-convert2mkvaac https://raw.githubusercontent.com/NicolasBernaerts/ubuntu-scripts/master/video/video-convert2mkvaac
# sudo chmod +x /usr/local/bin/video-convert2mkvaac

You are now ready to test it :

Terminal
# video-convert2mkvaac yourvideofile.mp4

If everything runs fine, you should get the 2 selection dialog boxes and end up with a brand new MKV file side to your original video.

3. Desktop Integration

It is now time to fully integrate this MKV/AAC transcoding tool in your desktop environment.

3.1. Menu declaration

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

/usr/share/applications/video-convert2mkvaac.desktop

It should be avaiable from Application / Sound & Video menu after next login.

3.2. Nautilus integration

You can also integrate this tool straight from Nautilus file manager. You'll then be able to access it from a right click menu after selecting file(s).

First thing is to install nautilus-actions extensions, which is not installed by default under Ubuntu.

Terminal
# sudo apt-get install nautilus-actions

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

~/.local/share/file-manager/actions/video-convert2mkvaac-action.desktop

This will make the transcoding tool accessible from the right menu on any video file whose mimetypes is matching the one declared in the .desktop file.

You will then be able to start the transcoding of any video file from a simple right click in Nautilus.

ubuntu mkvaac menu rightclick

To declare this Nautilus action, just run these commands :

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

4. Complete installation procedure

If you want to install all needed tools and scripts in one go, you can run an all-in-one installation script available from my Github repository.

This script has been written and tested on Ubuntu 14.04 LTS. It will handle whatever installation and configuration described earlier in this article.

Terminal

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

After next login, you should be able to generate a MKV/AAC video file from any multi-tracks 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