audiblefreedom 6.08 KB
Newer Older
John Wesorick's avatar
John Wesorick committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
#!/bin/bash
# audiblefreedom
# audiblefreedom is a simple Linux program that strips the DRM from Audible
# audiobooks, splits it into chapters, tags and names the files and converts
# them to mp3 format.
#
# REQUIREMENTS
# Requires mkvmerge, ffmpeg, lame
# if using Ubuntu 14.04, a ppa is required for ffmpeg
# sudo add-apt-repository ppa:mc3man/trusty-media
# sudo apt-get update
# sudo apt-get install mkvtoolnix ffmpeg lame
# 
# You must also use audible-activator
# (https://github.com/inAudible-NG/audible-activator/) to get your activation
# bytes (to decrypt the AAX files) and save them as a file called bytes.txt in
# the same dir as the script. Note, this will only decrypt AAX files purchased
# on this account.
#
# USAGE
# audiblefreedom AAXFILE [COVERJPG]
# 
# You can optionally specify a .jpg path either from your local machine or URL
# to use for the cover art.
#
# There does not appear to be an Audible player/downloader for Linux, so I use
# the Audible Android app to download the AAX file and copy it to my machine.
#
# Initial script from:
# https://www.reddit.com/r/linux/comments/5g841u/what_are_some_scripts_you_use_for_personal/daro100/
# heavily modified by John Wesorick
#
if [ -e "$PWD/bytes.txt" ]; then
    ABYTES=$(sed '1q;d' "$PWD/bytes.txt")
else
    echo "Activation bytes file (bytes.txt) is missing! Please use"
    echo "audible-activator (https://github.com/inAudible-NG/audible-activator/)"
    echo "to get your activation bytes and save them to a file called bytes.txt."
    exit 1
fi

# Verify that the necessary programs are installed
REQUIREDPROGRAMS=("ffmpeg" "lame" "mkvmerge")
for i in "${REQUIREDPROGRAMS[@]}"; do
    if ! type "$i" >/dev/null; then
        echo "Required program $i is missing! I cannot continue"
        # Check distro to see how to install requirements
        DISTRO=$(cat /etc/issue)
        if [[ "$DISTRO" == "Ubuntu"* ]]; then
            echo "Run the following command(s) to install all required programs"
            if [[ "$DISTRO" == *"14.04"* ]]; then
                echo "sudo add-apt-repository ppa:mc3man/trusty-media"
                echo "sudo apt-get update"
            fi
            echo "sudo apt-get install mkvtoolnix ffmpeg lame"
        fi
        exit 1
    fi
done
# Move into temporary work folder.
mkdir work
cd work

# Remove DRM from AAX file.
echo "Stripping DRM..."
ffmpeg -nostats -loglevel 0 -activation_bytes $ABYTES -i "../$1" \
    -vn -c:a copy "${1%.*}.m4a" ; 
BOOKTITLE=$(ffprobe -v quiet -show_format "${1%.*}.m4a" | grep "TAG:title" | cut -d"=" -f2)
AUTHOR=$(ffprobe -v quiet -show_format "${1%.*}.m4a" | grep "TAG:artist" | cut -d"=" -f2)
YEAR=$(ffprobe -v quiet -show_format "${1%.*}.m4a" | grep "TAG:date" | cut -d"=" -f2)
COMMENT=$(ffprobe -v quiet -show_format "${1%.*}.m4a" | grep "TAG:comment" | cut -d"=" -f2)
TOKENWORDS=("A" "An" "The")
# If a title begins with A, An, or The, we want to rename it so it sorts well
FSBOOKTITLE="$BOOKTITLE"
FSAUTHOR="$AUTHOR"
for i in "${TOKENWORDS[@]}"; do
    if [[ "$FSBOOKTITLE" == "$i "* ]]; then
        FSBOOKTITLE=$(echo $FSBOOKTITLE | perl -pe "s/^$i //")
        # If book has a subtitle, we want the token word to go right before it
        if [[ "$FSBOOKTITLE" == *": "* ]]; then
            FSBOOKTITLE=$(echo $FSBOOKTITLE | perl -pe "s/: /, $i: /")
            break  
        fi
        FSBOOKTITLE="$FSBOOKTITLE, $i"
        break
    fi
done
# Replace special characters in Book Title and Author Name with a - to make
# them file name safe. I'm not actually using the Author Name in the file
# name, but I figured it'd be nice to make it easy to use.
FSBOOKTITLE=$(echo $FSBOOKTITLE | perl -pe 's/[<>:"\/\\\|\?\*]/-/g')
FSAUTHOR=$(echo $FSAUTHOR | perl -pe 's/[<>:"\/\\\|\?\*]/-/g')

# Split stripped M4A file by chapters.
echo "Splitting by chapter..."
mkvmerge -o "${1%.*} .m4a" --split chapters:all "${1%.*}.m4a" 1> /dev/null

rm "${1%.*}.m4a"

# if album art is given as a second argument, grab it
if [ -n "$2" ]; then
    if [[ "$2" == "http"* ]]; then
        wget -q "$2" -O folder.jpg
    else
        mv "../$2" folder.jpg
    fi
fi

# Transcode to .mp3
TOTALTRACKS=$(ls -l *.m4a | wc -l)
TRACK=0

for f in *.m4a ;
do
    TRACK=$(($TRACK+1))
    echo "Transcoding track $TRACK of $TOTALTRACKS..."
    MP3FILE="${f//m4a/mp3}"
    TRACKTITLE="$(mkvinfo "$f" | grep 'ChapterString:' | cut -d":" -f2 | awk '{gsub(/^ +| +$/,"")} {print $0 }')"
    ffmpeg -nostats \
        -loglevel 0 \
        -i "$f" \
        -metadata album="$BOOKTITLE" \
        -metadata genre="Audiobook" \
        -metadata title="$TRACKTITLE" \
        -metadata artist="$AUTHOR" \
        -metadata album_artist="$AUTHOR" \
        -metadata date="$YEAR" \
        -metadata comment="$COMMENT" \
        -metadata track="$TRACK/$TOTALTRACKS" \
        -id3v2_version 3 \
        -codec:a libmp3lame \
        -qscale:a 3 \
        "$MP3FILE"
    # zero padding the track number as a string
    if [ $TOTALTRACKS -ge 100 ] ; then
        if [ $TRACK -le 99 ] ; then
            TRACKSTR="0$TRACK"
        elif [ $TRACK -le 9 ] ; then
            TRACKSTR="00$TRACK"
        else
            TRACKSTR=$TRACK
        fi
    else
        if [ $TRACK -le 9 ] ; then
            TRACKSTR="0$TRACK"
        else
            TRACKSTR=$TRACK
        fi
    fi
    
    # if album art exists, add it
    if [ -a "folder.jpg" ]; then
        # ffmpeg does not allow in-place editing, so create a temp file, then
        # delete the old one and rename.
        ffmpeg -nostats \
            -loglevel 0 \
            -i "$MP3FILE" \
            -i folder.jpg \
            -map 0:0 \
            -map 1:0 \
            -c copy \
            -id3v2_version 3 \
            -metadata:s:v title="Album cover" \
            -metadata:s:v comment="Cover (Front)" \
            out.mp3
        rm "$MP3FILE"
        mv out.mp3 "$MP3FILE"
    fi
    # rename .mp3's. Format: [email protected])TRACKTITLE.mp3
    mv "$MP3FILE" "$FSBOOKTITLE@$TRACKSTR)$TRACKTITLE.mp3"
done

# Move out of work folder.
mkdir "../$FSBOOKTITLE"
mv *.mp3 "../$FSBOOKTITLE" 
if [ -a folder.jpg ]; then
    mv folder.jpg "../$FSBOOKTITLE"
fi
cd ..

# Delete work folder.
echo "Cleaning up..."
rm -rf work

echo